diff options
Diffstat (limited to 'kernel/audit.c')
-rw-r--r-- | kernel/audit.c | 61 |
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) | |||
620 | 620 | ||
621 | __setup("audit=", audit_enable); | 621 | __setup("audit=", audit_enable); |
622 | 622 | ||
623 | static void audit_buffer_free(struct audit_buffer *ab) | ||
624 | { | ||
625 | unsigned long flags; | ||
626 | |||
627 | atomic_dec(&audit_backlog); | ||
628 | spin_lock_irqsave(&audit_freelist_lock, flags); | ||
629 | if (++audit_freelist_count > AUDIT_MAXFREE) | ||
630 | kfree(ab); | ||
631 | else | ||
632 | list_add(&ab->list, &audit_freelist); | ||
633 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | ||
634 | } | ||
635 | |||
636 | static struct audit_buffer * audit_buffer_alloc(int gfp_mask) | ||
637 | { | ||
638 | unsigned long flags; | ||
639 | struct audit_buffer *ab = NULL; | ||
640 | |||
641 | spin_lock_irqsave(&audit_freelist_lock, flags); | ||
642 | if (!list_empty(&audit_freelist)) { | ||
643 | ab = list_entry(audit_freelist.next, | ||
644 | struct audit_buffer, list); | ||
645 | list_del(&ab->list); | ||
646 | --audit_freelist_count; | ||
647 | } | ||
648 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | ||
649 | |||
650 | if (!ab) { | ||
651 | ab = kmalloc(sizeof(*ab), GFP_ATOMIC); | ||
652 | if (!ab) | ||
653 | goto out; | ||
654 | } | ||
655 | atomic_inc(&audit_backlog); | ||
656 | out: | ||
657 | return ab; | ||
658 | } | ||
623 | 659 | ||
624 | /* Obtain an audit buffer. This routine does locking to obtain the | 660 | /* Obtain an audit buffer. This routine does locking to obtain the |
625 | * audit buffer, but then no locking is required for calls to | 661 | * audit buffer, but then no locking is required for calls to |
@@ -630,7 +666,6 @@ __setup("audit=", audit_enable); | |||
630 | struct audit_buffer *audit_log_start(struct audit_context *ctx) | 666 | struct audit_buffer *audit_log_start(struct audit_context *ctx) |
631 | { | 667 | { |
632 | struct audit_buffer *ab = NULL; | 668 | struct audit_buffer *ab = NULL; |
633 | unsigned long flags; | ||
634 | struct timespec t; | 669 | struct timespec t; |
635 | unsigned int serial; | 670 | unsigned int serial; |
636 | 671 | ||
@@ -649,23 +684,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) | |||
649 | return NULL; | 684 | return NULL; |
650 | } | 685 | } |
651 | 686 | ||
652 | spin_lock_irqsave(&audit_freelist_lock, flags); | 687 | ab = audit_buffer_alloc(GFP_ATOMIC); |
653 | if (!list_empty(&audit_freelist)) { | ||
654 | ab = list_entry(audit_freelist.next, | ||
655 | struct audit_buffer, list); | ||
656 | list_del(&ab->list); | ||
657 | --audit_freelist_count; | ||
658 | } | ||
659 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | ||
660 | |||
661 | if (!ab) | ||
662 | ab = kmalloc(sizeof(*ab), GFP_ATOMIC); | ||
663 | if (!ab) { | 688 | if (!ab) { |
664 | audit_log_lost("out of memory in audit_log_start"); | 689 | audit_log_lost("out of memory in audit_log_start"); |
665 | return NULL; | 690 | return NULL; |
666 | } | 691 | } |
667 | 692 | ||
668 | atomic_inc(&audit_backlog); | ||
669 | skb_queue_head_init(&ab->sklist); | 693 | skb_queue_head_init(&ab->sklist); |
670 | 694 | ||
671 | ab->ctx = ctx; | 695 | ab->ctx = ctx; |
@@ -824,8 +848,6 @@ static void audit_log_end_irq(struct audit_buffer *ab) | |||
824 | * be called in an irq context. */ | 848 | * be called in an irq context. */ |
825 | static void audit_log_end_fast(struct audit_buffer *ab) | 849 | static void audit_log_end_fast(struct audit_buffer *ab) |
826 | { | 850 | { |
827 | unsigned long flags; | ||
828 | |||
829 | BUG_ON(in_irq()); | 851 | BUG_ON(in_irq()); |
830 | if (!ab) | 852 | if (!ab) |
831 | return; | 853 | return; |
@@ -836,14 +858,7 @@ static void audit_log_end_fast(struct audit_buffer *ab) | |||
836 | if (audit_log_drain(ab)) | 858 | if (audit_log_drain(ab)) |
837 | return; | 859 | return; |
838 | } | 860 | } |
839 | 861 | audit_buffer_free(ab); | |
840 | atomic_dec(&audit_backlog); | ||
841 | spin_lock_irqsave(&audit_freelist_lock, flags); | ||
842 | if (++audit_freelist_count > AUDIT_MAXFREE) | ||
843 | kfree(ab); | ||
844 | else | ||
845 | list_add(&ab->list, &audit_freelist); | ||
846 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | ||
847 | } | 862 | } |
848 | 863 | ||
849 | /* Send or queue the message in the audit buffer, depending on the | 864 | /* Send or queue the message in the audit buffer, depending on the |