Re: objtool clac/stac handling change..

From: Linus Torvalds
Date: Thu Jul 02 2020 - 16:13:42 EST


On Thu, Jul 2, 2020 at 8:13 AM Christophe Leroy
<christophe.leroy@xxxxxxxxxx> wrote:
>
> Isn't it something easy to do in bad_page_fault() ?

Can't the user access functions take any other faults on ppc?

On x86-64, we have the "address is non-canonical" case which doesn't
take a page fault at all, but takes a general protection fault
instead.

But note that depending on how you nest and save/restore the state,
things can be very subtle.

For example, what can happen is:

(a) user_access_begin()..

(b) we take a normal interrupt

(c) the interrupt code does something that has an exception handling
case entirely unrelated to the user access (on x86, it might be the
"unsafe_msr' logic, for example.

(d) we take that exception, do "fixup_exception()" for whatever that
interrupt did.

(e) we return from that exception to the fixed up state

(d) we return from the interrupt

(e) we should still have user accesses enabled.

NOTE! on x86, we can have "all fixup_exceptions() will clear AC in the
exception pt_regs", because AC is part of rflags which is saved on
(and cleared for the duration of) all interrupt and exceptions.

So what happens is that on x86 all of (b)-(d) will run with AC clear
and no user accesses allowed, and (e) will have user accesses enabled
again, because the "fixup_exception()" at (d) only affected the state
of the interrupt hander (which already had AC clear anyway).

But I don't think exceptions and interrupts save/restore the user
access state on powerpc, do they?

So on powerpc you do need to be more careful. You would only need to
disable user access on exceptions that happen _on_ user accesses.

The easiest way to do that is to do what x86 does: different
exceptions have different handlers. It's not what we did originally,
but it's been useful.

Hmm.

And again, on x86, this all works fine because of how exceptions
save/restore the user_access state and it all nests fine. But I'm
starting to wonder how the nesting works AT ALL for powerpc?

Because that nesting happens even without

IOW, even aside from this whole thing, what happens on PPC, when you have

(a) user_access_begin();
- profile NMI or interrupt happens
- it wants to do user stack tracing so does
pagefault_disable();
(b) get_user();
pagefault_enable();
- profile NMI/interrupt returns
(c) user accesss should work here!

even if the "get_user()" in (b) would have done a
"user_access_begin/end" pair, and regardless of whether (b) might have
triggered a "fixup_exception()", and whether that fixup_exception()
then did the user_access_end().

On x86, this is all ok exactly because of how we only have the AC bit,
and it nests very naturally with any exception handling.

Is the ppc code nesting-safe? Particularly since it has that whole
range-handling?

Linus