aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-07-15 07:56:03 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-07-15 07:56:03 -0400
commitd5b454f2c40c9efd0cc113bc3220ebcb66b7c022 (patch)
treea8aaa30e003c9dcc07840c217760f92e4fab430a /kernel/audit.c
parent351bb722590b2329ac5e72c4b824b8b6ce6e3082 (diff)
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>
Diffstat (limited to 'kernel/audit.c')
-rw-r--r--kernel/audit.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index 518a833b676a..27ffcf363f8d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -610,26 +610,25 @@ err:
610 * (timestamp,serial) tuple is unique for each syscall and is live from 610 * (timestamp,serial) tuple is unique for each syscall and is live from
611 * syscall entry to syscall exit. 611 * syscall entry to syscall exit.
612 * 612 *
613 * Atomic values are only guaranteed to be 24-bit, so we count down.
614 *
615 * NOTE: Another possibility is to store the formatted records off the 613 * NOTE: Another possibility is to store the formatted records off the
616 * audit context (for those records that have a context), and emit them 614 * audit context (for those records that have a context), and emit them
617 * all at syscall exit. However, this could delay the reporting of 615 * all at syscall exit. However, this could delay the reporting of
618 * significant errors until syscall exit (or never, if the system 616 * significant errors until syscall exit (or never, if the system
619 * halts). */ 617 * halts). */
618
620unsigned int audit_serial(void) 619unsigned int audit_serial(void)
621{ 620{
622 static atomic_t serial = ATOMIC_INIT(0xffffff); 621 static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
623 unsigned int a, b; 622 static unsigned int serial = 0;
623
624 unsigned long flags;
625 unsigned int ret;
624 626
625 do { 627 spin_lock_irqsave(&serial_lock, flags);
626 a = atomic_read(&serial); 628 ret = serial++;
627 if (atomic_dec_and_test(&serial)) 629 spin_unlock_irqrestore(&serial_lock, flags);
628 atomic_set(&serial, 0xffffff);
629 b = atomic_read(&serial);
630 } while (b != a - 1);
631 630
632 return 0xffffff - b; 631 return ret;
633} 632}
634 633
635static inline void audit_get_stamp(struct audit_context *ctx, 634static inline void audit_get_stamp(struct audit_context *ctx,