This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug dynamic-link/21269] i386 sigaction sa_restorer handling is wrong


https://sourceware.org/bugzilla/show_bug.cgi?id=21269

--- Comment #2 from Andy Lutomirski <luto at kernel dot org> ---
(In reply to Florian Weimer from comment #1)
> (In reply to Andy Lutomirski from comment #0)
> > glibc does this:
> > 
> >       if (GLRO(dl_sysinfo_dso) == NULL)
> >         {
> >           kact.sa_flags |= SA_RESTORER;
> > 
> >           kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
> >                               ? &restore_rt : &restore);
> >         }
> > 
> > This is correct for the vDSO-present case, but it's subtly wrong for the
> > vDSO-not-present case.  For ancient historical reasons, x86_32 Linux (and
> > compat on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a
> > request for stack switching if the SS segment is funny.  This means that
> > anything that tries to mix glibc's signal handling with segmentation is
> > randomly broken depending on what garbage lands in sa_restorer.  (Also, it's
> > just bad form to pass uninitialized data into the kernel.)
> > 
> > The fix should be trivial:
> > 
> >     else
> >       kact.sa_restorer = NULL;
> > 
> > or similar.
> 
> I think I'll take your word for this.  This seems an 

?

> 
> Do you see occasional crashes due to this?  Can they be triggered somehow,
> or are they spontaneous?

I see crashes 100% of the time in tools/testing/selftests/x86/ldt_gdt_32 in
Linux (if run on SMP) on Fedora 25.  I didn't before, presumably because of
luck.

> 
> > I can send a short test case if needed.
> 
> Do you have a copyright assignment for glibc?  If not, I'd prefer if you
> could describe what we need to test instead, so that we can write our own
> test case.  (And yes, we'd very much like to have a test case for this.)

No copyright assignment.

The most straightforward reproducer I can think of is to set up a struct
user_desc that's all zeros except entry_number = -1, limit = 0xfffff, seg_32bit
= 1, and limit_in_pages = 1.  Call set_thread_area(2) on it.  Set up a handler
for SIGTRAP -- details don't really matter.

Then do (intentionally not valid C so you can't copy it):

mov [(entry_number << 3) | 3], %ss
int3

A successful test will run the signal handler.  A failed test will segfault.

What's going on is that the combination of SA_RESTORER clear, sa_restorer != 0,
and nondefault %ss is interpreted as "change my stack pointer to the value in
sa_restorer".  The result is a crash.

This obviously won't affect the vast majority of programs that use glibc
because, while the first two conditions will be met, the latter condition is
rather unlikely.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]