提交 47f89c10 编写于 作者: D Dmitry Osipenko 提交者: Thierry Reding

gpu: host1x: Do not leak BO's phys address to userspace

Perform gathers coping before patching them, so that original gathers are
left untouched. That's not as bad as leaking kernel addresses, but still
doesn't feel right.
Signed-off-by: NDmitry Osipenko <digetx@gmail.com>
Reviewed-by: NMikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: NThierry Reding <treding@nvidia.com>
上级 e5855aa3
...@@ -137,8 +137,9 @@ static void host1x_syncpt_patch_offset(struct host1x_syncpt *sp, ...@@ -137,8 +137,9 @@ static void host1x_syncpt_patch_offset(struct host1x_syncpt *sp,
* avoid a wrap condition in the HW). * avoid a wrap condition in the HW).
*/ */
static int do_waitchks(struct host1x_job *job, struct host1x *host, 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; int i;
/* compare syncpt vs wait threshold */ /* compare syncpt vs wait threshold */
...@@ -165,7 +166,8 @@ static int do_waitchks(struct host1x_job *job, struct host1x *host, ...@@ -165,7 +166,8 @@ static int do_waitchks(struct host1x_job *job, struct host1x *host,
wait->syncpt_id, sp->name, wait->thresh, wait->syncpt_id, sp->name, wait->thresh,
host1x_syncpt_read_min(sp)); 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; wait->bo = NULL;
...@@ -269,11 +271,12 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) ...@@ -269,11 +271,12 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
return err; 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; int i = 0;
u32 last_page = ~0; u32 last_page = ~0;
void *cmdbuf_page_addr = NULL; void *cmdbuf_page_addr = NULL;
struct host1x_bo *cmdbuf = g->bo;
/* pin & patch the relocs for one gather */ /* pin & patch the relocs for one gather */
for (i = 0; i < job->num_relocs; i++) { for (i = 0; i < job->num_relocs; i++) {
...@@ -286,6 +289,13 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) ...@@ -286,6 +289,13 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
if (cmdbuf != reloc->cmdbuf.bo) if (cmdbuf != reloc->cmdbuf.bo)
continue; continue;
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
target = (u32 *)job->gather_copy_mapped +
reloc->cmdbuf.offset / sizeof(u32) +
g->offset / sizeof(u32);
goto patch_reloc;
}
if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) { if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
if (cmdbuf_page_addr) if (cmdbuf_page_addr)
host1x_bo_kunmap(cmdbuf, last_page, host1x_bo_kunmap(cmdbuf, last_page,
...@@ -302,6 +312,7 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) ...@@ -302,6 +312,7 @@ static int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
} }
target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK); target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
patch_reloc:
*target = reloc_addr; *target = reloc_addr;
} }
...@@ -573,6 +584,12 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) ...@@ -573,6 +584,12 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
if (err) if (err)
goto out; goto out;
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
err = copy_gathers(job, dev);
if (err)
goto out;
}
/* patch gathers */ /* patch gathers */
for (i = 0; i < job->num_gathers; i++) { for (i = 0; i < job->num_gathers; i++) {
struct host1x_job_gather *g = &job->gathers[i]; struct host1x_job_gather *g = &job->gathers[i];
...@@ -581,7 +598,9 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) ...@@ -581,7 +598,9 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
if (g->handled) if (g->handled)
continue; continue;
g->base = job->gather_addr_phys[i]; /* copy_gathers() sets gathers base if firewall is enabled */
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
g->base = job->gather_addr_phys[i];
for (j = i + 1; j < job->num_gathers; j++) { for (j = i + 1; j < job->num_gathers; j++) {
if (job->gathers[j].bo == g->bo) { if (job->gathers[j].bo == g->bo) {
...@@ -590,19 +609,15 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) ...@@ -590,19 +609,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) if (err)
goto out; break;
err = do_waitchks(job, host, g->bo); err = do_waitchks(job, host, g);
if (err) if (err)
goto out; break;
} }
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
goto out;
err = copy_gathers(job, dev);
out: out:
if (err) if (err)
host1x_job_unpin(job); host1x_job_unpin(job);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册