Re: libssl: signal races in capability checks

2015-03-15 Thread Miod Vallat
> grep'ed the tree for siglongjmp calls, and spotted possible offenders in
> libssl's code. The code in question checks hardware capabilities for
> ARM, S390x, and SPARCv9.
> 
> The code will call some routines that could trigger SIGILL (or SIGBUS),
> which is caught with an own signal handler. This signal handler will
> perform the previously mentioned siglongjmp and jumps out of the
> capability testing.

For the record, none of this code is enabled under OpenBSD. I will spare
you my opinion of libraries registering signal handlers, because the
amount of profanity I'd use is beyond the tolerance level of this list.

All the information about the processor we run, and obtained by
attempting to execute code and catch signals, has to be obtained from
the kernel in a safe way (such as sysctl). Only the kernel will know
that all the processors the library may run on, when running on a
multiprocessor system, support the various instruction flavours.

For a good example of this, see for example ppccap.c, although it is
currently unused either.

> It's difficult to write proper signal handlers, and even worse, I lack
> machines of these types. "gcc -c" compiles the S390x and SPARCv9 files
> for me, so there shouldn't be syntax errors. Yet I really need peer
> reviews. If somebody dares to look at signals: Now is the time! :)

I think now is the time to remove the S390x code, and work on
documenting what the signal-based code attempts to know so that this
code can be removed completely.

(and this reminds me to add a few machdep sysctls to sparc64 so that I
can tinker with the VIS Montgomery code...)

Miod



libssl: signal races in capability checks

2015-03-14 Thread Tobias Stoeckmann
Hi,

grep'ed the tree for siglongjmp calls, and spotted possible offenders in
libssl's code. The code in question checks hardware capabilities for
ARM, S390x, and SPARCv9.

The code will call some routines that could trigger SIGILL (or SIGBUS),
which is caught with an own signal handler. This signal handler will
perform the previously mentioned siglongjmp and jumps out of the
capability testing.

Unfortunately, the signal handlers are registered and activated before
the jump environment is properly initialized. If the program receives
SIGILL (or SIGBUS in case of SPARCv9) from another source, the behavior
of the program will be undefined.

Fix for ARM and S390x is simple: Register the signal handlers after the
environment has been properly set up. Which means right after sigsetjmp.

The SPARCv9 code is more complicated: It registers a signal handler for
SIGILL and SIGBUS. These signal handlers don't block each other, which
means that SIGILL performing a siglongjmp could be interrupted by SIGBUS
which will perform a siglongjmp, too. I haven't seen these jump methods
as signal-safe in signal(3), so I assume that they are not. The first
part of the fix is to block SIGILL and SIGBUS while performing the
signal handler.

Also, SPARCv9 code overrides the environment between two independent
tests, still allowing these signals. It means that the setting of the
jump environment can be interrupted with a jump... That sounds like
asking for trouble. Therefore, I block these two signals during call of
sigsetjmp.

Last remaining bits are KNF and removing unused code.

It's difficult to write proper signal handlers, and even worse, I lack
machines of these types. "gcc -c" compiles the S390x and SPARCv9 files
for me, so there shouldn't be syntax errors. Yet I really need peer
reviews. If somebody dares to look at signals: Now is the time! :)


Tobias

Index: armcap.c
===
RCS file: /cvs/src/lib/libssl/src/crypto/armcap.c,v
retrieving revision 1.6
diff -u -p -r1.6 armcap.c
--- armcap.c20 Jun 2014 21:00:46 -  1.6
+++ armcap.c14 Mar 2015 17:52:50 -
@@ -14,7 +14,10 @@ unsigned int OPENSSL_armcap_P;
 static sigset_t all_masked;
 
 static sigjmp_buf ill_jmp;
-   static void ill_handler (int sig) { siglongjmp(ill_jmp, sig);
+static void
+ill_handler(int sig)
+{
+   siglongjmp(ill_jmp, sig);
 }
 
 /*
@@ -31,9 +34,6 @@ void OPENSSL_cpuid_setup(void) __attribu
 void
 OPENSSL_cpuid_setup(void)
 {
-#ifndef __OpenBSD__
-   char *e;
-#endif
 #if __ARM_ARCH__ >= 7
struct sigactionill_oact, ill_act;
sigset_toset;
@@ -59,14 +59,14 @@ OPENSSL_cpuid_setup(void)
ill_act.sa_mask = all_masked;
 
sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
-   sigaction(SIGILL, &ill_act, &ill_oact);
 
if (sigsetjmp(ill_jmp, 1) == 0) {
+   sigaction(SIGILL, &ill_act, &ill_oact);
_armv7_neon_probe();
OPENSSL_armcap_P |= ARMV7_NEON;
}
 
-   sigaction (SIGILL, &ill_oact, NULL);
+   sigaction(SIGILL, &ill_oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
 #endif
 }
Index: s390xcap.c
===
RCS file: /cvs/src/lib/libssl/src/crypto/s390xcap.c,v
retrieving revision 1.3
diff -u -p -r1.3 s390xcap.c
--- s390xcap.c  12 Jun 2014 15:49:27 -  1.3
+++ s390xcap.c  14 Mar 2015 17:52:50 -
@@ -8,7 +8,8 @@
 extern unsigned long OPENSSL_s390xcap_P[];
 
 static sigjmp_buf ill_jmp;
-static void ill_handler (int sig)
+static void
+ill_handler(int sig)
 {
siglongjmp(ill_jmp, sig);
 }
@@ -32,12 +33,13 @@ OPENSSL_cpuid_setup(void)
sigdelset(&ill_act.sa_mask, SIGILL);
sigdelset(&ill_act.sa_mask, SIGTRAP);
sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
-   sigaction (SIGILL, &ill_act, &oact);
 
/* protection against missing store-facility-list-extended */
-   if (sigsetjmp(ill_jmp, 1) == 0)
+   if (sigsetjmp(ill_jmp, 1) == 0) {
+   sigaction(SIGILL, &ill_act, &oact);
OPENSSL_s390x_facilities();
+   }
 
-   sigaction (SIGILL, &oact, NULL);
+   sigaction(SIGILL, &oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
 }
Index: sparcv9cap.c
===
RCS file: /cvs/src/lib/libssl/src/crypto/sparcv9cap.c,v
retrieving revision 1.7
diff -u -p -r1.7 sparcv9cap.c
--- sparcv9cap.c20 Jun 2014 21:00:46 -  1.7
+++ sparcv9cap.c14 Mar 2015 17:52:50 -
@@ -44,9 +44,8 @@ common_handler(int sig)
 void
 OPENSSL_cpuid_setup(void)
 {
-   char *e;
struct sigactioncommon_act, ill_oact, bus_oact;
-   sigset_tall_masked, oset;
+   sigset_tothers_masked, all_masked, oset;
static int trigger = 0;
 
if (trigger)
@@ -56,25 +55,33 @@ OPENSSL_cpuid_setup(