fix data race in timer_create with SIGEV_THREAD notification
authorRich Felker <dalias@aerifal.cx>
Thu, 26 Sep 2019 01:49:53 +0000 (21:49 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 26 Sep 2019 01:49:53 +0000 (21:49 -0400)
in the timer thread start function, self->timer_id was accessed
without synchronization; the timer thread could fail to see the store
from the calling thread, resulting in timer_delete failing to delete
the correct kernel-level timer.

this fix is based on a patch by changdiankang, but with the load moved
to after receiving the timer_delete signal rather than just after the
start barrier, so as not to retain the possibility of data race with
timer_delete.

src/time/timer_create.c

index c5e40a195801d19afb9a4a1075835b8f0af1f289..455d49fc5035beca4b3f2b97553311d389cff164 100644 (file)
@@ -1,5 +1,6 @@
 #include <time.h>
 #include <setjmp.h>
+#include <limits.h>
 #include "pthread_impl.h"
 
 struct ksigevent {
@@ -48,7 +49,6 @@ static void *start(void *arg)
 {
        pthread_t self = __pthread_self();
        struct start_args *args = arg;
-       int id = self->timer_id;
        jmp_buf jb;
 
        void (*notify)(union sigval) = args->sev->sigev_notify_function;
@@ -65,7 +65,7 @@ static void *start(void *arg)
                }
                if (self->timer_id < 0) break;
        }
-       __syscall(SYS_timer_delete, id);
+       __syscall(SYS_timer_delete, self->timer_id & INT_MAX);
        return 0;
 }