diff --git a/kernel/audit.c b/kernel/audit.c index 6f344b44d3d3..e5bdba3e3ae1 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -620,6 +620,42 @@ static int __init audit_enable(char *str) __setup("audit=", audit_enable); +static void audit_buffer_free(struct audit_buffer *ab) +{ + unsigned long flags; + + atomic_dec(&audit_backlog); + spin_lock_irqsave(&audit_freelist_lock, flags); + if (++audit_freelist_count > AUDIT_MAXFREE) + kfree(ab); + else + list_add(&ab->list, &audit_freelist); + spin_unlock_irqrestore(&audit_freelist_lock, flags); +} + +static struct audit_buffer * audit_buffer_alloc(int gfp_mask) +{ + unsigned long flags; + struct audit_buffer *ab = NULL; + + spin_lock_irqsave(&audit_freelist_lock, flags); + if (!list_empty(&audit_freelist)) { + ab = list_entry(audit_freelist.next, + struct audit_buffer, list); + list_del(&ab->list); + --audit_freelist_count; + } + spin_unlock_irqrestore(&audit_freelist_lock, flags); + + if (!ab) { + ab = kmalloc(sizeof(*ab), GFP_ATOMIC); + if (!ab) + goto out; + } + atomic_inc(&audit_backlog); +out: + return ab; +} /* Obtain an audit buffer. This routine does locking to obtain the * audit buffer, but then no locking is required for calls to @@ -630,7 +666,6 @@ __setup("audit=", audit_enable); struct audit_buffer *audit_log_start(struct audit_context *ctx) { struct audit_buffer *ab = NULL; - unsigned long flags; struct timespec t; unsigned int serial; @@ -649,23 +684,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) return NULL; } - spin_lock_irqsave(&audit_freelist_lock, flags); - if (!list_empty(&audit_freelist)) { - ab = list_entry(audit_freelist.next, - struct audit_buffer, list); - list_del(&ab->list); - --audit_freelist_count; - } - spin_unlock_irqrestore(&audit_freelist_lock, flags); - - if (!ab) - ab = kmalloc(sizeof(*ab), GFP_ATOMIC); + ab = audit_buffer_alloc(GFP_ATOMIC); if (!ab) { audit_log_lost("out of memory in audit_log_start"); return NULL; } - atomic_inc(&audit_backlog); skb_queue_head_init(&ab->sklist); ab->ctx = ctx; @@ -824,8 +848,6 @@ static void audit_log_end_irq(struct audit_buffer *ab) * be called in an irq context. */ static void audit_log_end_fast(struct audit_buffer *ab) { - unsigned long flags; - BUG_ON(in_irq()); if (!ab) return; @@ -836,14 +858,7 @@ static void audit_log_end_fast(struct audit_buffer *ab) if (audit_log_drain(ab)) return; } - - atomic_dec(&audit_backlog); - spin_lock_irqsave(&audit_freelist_lock, flags); - if (++audit_freelist_count > AUDIT_MAXFREE) - kfree(ab); - else - list_add(&ab->list, &audit_freelist); - spin_unlock_irqrestore(&audit_freelist_lock, flags); + audit_buffer_free(ab); } /* Send or queue the message in the audit buffer, depending on the