This is sources Bugzilla
Bugzilla Version 2.17.5
Bugzilla Bug 5220
  timer_delete race Last modified: 2007-10-28 19:27
     Query page      Enter new bug
Bug#: 5220   Hardware:   Reporter: Joseph Myers <jsm28@gcc.gnu.org>
Host: Target: Build:
Product:     Add CC:
Component:   Version:   CC:
Remove selected CCs
Status: RESOLVED   Priority:  
Resolution: FIXED   Severity:  
Assigned To: Ulrich Drepper <drepper@redhat.com>   Target Milestone:  
Flags: Requestee:
  backport ()
  examined ()
  testsuite ()
Summary:
Keywords:

Attachment Description Type Created Actions
glibc-timers-race Proposed patch patch 2007-10-25 20:41 Edit | Diff
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 5220 depends on: Show dependency tree
Show dependency graph
Bug 5220 blocks:

Additional Comments:


Leave as RESOLVED FIXED
Reopen bug
Mark bug as VERIFIED

View Bug Activity   |   Format For Printing


Description:   Last confirmed: 0000-00-00 00:00 Opened: 2007-10-25 20:39
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.

------- Additional Comment #1 From Joseph Myers 2007-10-25 20:41 -------
Created an attachment (id=2059)
Proposed patch

------- Additional Comment #2 From Ulrich Drepper 2007-10-28 19:27 -------
I checked in a patch to the cvs trunk.

     Query page      Enter new bug
Actions: New | Query | bug # | Reports | Requests   New Account | Log In