RE: [PATCH v4 3/4] x86/uaccess: Use pointer masking to limit uaccess speculation

From: David Laight
Date: Thu May 06 2021 - 04:36:24 EST


From: Andy Lutomirski
> Sent: 05 May 2021 17:55
...
> Is there an equally efficient sequence that squishes the pointer value
> to something noncanonical or something like -1 instead of 0? I'm not
> sure this matters, but it opens up the possibility of combining the
> access_ok check with the masking without any branches at all.

Are you thinking of using:
uaddr = access_ok(uaddr, size)
and having the output value being one that is guaranteed
to fault when (a little later on) used to access user memory?

As well as the problem of finding a suitable invalid address
in 32bit architectures there can be issues if the code accesses
(uaddr + big_offset) since that could be outside the invalid
address window.

We are back to the fact that if we know the accesses are
sequential (or a single access) then it can usually be
arranged for them to fault without an explicit size check.

This could mean you have:
if (access_ok_mask(&uaddr, size))
return -EFAULT;
that never actually returns EFAULT on some architectures
when size is a small compile-time constant.

If you don't need to check the size then you'd need
something like:
mov uaddr, reg
add #-TASK_SIZE_MAX, reg // sets carry for bad addresses
sbb reg, reg // -1 for bad addresses
or reg, uaddr
That converts addresses above TASK_SIZE_MASK to -1.
Non-byte accesses will fault on all x86 cpu.
For x64 (and some other 64bit) you can clear the top few
bits to get an invalid address.

So probably ok for get_user() and copy_from_user() (etc)
but not as a more general check.

David.

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)