[PATCH 13/22] gpu: host1x: Do not leak BO's phys address to userspace
Mikko Perttunen
cyndis at kapsi.fi
Tue Jun 13 17:31:45 UTC 2017
On 05/23/2017 03:14 AM, Dmitry Osipenko wrote:
> Do gathers coping before patching them, so the original gathers are left
> untouched. That's not as bad as leaking a kernel addresses, but still
> doesn't feel right.
>
> Signed-off-by: Dmitry Osipenko <digetx at gmail.com>
> ---
> drivers/gpu/host1x/job.c | 44 ++++++++++++++++++++++++++++++--------------
> 1 file changed, 30 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
> index 14f3f957ffab..190353944d23 100644
> --- a/drivers/gpu/host1x/job.c
> +++ b/drivers/gpu/host1x/job.c
> @@ -137,8 +137,9 @@ static void host1x_syncpt_patch_offset(struct host1x_syncpt *sp,
> * avoid a wrap condition in the HW).
> */
> static int do_waitchks(struct host1x_job *job, struct host1x *host,
> - struct host1x_bo *patch)
> + struct host1x_job_gather *g)
> {
> + struct host1x_bo *patch = g->bo;
> int i;
>
> /* compare syncpt vs wait threshold */
> @@ -165,7 +166,8 @@ static int do_waitchks(struct host1x_job *job, struct host1x *host,
> wait->syncpt_id, sp->name, wait->thresh,
> host1x_syncpt_read_min(sp));
>
> - host1x_syncpt_patch_offset(sp, patch, wait->offset);
> + host1x_syncpt_patch_offset(sp, patch,
> + g->offset + wait->offset);
> }
>
> wait->bo = NULL;
> @@ -269,11 +271,12 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
> return err;
> }
>
> -static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
> +static int do_relocs(struct host1x_job *job, struct host1x_job_gather *g)
> {
> int i = 0;
> u32 last_page = ~0;
> void *cmdbuf_page_addr = NULL;
> + struct host1x_bo *cmdbuf = g->bo;
>
> /* pin & patch the relocs for one gather */
> for (i = 0; i < job->num_relocs; i++) {
> @@ -286,7 +289,8 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
> if (cmdbuf != reloc->cmdbuf.bo)
> continue;
>
> - if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
> + if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) &&
> + last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
> if (cmdbuf_page_addr)
> host1x_bo_kunmap(cmdbuf, last_page,
> cmdbuf_page_addr);
> @@ -301,11 +305,20 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
> }
> }
>
> + if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
> + cmdbuf_page_addr = job->gather_copy_mapped;
> + cmdbuf_page_addr += g->offset;
> + }
> +
> target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
> +
> + if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
> + target += (reloc->cmdbuf.offset & PAGE_MASK) >> 2;
> +
> *target = reloc_addr;
I think this logic would be cleaner like ..
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
target = job->gather_copy_mapped + g->offset + reloc->cmdbuf.offset;
...
} else {
if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
...
}
target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
}
*target = reloc_addr
> }
>
> - if (cmdbuf_page_addr)
> + if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && cmdbuf_page_addr)
> host1x_bo_kunmap(cmdbuf, last_page, cmdbuf_page_addr);
>
> return 0;
> @@ -573,6 +586,12 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
> if (err)
> goto out;
>
> + if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
> + err = copy_gathers(job, dev);
> + if (err)
> + goto out;
> + }
> +
> /* patch gathers */
> for (i = 0; i < job->num_gathers; i++) {
> struct host1x_job_gather *g = &job->gathers[i];
> @@ -581,7 +600,8 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
> if (g->handled)
> continue;
>
> - g->base = job->gather_addr_phys[i];
> + if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
> + g->base = job->gather_addr_phys[i];
Perhaps add a comment here like "copy_gathers sets base when firewall is
enabled"
>
> for (j = i + 1; j < job->num_gathers; j++) {
> if (job->gathers[j].bo == g->bo) {
> @@ -590,19 +610,15 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
> }
> }
>
> - err = do_relocs(job, g->bo);
> + err = do_relocs(job, g);
> if (err)
> - goto out;
> + break;
>
> - err = do_waitchks(job, host, g->bo);
> + err = do_waitchks(job, host, g);
> if (err)
> - goto out;
> + break;
> }
>
> - if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
> - goto out;
> -
> - err = copy_gathers(job, dev);
> out:
> if (err)
> host1x_job_unpin(job);
>
More information about the dri-devel
mailing list