Re: Strange EFAULT on mips64el returned by syscall when another thread is forking

From: Linus Torvalds
Date: Wed Jan 24 2024 - 17:11:26 EST


On Wed, 24 Jan 2024 at 13:54, Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
>
>
> And I think the "fails with any integer in [1, 8)" is because the MIPS
> "copy_from_user()" code is likely doing something special for those
> small copies.

Lcopy_bytes_checklen\@: does COPY_BYTE(0) for the first access, which is

#define COPY_BYTE(N) \
LOADB(t0, N(src), .Ll_exc\@); \
SUB len, len, 1; \
beqz len, .Ldone\@; \
STOREB(t0, N(dst), .Ls_exc_p1\@)

so yeah, for 'copy_to_user()" (which is what that "read (fd, buf, 7)"
will do, we have that user space write ("STOREB()") in the branch
delay slot of the length test.

So that matches.

And it only fails when

(a) you're unlucky, and that stack buffer

char buf[16] = {};

happens to be just under the last page that has been accessed, so
you get a page fault

(b) you hit a mmap_sem already being locked, presumably because
another thread is doing that fork().

Anyway, I'm pretty sure this is the bug, now some MIPS person just
needs to fix the MIPS version of "instruction_pointer()" to do what
"exception_epc()" already does.

Linus