[PATCH v5] ARM: vDSO gettimeofday using generic timer architecture

Kees Cook keescook at google.com
Fri Mar 28 14:42:10 EDT 2014


On Thu, Mar 27, 2014 at 5:20 PM, Nathan Lynch <Nathan_Lynch at mentor.com> wrote:
> On 03/27/2014 06:06 PM, Kees Cook wrote:
>> On Mon, Mar 24, 2014 at 2:17 PM, Nathan Lynch <nathan_lynch at mentor.com> wrote:
>>> +
>>> +/* assumes mmap_sem is write-locked */
>>> +void arm_install_vdso(struct mm_struct *mm)
>>> +{
>>> +       unsigned long vdso_base;
>>> +       int ret;
>>> +
>>> +       mm->context.vdso = ~0UL;
>>> +
>>> +       if (vdso_pagelist == NULL)
>>> +               return;
>>> +
>>> +       vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
>>
>> While get_unmapped_area() should be returning an address that has been
>> base-offset randomized, I notice that x86 actually moves its vdso to a
>> random location near the stack instead (see vdso_addr() in
>> arch/x86/vdso/vma.c), in theory to avoid a hole in memory and to
>> separately randomize the vdso separately from heap and stack. I think
>> a similar thing be a benefit on ARM too.
>
> OK, I'll look into this.  Perhaps a similar treatment for the sigpage?

Oh, yeah. Unless there's a reason not too, it would be nice, yes.

> I notice on my systems (OMAP5 and i.MX6) that vdso, sigpage, and ld.so
> are always mapped consecutively:
>
> # grep -A2 vdso /proc/self/maps
> b6f44000-b6f46000 r-xp 00000000 00:00 0          [vdso]
> b6f46000-b6f47000 r-xp 00000000 00:00 0          [sigpage]
> b6f47000-b6f48000 r--p 00016000 00:01 1254       /lib/ld-2.19.90.so
>
> but I wonder if that's due to starved entropy pools, or is the VM
> already trying to prevent holes?

Right, this is because (I think) they're all using un-hinted
get_unmapped_area(), which allocates consecutively. The base address
is randomized, so each process should have a different starting
address for the start of the range used to fulfill get_unmapped_area()
calls.

>
>
>>> +       if (IS_ERR_VALUE(vdso_base)) {
>>> +               pr_notice_once("%s: get_unapped_area failed (%ld)\n",
>>> +                              __func__, (long)vdso_base);
>>> +               return;
>>> +       }
>>> +
>>> +       /*
>>> +        * Put vDSO base into mm struct before calling
>>> +        * install_special_mapping so the perf counter mmap tracking
>>> +        * code will recognise it as a vDSO.
>>> +        */
>>> +       mm->context.vdso = vdso_base;
>>> +
>>> +       ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
>>> +                                     VM_READ|VM_EXEC|
>>> +                                     VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
>>> +                                     vdso_pagelist);
>>
>> Why is this given VM_MAYWRITE? (I would ask the same about x86's
>> implementation too.)
>
> For setting breakpoints in the text area.  FWIW powerpc's
> arch_setup_additional_pages has this comment:
>
> /*
>  * our vma flags don't have VM_WRITE so by default, the process isn't
>  * allowed to write those pages.
>  * gdb can break that with ptrace interface, and thus trigger COW on
>  * those pages but it's then your responsibility to never do that on
>  * the "data" page of the vDSO or you'll stop getting kernel updates
>  * and your nice userland gettimeofday will be totally dead.
>  * It's fine to use that for setting breakpoints in the vDSO code
>  * pages though.
>  */
> rc = install_special_mapping(mm, vdso_base, vdso_pages << PAGE_SHIFT,
>                              VM_READ|VM_EXEC|
>                              VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
>                              vdso_pagelist);

Ah-ha, thanks. As long as I'm asking dumb questions about vm
internals... where is the COW flag for these pages stored? Nothing
jumped out at me when I was reading install_special_mapping.

Thanks!

-Kees

-- 
Kees Cook
Chrome OS Security



More information about the linux-arm-kernel mailing list