Re: [PATCH 2/9] ARM: traps: use get_kernel_nofault instead of set_fs()

From: Russell King - ARM Linux admin
Date: Fri Sep 18 2020 - 03:42:10 EST


On Thu, Sep 17, 2020 at 07:29:37PM +0200, Arnd Bergmann wrote:
> On Tue, Sep 8, 2020 at 8:15 AM Christoph Hellwig <hch@xxxxxx> wrote:
> >
> > > +static void dump_mem(const char *, const char *, unsigned long, unsigned long, bool kernel_mode);
> >
> > This adds a pointlessly long line.
>
> Fixed.
>
> > And looking at the code I don't see why the argument is even needed.
> >
> > dump_mem() currently does an unconditional set_fs(KERNEL_DS), so it
> > should always use get_kernel_nofault.
>
> I had looked at
>
> if (!user_mode(regs) || in_interrupt()) {
> dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
> THREAD_SIZE + (unsigned
> long)task_stack_page(tsk), kernel_mode);
>
> which told me that there should be at least some code path ending up in
> __die() that has in_interrupt() set but comes from user mode.
>
> In this case, the memory to print would be a user pointer and cannot be
> accessed by get_kernel_nofault() (but could be accessed with
> "set_fs(KERNEL_DS); __get_user()").
>
> I looked through the history now and the only code path I could
> find that would arrive here this way is from bad_mode(), indicating
> that there is probably a hardware bug or the contents of *regs are
> corrupted.

Yes, that's correct. It isn't something entirely theoretical, although
we never see it now, it used to happen in the distant past due to saved
regs corruption. If bad_mode() ever gets called, all bets are off and
we're irrecoverably crashing.

Note that in that case, while user_mode(regs) may return true or false,
regs->ARM_sp and regs->ARM_lr are always the SVC mode stack and return
address after regs has been stacked, and not the expected values for
the parent context (which we have most likely long since destroyed.)

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!