Message ID | 20220216131332.1489939-15-arnd@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | clean up asm/uaccess.h, kill set_fs for good | expand |
On Wed, Feb 16, 2022 at 02:13:28PM +0100, Arnd Bergmann wrote: > From: Arnd Bergmann <arnd@arndb.de> > > test_kernel_ptr() uses access_ok() to figure out if a given address > points to user space instead of kernel space. However on architectures > that set CONFIG_ALTERNATE_USER_ADDRESS_SPACE, a pointer can be valid > for both, and the check always fails because access_ok() returns true. > > Make the check for user space pointers conditional on the type of > address space layout. What is this code even trying to do? It looks extremly broken.
On Fri, Feb 18, 2022 at 7:35 AM Christoph Hellwig <hch@lst.de> wrote: > > On Wed, Feb 16, 2022 at 02:13:28PM +0100, Arnd Bergmann wrote: > > From: Arnd Bergmann <arnd@arndb.de> > > > > test_kernel_ptr() uses access_ok() to figure out if a given address > > points to user space instead of kernel space. However on architectures > > that set CONFIG_ALTERNATE_USER_ADDRESS_SPACE, a pointer can be valid > > for both, and the check always fails because access_ok() returns true. > > > > Make the check for user space pointers conditional on the type of > > address space layout. > > What is this code even trying to do? It looks extremly broken. As I understand it, this is only meant for debugging, and the module contains intentionally broken lock usage to test whether the watchdog and lockup detection in the kernel is able to find them. I did not try that hard to understand how it works though. Arnd
diff --git a/lib/test_lockup.c b/lib/test_lockup.c index 6a0f329a794a..c3fd87d6c2dd 100644 --- a/lib/test_lockup.c +++ b/lib/test_lockup.c @@ -417,9 +417,14 @@ static bool test_kernel_ptr(unsigned long addr, int size) return false; /* should be at least readable kernel address */ - if (access_ok((void __user *)ptr, 1) || - access_ok((void __user *)ptr + size - 1, 1) || - get_kernel_nofault(buf, ptr) || + if (!IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) && + (access_ok((void __user *)ptr, 1) || + access_ok((void __user *)ptr + size - 1, 1))) { + pr_err("user space ptr invalid in kernel: %#lx\n", addr); + return true; + } + + if (get_kernel_nofault(buf, ptr) || get_kernel_nofault(buf, ptr + size - 1)) { pr_err("invalid kernel ptr: %#lx\n", addr); return true;