This is an archive of emails on LKML, where Alan Cox acknowledges the bug. --- Alan Cox wrote: >On Iau, 2004-10-28 at 10:48, Andrew Morton wrote: > >>is safe. We know that the address is in the 0x00000000-0xbfffffff range by >>the time we call __put_user(). And if the page at *addr it not writeable >>the kernel will take a fault. >> >>So I see no hole. But I wouldn't have coded it that way... > > >On x86 maybe. I think he's right in the sense that we may have a non x86 >platform that this is not safe on. > --- Sorav Bansal wrote: >>Nope. The only significant difference between copy_from_user() and >>__put_user() here is that copy_from_user() checks that the address is not >>in the 0xc0000000-0xffffffff range. __put_user() skips that check. > > >This is true for modern x86 architectures. > >For some older 386's, where Write-Protect does not work okay, there is a >difference between put_user() and copy_from_user(). put_user() performs an >extra check called verify_write() in addition to checking the address >range. Hence, the following code may be unsafe when running on those >machines. > >>So >> >> if (copy_from_user(kaddr, addr, n)) >> fail(); >> __put_user(42, addr); >> >>is safe. We know that the address is in the 0x00000000-0xbfffffff range by >>the time we call __put_user(). And if the page at *addr it not writeable >>the kernel will take a fault. > > >In older 386's, the kernel will NOT take a fault and write to the >write-protected region. > >But then, maybe 386 is too old to worry about :-) > --- Andrew Morton wrote: >Sorav Bansal wrote: > >>Older x86 architectures (386 and before) allow the kernel to write to any >> user location regardless of the write-protect bits. >> >> Hence, with this bug, a user program could write to the write-protected >> region of its address space by calling the sys_poll system call and >> setting the address and data values appropriately. > > >Nope. The only significant difference between copy_from_user() and >__put_user() here is that copy_from_user() checks that the address is not >in the 0xc0000000-0xffffffff range. __put_user() skips that check. > >So > > if (copy_from_user(kaddr, addr, n)) > fail(); > __put_user(42, addr); > >is safe. We know that the address is in the 0x00000000-0xbfffffff range by >the time we call __put_user(). And if the page at *addr it not writeable >the kernel will take a fault. > >So I see no hole. But I wouldn't have coded it that way... > --- Sorav Bansal wrote: > > Package: linux-kernel-src > Version: 2.4.27 > > Description: User/Kernel pointer bug/security holl > in sys_poll > > I think, there is a potential bug/security hole in > the sys_poll system > call. > > In sys_poll, the user pointer ufds (first arg to > sys_poll) goes through > copy_from_user. Then __put_user is called on > &ufds->revents. > > Since copy_from_user is a read access and __put_user > is a write access, > the first call does not verify write-access to ufds. > This can be exploited > by a malicious user on a 386 machine (where > write-protection in > kernel mode is not enabled .i.e. > CONFIG_X86_WP_WORKS_OK is undef). > > It seems that this bug can be corrected by replacing > the two __put_user > calls in sys_poll by put_user. I am using the latest > kernel from > kernel.org .i.e. linux-2.4.27 > > thanks, > Sorav