[PATCH 13/22] gpu: host1x: Do not leak BO's phys address to userspace

Dmitry Osipenko digetx at gmail.com
Tue Jun 13 19:56:49 UTC 2017


On 13.06.2017 22:03, Mikko Perttunen wrote:
> 
> 
> On 06/13/2017 09:21 PM, Dmitry Osipenko wrote:
>> On 13.06.2017 20:31, Mikko Perttunen wrote:
>>> 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
>>>
>>
>> What about this variant?
>>
>> -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,6 +289,12 @@ static int do_relocs(struct host1x_job *job, struct
>> host1x_bo *cmdbuf)
>>           if (cmdbuf != reloc->cmdbuf.bo)
>>               continue;
>>
>> +        if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
>> +            cmdbuf_page_addr = job->gather_copy_mapped + g->offset;
> 
> This no longer represents the address of a page, so I think it would be better
> to just assign the final value to target.
> 
>> +            target = cmdbuf_page_addr + reloc->cmdbuf.offset;
>> +            goto patch_reloc;
>> +        }
>> +
>>           if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
>>               if (cmdbuf_page_addr)
>>                   host1x_bo_kunmap(cmdbuf, last_page,
>> @@ -302,10 +311,11 @@ static int do_relocs(struct host1x_job *job, struct
>> host1x_bo *cmdbuf)
>>           }
>>
>>           target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
>> +patch_reloc:
>>           *target = reloc_addr;
>>       }
>>
>> -    if (cmdbuf_page_addr)
>> +    if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && cmdbuf_page_addr)
> 
> And then we wouldn't need the IS_ENABLED here
> 
>>           host1x_bo_kunmap(cmdbuf, last_page, cmdbuf_page_addr);
>>
>>       return 0;
>>
> with that change, looks good to me
> 

Thank you very much for the suggestion.

>>>>        }
>>>>    -    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"
>>>
>>
>> Okay, added. Thank you for the review comments!
>>


-- 
Dmitry


More information about the dri-devel mailing list