View Bug Activity | Format For Printing
There is a race between timer_delete freeing memory and the timers helper thread accessing that memory. Suppose a timer uses signal delivery to the helper thread. The following sequence of events happens: 1. The timer signals the helper thread, so the following code starts executing. if (si.si_code == SI_TIMER) { struct timer *tk = (struct timer *) si.si_ptr; struct thread_start_data *td = malloc (sizeof (*td)); /* There is not much we can do if the allocation fails. */ if (td != NULL) { /* That is the signal we are waiting for. */ 2. timer_delete is called on the timer and frees the associated memory. struct timer *kt = (struct timer *) timerid; /* Delete the kernel timer object. */ int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); if (res == 0) { # ifndef __ASSUME_POSIX_TIMERS /* We know the syscall support is available. */ __no_posix_timers = 1; # endif /* Free the memory. */ (void) free (kt); 3. Some other thread reuses that freed memory. 4. The helper thread accesses the memory that was just freed and reused. td->thrfunc = tk->thrfunc; td->sival = tk->sival; I think that timer_delete needs to allow for the helper thread to process any pending signals for this timer before freeing the memory; doing otherwise is problematic for reliable use of timers, and POSIX says the disposition of pending signals for a deleted timer is unspecified, not undefined, which I interpret as requiring them to be safely delivered or not delivered at all rather than involving undefined behavior. I'll attach a patch for this race, though I'm not sure it's a particularly good approach for fixing it.
Created an attachment (id=2059) Proposed patch
I checked in a patch to the cvs trunk.