[PATCH 04/14] x86: use more conventional access_ok() definition
Linus Torvalds
torvalds at linux-foundation.org
Mon Feb 14 12:24:13 PST 2022
On Mon, Feb 14, 2022 at 12:01 PM Linus Torvalds
<torvalds at linux-foundation.org> wrote:
>
> x86-64 has always(*) used TASK_SIZE_MAX for access_ok(), and the
> get_user() assembler implementation does the same.
Side note: we could just check the sign bit instead, and avoid big
constants that way.
Right now we actually have this complexity in the x86-64 user access code:
#ifdef CONFIG_X86_5LEVEL
#define LOAD_TASK_SIZE_MINUS_N(n) \
ALTERNATIVE __stringify(mov $((1 << 47) - 4096 - (n)),%rdx), \
__stringify(mov $((1 << 56) - 4096 - (n)),%rdx),
X86_FEATURE_LA57
#else
#define LOAD_TASK_SIZE_MINUS_N(n) \
mov $(TASK_SIZE_MAX - (n)),%_ASM_DX
#endif
just because the code tries to get that TASK_SIZE_MAX boundary just right.
And getting that boundary just right is important on 32-bit x86, but
it's *much* less important on x86-64.
There's still a (weak) reason to do it even for 64-bit code: page
faults outside the valid user space range don't actually cause a #PF
fault - they cause #GP - and then we have the #GP handler warn about
"this address hasn't been checked".
Which is nice and useful for doing syzbot kind of randomization loads
(ie user accesses that didn't go through access_ok() will stand out
nicely), but maybe it's not worth this. syzbot would be fine with only
the "sign bit set" case warning for the same thing.
So on x86-64, we could just check the sign of the address instead, and
simplify and shrink those get/put_user() code sequences (but
array_index_mask_nospec() currently uses the carry flag computation
too, so we'd have to change that part as well, maybe not worth it).
Linus
More information about the linux-riscv
mailing list