tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Possible bug in i386 NetBSD 1.6 emulated signal delivery, sanity check on reasoning and possible fix.

        We have a project that is 5.1 i386, and a couple of our guys (Naren and 
Ashok) tracked down a problem with 1.6 emulation enabled, a signal would 
corrupt the fpu context.  That turned out to be the use of buildcontext in 
sendsig_sigcontext.  It blindly calls buildcontext, which resets the 
MDL_USEDFPU flag.  However, in the siginfo (sendsig_siginfo) case, it calls 
cpu_getmcontext, which builds a full register context for the processor 
(including FPU if needed -- and sets a flag noting that the fpu context was 
saved, and needs to be restored).  The sigcontext case has no such save, and as 
such the effect is that the fpu context is a fresh one when that process next 
attempts to use floating point.  In our case, the signal happened to slice a 
set of floating point operations in snprintf -- that is dtoa.  The result being 
that the code is sliced, and on return from the signal, attempted to complete 
the set of fpu operations, which now operated on a reset fpu register context 
--obviously giving erroneous results.
        I assume the sigcontext (1.6) signal delivery context assumes that the 
signal handler uses the same fpu context as the main portion of the program.  
In that case, I believe saving the state of the MDL_USEDFPU prior to calling 
buildcontext, and restoring it after the buildcontext call (only in the 
sigcontext case -- thus in compat_16_machdep.c:

   2011-09-07 05:46:27.000000000 -0700
     2011-09-07 05:46:27.000000000 -0700
@@ -175,6 +175,7 @@
        u_long code = KSI_TRAPCODE(ksi);
        struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), frame;
        sig_t catcher = SIGACTION(p, sig).sa_handler;
+       int svufpu;


@@ -259,8 +260,9 @@
                sigexit(l, SIGILL);
                /* NOTREACHED */
+       svufpu = l->l_md.md_flags & MDL_USEDFPU;
        buildcontext(l, sel, catcher, fp);
+       l->l_md.md_flags |= svufpu;

        /* Remember that we're now on the signal stack. */
        if (onstack)

Home | Main Index | Thread Index | Old Index