[RFC PATCH 0/2] ARM: Fix unparseable signal frame with CONFIG_IWMMXT

Dave Martin Dave.Martin at arm.com
Tue Jun 27 10:15:31 PDT 2017


On Mon, Jun 26, 2017 at 07:12:32PM +0100, Russell King - ARM Linux wrote:
> On Mon, Jun 26, 2017 at 05:36:39PM +0100, Dave Martin wrote:
> > On Mon, Jun 26, 2017 at 03:40:01PM +0100, Russell King - ARM Linux wrote:
> > > I'd hope that the kernel implementation is not used as an example - it
> > > most certainly is not an example, as it does no parsing of the data
> > > structures.  As the kernel is responsible for creating the layout, it
> > > expects the exact same layout coming back in, and any deviation from
> > > that results in the task being forcefully exited.
> > 
> > Unfortunately, things that are not intended as examples do still get
> > used.  We can argue that's the userspace folks' fault, but it still
> > creates de facto ABI...
> 
> Given that the contents of the structure depend on kernel configuration
> symbols, it's impossible for userspace to use it unless they also have
> some kind of static configuration as well.

Agreed

> > > Basically, the layout that the kernel creates is entirely dependent on
> > > the kernel configuration, and any scheme that replicates what the kernel
> > > is doing in the restore paths is doomed to failure.  (However, that's
> > > not to say userspace isn't, but if it is, userspace breaks if the kernel
> > > configuration is changed.  I don't regard that as a kernel-induced
> > > userspace regression though - it's a bit like expecting EABI userspace
> > > to work with OABI-only supporting kernel.)
> 
> The kernel gained the tagged-list approach in 2006, and didn't start
> preserving the VFP state until 2010.
> 
> > I'm actually a little confused by, say,
> > 
> > https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/arm/setcontext.S;h=db6aebfbd4d360e3b7ba525cf2e483f8e3ddfc0d;hb=HEAD
> > 
> > Assuming I'm looking in the right place here, glibc effectively uses its
> > own private format for uc_regspace -- maybe there is kernel history
> > here I'm not aware of, or maybe it's not even trying to be compatible.
> 
> It looks to me like glibc is expecting:
> 
> - If the HWCAP includes VFP
>    - 64 bytes of d8-d15 registers
>    - fpscr
> - If the HWCAP includes iWMMXT
>    - 48 bytes of iWMMXT state
> 
> The kernel has never used that (partial!) format - note that it seems
> to omit d0-d7 from the context.
> 
> Given that setcontext()'s man page says:
> 
>        The  function setcontext() restores the user context pointed at by ucp.
>        A successful call does  not  return.   The  context  should  have  been
>        obtained  by  a  call  of getcontext(), or makecontext(3), or passed as
>        third argument to a signal handler.
> 
> it seems that for this to work in the signal handler case, there would
> have to be some kind of translation from the kernel format to glibc's
> format when calling into the signal handler - maybe there is... but
> what you point out is definitely incompatible with the kernel today,
> and has always been incompatible.
> 
> If there's no translation going on, then this has never worked, and so
> there's no possibility of a regression!

Yes.  Sadly, there's no indication of whether the incompatibility is
intentional or not.

> > Also, libunwind does not appear to attempt to parse uc_regspace:
> > 
> > git.savannah.gnu.org/gitweb/?p=libunwind.git;a=blob;f=src/arm/Gstep.c;h=37e6c12f115173ebbc9ebcf511c53fd7c0a7d9a1;hb=HEAD
> 
> Yea, it's just looking at the integer register set.
> 
> > I've not fully understood the gdb code, but there is a comment in
> > arm-linux-tdep.c that suggests that uc_regspace is not processed (nor do
> > I see any other mention of uc_regspace or things like VFP_MAGIC:
> > 
> > https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/arm-linux-tdep.c;h=95c52608adbb1ff92a9ddb203835d5a1102339bd;hb=HEAD
> > 
> > /* The VFP or iWMMXt registers may be saved on the stack, but there's
> > 	no reliable way to restore them (yet).  */
> 
> It sounds like no one implemented the userspace side of this then!
> 
> > Do you know of any userspace parser of uc_regspace?
> > 
> > All I have so far is this, from the reporter of the bug:
> > 
> > https://github.com/DynamoRIO/dynamorio/commit/0b75c635033d01ab04f955f5affe14a3ced9ab56
> 
> Hmm, well, it seems like they're the first to test this feature, which
> is pretty sad.

Hmm indeed

> > Should we enforce the same on sigreturn, or be more tolerant?
> 
> I've been thinking about that, and haven't come to a decision.  There
> is the matter that more complex parsing is harder to be correct (think
> about out of bounds 'size' values, although that can be mitigated by
> ensuring that size is numerically correct for the magic ID - but then
> what if we have a wrong ID, or the size is incorrect for the magic ID?)
> 
> > There is some merit to this, since the effect cannot be achieved 100%
> > safely in any other way.  However, it may require the caller to
> > manufacture a sigframe from scratch.  If so, it may be natural to
> > omit the IWMMXT block (and indeed the VFP block, if the caller
> > doesn't care what's in the VFP registers at the destination).
> 
> As you can see, the kernel hasn't really catered for manufactured
> sigframes - it expects to see the same sigframe that it wrote out.
> Whether that's reasonable or not, I'm not sure, but no one's
> complained about it yet!
> 
> > The DynamoRIO example above takes a signal to generate a "template"
> > sigframe, which is then modified to produce the desired result.
> > Putting aside the issue of whether this is an abuse of sigreturn
> > or not (and the question of why they are doing it at all), this
> > seems a reasonable approach -- which they also apparently use for
> > x86.  So their sigframe will contain the dummy iWMMXt block, but
> > it will have a valid tag if we patch the kernel to write one.
> 
> Bear in mind that parsing the data in uc_regspace is going to be
> hardware specific, it's hard to do it in a generic way.  Debuggers
> necessarily have to know the intricate hardware details of the
> system its running on, so it's reasonable for them to poke about
> in that area.  I'm not so sure about generic applications though.
> 
> Anyway, I don't have time this evening to continue this reply... so
> I'll send it anyway. :)

There's certainly a limit to the portability that userspace can expect
here.  Returning from a signal is portable; poking about inside
mcontext_t is not, though we should aim for least surprise.


For the RFC v2 I just posted, I've aimed for a halfway house where
the code is kept a simple as possible without mandating the
iWMMXt dummy block to be present on non-iWMMXt hardware.

If present, the block must have the same location and size as
the iwmmxt_sigframe would have.  This should avoid the possibility
of any runtime overrun when attempting to skip blocks.

Cheers
---Dave



More information about the linux-arm-kernel mailing list