Re: access_ok macor

From: Ralf Baechle
Date: Wed Jul 15 2009 - 08:05:25 EST


On Wed, Jul 15, 2009 at 12:14:52PM +0200, Arnd Bergmann wrote:

> On Wednesday 15 July 2009, John Williams wrote:
> > On Wed, Jul 15, 2009 at 2:43 AM, Arnd Bergmann <arnd@xxxxxxxx> wrote:
> > > The solution then is to handle fixups from the unaligned exception handler
> > > if you come from the kernel. That should fix the three text cases.
> > >
> > > I don't fully understand your exception handling there, but I think you
> > > also need to add code checking for __range_ok() to your unaligned handler,
> > > to prevent malicious user space code from accessing the kernel through
> > > unaligned pointers.
> >
> >
> > Just to try to clarify - are there any alignment rules in the ABI on
> > user-space pointers (which end up going to get/put_user)?
>
> The kernel normally expects aligned input from user space, but I guess
> it can't hurt to handle it anyway. arch/mips/kernel/alignment.c seems
> to handle that case. Maybe Ralf can give some more insight.

It's arch/arm/mm/alignment.c rsp. arch/mips/kernel/unaliged.c.

> > It seems the failure path is like this:
> >
> > 1. userspace passes unaligned pointer
> > 2. get_user attempts to access
> > 3. CPU raises unaligned exception (if only it would raise the segfault as
> > higher priority, before the unaligned!)
> > 4. unaligned exception handler attempts to simulate the unaligned access
> > with multiple partial read/write ops
> > 5. CPU raises MMU exception on the read/write by the unaligned handler
> > 6. kernel segfault handler looks up faulting address, it is in the unaligned
> > exception handler, which has no fixup.
> > 7. no fixup -> failure
>
> Right.
>
> > So, I suppose the question is - where in the sequence is the true failure?
>
> I think in step 4. AFIACT, the kernel must do a number of checks on accesses
> to random pointers.

Yes; but the checks that unaligned.c does on MIPS are no different from
any other get_user(), that is it ensures that the entire 8/16/32/64-bit
access is in userspace. That's done using access_ok().

> > Clearly LTP thinks it's ok to pass unaligned pointers to the kernel,
> > suggesting (1) is fine - thus my question about alignment rules in the ABI.
>
> No, LTP thinks it should get a -EFAULT error code for that access. It does
> specify whether it expects this because of an unaligned address or because
> of an invalid page.
>
> > Do we need fixups on the unaligned handler itself? This will be ugly ugly
> > ugly.
>
> That's what ARM does. You don't have to do it from assembly though,
> implementing it in C is probably easier.

The MIPS psABI of which the Linux/MIPS ABI is sort of derived doesn't
specify any alignment-specific behaviour for syscalls. That is they're not
treated any different than any random piece of library code. I don't
know of any other standards documents (POSIX, single UNIX etc.) that
would have anything relevant either.

There are several historic precedents for why Linux handles miss-alignment
this way:

o The networking stack where some cards may align the header in memory
such that IP addresses are always on an address that is aligned to a
16-bit but not a 32-bit boundary. The tulip cards do that for example.
It was considered a better solution to emulate the access or copy the
entire rx packet before further processing than hacking up the
networking stack to handle with ill-designed hardware.

o Another in-kernel case was the MS-DOS partition table parsing.

o The were also a bunch of historic Linux applications originally written
for x86 which were relativly hard to port, so generally handling
exceptions, was the by far easiest thing to do and probably for most
architectures where this is relevant it's the easiest to handle all
miss-alignment cases, not just selectively userland and maybe IP and
MS-DOS partition table parsing.

We've moved on. Handling miss-alignment is no longer a very relavent part
of the syscall interface. So I think for the definition of the Linux
ABI this should just be left as implementation defined behaviour but
whatever an architecture does, it should be done consistently for all
system interfaces.

Ralf
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/