diff options
author | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-07-15 07:56:03 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-07-15 07:56:03 -0400 |
commit | d5b454f2c40c9efd0cc113bc3220ebcb66b7c022 (patch) | |
tree | a8aaa30e003c9dcc07840c217760f92e4fab430a | |
parent | 351bb722590b2329ac5e72c4b824b8b6ce6e3082 (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>
-rw-r--r-- | kernel/audit.c | 21 |
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 | |||
620 | unsigned int audit_serial(void) | 619 | unsigned 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 | ||
635 | static inline void audit_get_stamp(struct audit_context *ctx, | 634 | static inline void audit_get_stamp(struct audit_context *ctx, |