Unaligned user pointer issues..

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



So Guenther Roeck reported that my fancy readdir() user access
optimization broke alpha and sparc64 boot for him.

(It really improves things on x86 - I swear! The cost of telling the
CPU over and over again to "please allow user space accesses" is
horrendously high, so doing the whole "user_access_begin()/end() just
_once_ per dirent is a big deal).

It turns out that it's broken on at least alpha because it does that
filename copy to user space by hand, and the "linux_filldir64"
structure is set up so that the name part is basically never aligned.
So when it does the word copies, it does them as unaligned
"put_user()" invocations.

I'll fix it, never fear, since it's clearly a horrible performance
pessimization on architectures that don't deal unaligned accesses
well.

However, at least on alpha, it's not just that unaligned user accesses
were slow, they didn't actually _work_.

And that's a problem.

Because they are easy to trigger from user space even without any new
readdir code.

This trivial program causes a kernel oops on alpha:

  #define _GNU_SOURCE
  #include <unistd.h>
  #include <sys/mman.h>

  int main(int argc, char **argv)
  {
        void *mymap;
        uid_t *bad_ptr = (void *) 0x01;

        /* Create unpopulated memory area */
        mymap = mmap(NULL, 16384,
                PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANONYMOUS,
                -1, 0);

        /* Unaligned uidpointer in that memory area */
        bad_ptr = mymap+1;

        /* Make the kernel do put_user() on it */
        return getresuid(bad_ptr, bad_ptr+1, bad_ptr+2);
  }

because getresuid() does "put_user()" on that unaligned pointer, and
it looks like something goes badly sideways when it first takes the
unaligned trap, and then the unaligned trap handler gets an exception
on the emulation code.

I'm not sure what the alpha bug is (I looked at the code just long
enough to see that it _tries_ to do the exception handling), but the
fact that apparently I broke at least sparc64 too makes me suspect
that other architectures have this issue too.

So hey, can I ask architecture maintainers to try the above trivial
program and see how it works (or doesn't)?

On alpha, when Guenther tried my silly test-program, he reported:

  # ./mmtest
  Unable to handle kernel paging request at virtual address 0000000000000004
  mmtest(75): Oops -1
  pc = [<0000000000000004>]  ra = [<fffffc0000311584>]  ps = 0000    Not tainted
  pc is at 0x4
  ra is at entSys+0xa4/0xc0
  v0 = fffffffffffffff2  t0 = 0000000000000000  t1 = 0000000000000000
  ...

which is not what is supposed to happen ;)

            Linus



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux