diff options
Diffstat (limited to 'kernel/audit.c')
-rw-r--r-- | kernel/audit.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 0738a4b290e6..0fbf1c116363 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/skbuff.h> | 56 | #include <linux/skbuff.h> |
57 | #include <linux/netlink.h> | 57 | #include <linux/netlink.h> |
58 | #include <linux/selinux.h> | 58 | #include <linux/selinux.h> |
59 | #include <linux/inotify.h> | ||
59 | 60 | ||
60 | #include "audit.h" | 61 | #include "audit.h" |
61 | 62 | ||
@@ -103,6 +104,12 @@ static atomic_t audit_lost = ATOMIC_INIT(0); | |||
103 | /* The netlink socket. */ | 104 | /* The netlink socket. */ |
104 | static struct sock *audit_sock; | 105 | static struct sock *audit_sock; |
105 | 106 | ||
107 | /* Inotify handle. */ | ||
108 | struct inotify_handle *audit_ih; | ||
109 | |||
110 | /* Hash for inode-based rules */ | ||
111 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; | ||
112 | |||
106 | /* The audit_freelist is a list of pre-allocated audit buffers (if more | 113 | /* The audit_freelist is a list of pre-allocated audit buffers (if more |
107 | * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of | 114 | * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of |
108 | * being placed on the freelist). */ | 115 | * being placed on the freelist). */ |
@@ -115,10 +122,8 @@ static struct task_struct *kauditd_task; | |||
115 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 122 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
116 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 123 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
117 | 124 | ||
118 | /* The netlink socket is only to be read by 1 CPU, which lets us assume | 125 | /* Serialize requests from userspace. */ |
119 | * that list additions and deletions never happen simultaneously in | 126 | static DEFINE_MUTEX(audit_cmd_mutex); |
120 | * auditsc.c */ | ||
121 | DEFINE_MUTEX(audit_netlink_mutex); | ||
122 | 127 | ||
123 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting | 128 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting |
124 | * audit records. Since printk uses a 1024 byte buffer, this buffer | 129 | * audit records. Since printk uses a 1024 byte buffer, this buffer |
@@ -373,8 +378,8 @@ int audit_send_list(void *_dest) | |||
373 | struct sk_buff *skb; | 378 | struct sk_buff *skb; |
374 | 379 | ||
375 | /* wait for parent to finish and send an ACK */ | 380 | /* wait for parent to finish and send an ACK */ |
376 | mutex_lock(&audit_netlink_mutex); | 381 | mutex_lock(&audit_cmd_mutex); |
377 | mutex_unlock(&audit_netlink_mutex); | 382 | mutex_unlock(&audit_cmd_mutex); |
378 | 383 | ||
379 | while ((skb = __skb_dequeue(&dest->q)) != NULL) | 384 | while ((skb = __skb_dequeue(&dest->q)) != NULL) |
380 | netlink_unicast(audit_sock, skb, pid, 0); | 385 | netlink_unicast(audit_sock, skb, pid, 0); |
@@ -665,20 +670,30 @@ static void audit_receive(struct sock *sk, int length) | |||
665 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
666 | unsigned int qlen; | 671 | unsigned int qlen; |
667 | 672 | ||
668 | mutex_lock(&audit_netlink_mutex); | 673 | mutex_lock(&audit_cmd_mutex); |
669 | 674 | ||
670 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { | 675 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { |
671 | skb = skb_dequeue(&sk->sk_receive_queue); | 676 | skb = skb_dequeue(&sk->sk_receive_queue); |
672 | audit_receive_skb(skb); | 677 | audit_receive_skb(skb); |
673 | kfree_skb(skb); | 678 | kfree_skb(skb); |
674 | } | 679 | } |
675 | mutex_unlock(&audit_netlink_mutex); | 680 | mutex_unlock(&audit_cmd_mutex); |
676 | } | 681 | } |
677 | 682 | ||
683 | #ifdef CONFIG_AUDITSYSCALL | ||
684 | static const struct inotify_operations audit_inotify_ops = { | ||
685 | .handle_event = audit_handle_ievent, | ||
686 | .destroy_watch = audit_free_parent, | ||
687 | }; | ||
688 | #endif | ||
678 | 689 | ||
679 | /* Initialize audit support at boot time. */ | 690 | /* Initialize audit support at boot time. */ |
680 | static int __init audit_init(void) | 691 | static int __init audit_init(void) |
681 | { | 692 | { |
693 | #ifdef CONFIG_AUDITSYSCALL | ||
694 | int i; | ||
695 | #endif | ||
696 | |||
682 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", | 697 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", |
683 | audit_default ? "enabled" : "disabled"); | 698 | audit_default ? "enabled" : "disabled"); |
684 | audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, | 699 | audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, |
@@ -697,6 +712,16 @@ static int __init audit_init(void) | |||
697 | selinux_audit_set_callback(&selinux_audit_rule_update); | 712 | selinux_audit_set_callback(&selinux_audit_rule_update); |
698 | 713 | ||
699 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); | 714 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); |
715 | |||
716 | #ifdef CONFIG_AUDITSYSCALL | ||
717 | audit_ih = inotify_init(&audit_inotify_ops); | ||
718 | if (IS_ERR(audit_ih)) | ||
719 | audit_panic("cannot initialize inotify handle"); | ||
720 | |||
721 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) | ||
722 | INIT_LIST_HEAD(&audit_inode_hash[i]); | ||
723 | #endif | ||
724 | |||
700 | return 0; | 725 | return 0; |
701 | } | 726 | } |
702 | __initcall(audit_init); | 727 | __initcall(audit_init); |