From d5b454f2c40c9efd0cc113bc3220ebcb66b7c022 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 15 Jul 2005 12:56:03 +0100 Subject: AUDIT: Fix livelock in audit_serial(). The tricks with atomic_t were bizarre. Just do it sensibly instead. Signed-off-by: David Woodhouse --- kernel/audit.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'kernel/audit.c') diff --git a/kernel/audit.c b/kernel/audit.c index 518a833b676..27ffcf363f8 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -610,26 +610,25 @@ err: * (timestamp,serial) tuple is unique for each syscall and is live from * syscall entry to syscall exit. * - * Atomic values are only guaranteed to be 24-bit, so we count down. - * * NOTE: Another possibility is to store the formatted records off the * audit context (for those records that have a context), and emit them * all at syscall exit. However, this could delay the reporting of * significant errors until syscall exit (or never, if the system * halts). */ + unsigned int audit_serial(void) { - static atomic_t serial = ATOMIC_INIT(0xffffff); - unsigned int a, b; + static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED; + static unsigned int serial = 0; + + unsigned long flags; + unsigned int ret; - do { - a = atomic_read(&serial); - if (atomic_dec_and_test(&serial)) - atomic_set(&serial, 0xffffff); - b = atomic_read(&serial); - } while (b != a - 1); + spin_lock_irqsave(&serial_lock, flags); + ret = serial++; + spin_unlock_irqrestore(&serial_lock, flags); - return 0xffffff - b; + return ret; } static inline void audit_get_stamp(struct audit_context *ctx, -- cgit v1.2.3-18-g5258