libnih-1.0.3-signal-race.patch 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. https://bugs.launchpad.net/libnih/+bug/518921
  2. fix race in signal processing leading to lost signals
  3. The current loop will walk all signals one by one and run the handler
  4. for it if any signals were pending. Then it clears the array. But if
  5. a signal comes in for an earlier checked signal, it will get clobbered
  6. when the final clear runs.
  7. Change the logic so that we only clear entries for signals whose handler
  8. we explicitly call. If a different signal comes in, we'll process it
  9. the next time around.
  10. This was discovered & triaged by Jeffy Chen from Rockchip.
  11. === modified file 'nih/signal.c'
  12. --- nih/signal.c 2009-06-23 09:29:37 +0000
  13. +++ nih/signal.c 2015-05-21 08:12:11 +0000
  14. @@ -337,17 +337,37 @@
  15. nih_signal_init ();
  16. + /* Since this poller runs w/out signals masked, we do not want to try
  17. + * and clear any other signals (like zeroing the caught array at the
  18. + * end). If we do that, we open a race:
  19. + * - Walk the list of signals.
  20. + * - First one is not set so we move on to the second one.
  21. + * - First signal comes in while processing second and increments the
  22. + * caught array entry.
  23. + * - Finish walking the whole list.
  24. + * - Zero out the whole list and thus throw away the first signal.
  25. + * Since the signal handlers can take any length of time, this race
  26. + * can be open for a variable amount of time.
  27. + */
  28. +
  29. NIH_LIST_FOREACH_SAFE (nih_signals, iter) {
  30. NihSignal *signal = (NihSignal *)iter;
  31. if (! signals_caught[signal->signum])
  32. continue;
  33. + /* Now that we know we're going to process this signal, clear
  34. + * out all pending counts for it. There is a slight race here
  35. + * where the same signal can come in, but the API has never
  36. + * guaranteed exact coverage since POSIX does not provide it --
  37. + * more than one signal can be collapsed into one event. All
  38. + * we can guarantee is that we'll notice signals that come in
  39. + * once the handler runs.
  40. + */
  41. + signals_caught[signal->signum] = 0;
  42. +
  43. signal->handler (signal->data, signal);
  44. }
  45. -
  46. - for (s = 0; s < NUM_SIGNALS; s++)
  47. - signals_caught[s] = 0;
  48. }