On Fri, Mar 18, 2022 at 8:11 AM Chen Jiahao <chenjiahao16@xxxxxxxxxx> wrote: > > In __access_ok, TASK_SIZE_MAX is used to check if a memory access > is in user address space, but some cases may get omitted in compat > mode. > > For example, a 32-bit testcase calling pread64(fd, buf, -1, 1) > and running in x86-64 kernel, the obviously illegal size "-1" will > get ignored by __access_ok. Since from the kernel point of view, > 32-bit userspace 0xffffffff is within the limit of 64-bit > TASK_SIZE_MAX. > > Replacing the limit TASK_SIZE_MAX with TASK_SIZE in __access_ok > will fix the problem above. I don't see what problem this fixes, the choice of TASK_SIZE_MAX in __access_ok() is intentional, as this means we can use a compile-time constant as the limit, which produces better code. Any user pointer between COMPAT_TASK_SIZE and TASK_SIZE_MAX is not accessible by a user process but will not let user space access any kernel data either, which is the point of the check. In your example of using '-1' as the pointer, access_ok() returns true, so the kernel can go on to perform an unchecked __get_user() on __put_user() on 0xffffffffull, which causes page fault that is intercepted by the ex_table fixup. This should not result in any user visible difference, in both cases user process will see a -EFAULT return code from its system call. Are you able to come up with a test case that shows an observable difference in behavior? Arnd