On Sun, Oct 06, 2019 at 08:25:05PM -0700, Linus Torvalds wrote:
> 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 ;)
Testing the above on an XP1000 running 5.4.0-rc2 built for Alpha
DP264 reveals no problems. No Oops reported. Unaligned access
count goes up by three in /proc/cpuinfo as expected. But
interestingly the kernel unaligned access count is quite high
(14000 or so) on this kernel after boot whereas with the 5.2.y
kernel I was recently running it was zero.
Cheers,
Michael.