summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/audit.c61
1 files changed, 38 insertions, 23 deletions
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