Commit d5b454f2c40c9efd0cc113bc3220ebcb66b7c022

Authored by David Woodhouse
1 parent 351bb72259

AUDIT: Fix livelock in audit_serial().

The tricks with atomic_t were bizarre. Just do it sensibly instead.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>

Showing 1 changed file with 10 additions and 11 deletions Side-by-side Diff

... ... @@ -610,26 +610,25 @@
610 610 * (timestamp,serial) tuple is unique for each syscall and is live from
611 611 * syscall entry to syscall exit.
612 612 *
613   - * Atomic values are only guaranteed to be 24-bit, so we count down.
614   - *
615 613 * NOTE: Another possibility is to store the formatted records off the
616 614 * audit context (for those records that have a context), and emit them
617 615 * all at syscall exit. However, this could delay the reporting of
618 616 * significant errors until syscall exit (or never, if the system
619 617 * halts). */
  618 +
620 619 unsigned int audit_serial(void)
621 620 {
622   - static atomic_t serial = ATOMIC_INIT(0xffffff);
623   - unsigned int a, b;
  621 + static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
  622 + static unsigned int serial = 0;
624 623  
625   - do {
626   - a = atomic_read(&serial);
627   - if (atomic_dec_and_test(&serial))
628   - atomic_set(&serial, 0xffffff);
629   - b = atomic_read(&serial);
630   - } while (b != a - 1);
  624 + unsigned long flags;
  625 + unsigned int ret;
631 626  
632   - return 0xffffff - b;
  627 + spin_lock_irqsave(&serial_lock, flags);
  628 + ret = serial++;
  629 + spin_unlock_irqrestore(&serial_lock, flags);
  630 +
  631 + return ret;
633 632 }
634 633  
635 634 static inline void audit_get_stamp(struct audit_context *ctx,