diff options
Diffstat (limited to 'kernel/audit.c')
-rw-r--r-- | kernel/audit.c | 146 |
1 files changed, 65 insertions, 81 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 9442c3533ba9..defc2e6f1e3b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -115,9 +115,6 @@ static atomic_t audit_lost = ATOMIC_INIT(0); | |||
115 | /* The netlink socket. */ | 115 | /* The netlink socket. */ |
116 | static struct sock *audit_sock; | 116 | static struct sock *audit_sock; |
117 | 117 | ||
118 | /* Inotify handle. */ | ||
119 | struct inotify_handle *audit_ih; | ||
120 | |||
121 | /* Hash for inode-based rules */ | 118 | /* Hash for inode-based rules */ |
122 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; | 119 | struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; |
123 | 120 | ||
@@ -136,7 +133,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | |||
136 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 133 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
137 | 134 | ||
138 | /* Serialize requests from userspace. */ | 135 | /* Serialize requests from userspace. */ |
139 | static DEFINE_MUTEX(audit_cmd_mutex); | 136 | DEFINE_MUTEX(audit_cmd_mutex); |
140 | 137 | ||
141 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting | 138 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting |
142 | * audit records. Since printk uses a 1024 byte buffer, this buffer | 139 | * audit records. Since printk uses a 1024 byte buffer, this buffer |
@@ -375,6 +372,25 @@ static void audit_hold_skb(struct sk_buff *skb) | |||
375 | kfree_skb(skb); | 372 | kfree_skb(skb); |
376 | } | 373 | } |
377 | 374 | ||
375 | /* | ||
376 | * For one reason or another this nlh isn't getting delivered to the userspace | ||
377 | * audit daemon, just send it to printk. | ||
378 | */ | ||
379 | static void audit_printk_skb(struct sk_buff *skb) | ||
380 | { | ||
381 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | ||
382 | char *data = NLMSG_DATA(nlh); | ||
383 | |||
384 | if (nlh->nlmsg_type != AUDIT_EOE) { | ||
385 | if (printk_ratelimit()) | ||
386 | printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); | ||
387 | else | ||
388 | audit_log_lost("printk limit exceeded\n"); | ||
389 | } | ||
390 | |||
391 | audit_hold_skb(skb); | ||
392 | } | ||
393 | |||
378 | static void kauditd_send_skb(struct sk_buff *skb) | 394 | static void kauditd_send_skb(struct sk_buff *skb) |
379 | { | 395 | { |
380 | int err; | 396 | int err; |
@@ -427,14 +443,8 @@ static int kauditd_thread(void *dummy) | |||
427 | if (skb) { | 443 | if (skb) { |
428 | if (audit_pid) | 444 | if (audit_pid) |
429 | kauditd_send_skb(skb); | 445 | kauditd_send_skb(skb); |
430 | else { | 446 | else |
431 | if (printk_ratelimit()) | 447 | audit_printk_skb(skb); |
432 | printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0)); | ||
433 | else | ||
434 | audit_log_lost("printk limit exceeded\n"); | ||
435 | |||
436 | audit_hold_skb(skb); | ||
437 | } | ||
438 | } else { | 448 | } else { |
439 | DECLARE_WAITQUEUE(wait, current); | 449 | DECLARE_WAITQUEUE(wait, current); |
440 | set_current_state(TASK_INTERRUPTIBLE); | 450 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -495,42 +505,25 @@ int audit_send_list(void *_dest) | |||
495 | return 0; | 505 | return 0; |
496 | } | 506 | } |
497 | 507 | ||
498 | #ifdef CONFIG_AUDIT_TREE | ||
499 | static int prune_tree_thread(void *unused) | ||
500 | { | ||
501 | mutex_lock(&audit_cmd_mutex); | ||
502 | audit_prune_trees(); | ||
503 | mutex_unlock(&audit_cmd_mutex); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | void audit_schedule_prune(void) | ||
508 | { | ||
509 | kthread_run(prune_tree_thread, NULL, "audit_prune_tree"); | ||
510 | } | ||
511 | #endif | ||
512 | |||
513 | struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, | 508 | struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, |
514 | int multi, void *payload, int size) | 509 | int multi, void *payload, int size) |
515 | { | 510 | { |
516 | struct sk_buff *skb; | 511 | struct sk_buff *skb; |
517 | struct nlmsghdr *nlh; | 512 | struct nlmsghdr *nlh; |
518 | int len = NLMSG_SPACE(size); | ||
519 | void *data; | 513 | void *data; |
520 | int flags = multi ? NLM_F_MULTI : 0; | 514 | int flags = multi ? NLM_F_MULTI : 0; |
521 | int t = done ? NLMSG_DONE : type; | 515 | int t = done ? NLMSG_DONE : type; |
522 | 516 | ||
523 | skb = alloc_skb(len, GFP_KERNEL); | 517 | skb = nlmsg_new(size, GFP_KERNEL); |
524 | if (!skb) | 518 | if (!skb) |
525 | return NULL; | 519 | return NULL; |
526 | 520 | ||
527 | nlh = NLMSG_PUT(skb, pid, seq, t, size); | 521 | nlh = NLMSG_NEW(skb, pid, seq, t, size, flags); |
528 | nlh->nlmsg_flags = flags; | 522 | data = NLMSG_DATA(nlh); |
529 | data = NLMSG_DATA(nlh); | ||
530 | memcpy(data, payload, size); | 523 | memcpy(data, payload, size); |
531 | return skb; | 524 | return skb; |
532 | 525 | ||
533 | nlmsg_failure: /* Used by NLMSG_PUT */ | 526 | nlmsg_failure: /* Used by NLMSG_NEW */ |
534 | if (skb) | 527 | if (skb) |
535 | kfree_skb(skb); | 528 | kfree_skb(skb); |
536 | return NULL; | 529 | return NULL; |
@@ -926,28 +919,29 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
926 | } | 919 | } |
927 | 920 | ||
928 | /* | 921 | /* |
929 | * Get message from skb (based on rtnetlink_rcv_skb). Each message is | 922 | * Get message from skb. Each message is processed by audit_receive_msg. |
930 | * processed by audit_receive_msg. Malformed skbs with wrong length are | 923 | * Malformed skbs with wrong length are discarded silently. |
931 | * discarded silently. | ||
932 | */ | 924 | */ |
933 | static void audit_receive_skb(struct sk_buff *skb) | 925 | static void audit_receive_skb(struct sk_buff *skb) |
934 | { | 926 | { |
935 | int err; | 927 | struct nlmsghdr *nlh; |
936 | struct nlmsghdr *nlh; | 928 | /* |
937 | u32 rlen; | 929 | * len MUST be signed for NLMSG_NEXT to be able to dec it below 0 |
930 | * if the nlmsg_len was not aligned | ||
931 | */ | ||
932 | int len; | ||
933 | int err; | ||
938 | 934 | ||
939 | while (skb->len >= NLMSG_SPACE(0)) { | 935 | nlh = nlmsg_hdr(skb); |
940 | nlh = nlmsg_hdr(skb); | 936 | len = skb->len; |
941 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) | 937 | |
942 | return; | 938 | while (NLMSG_OK(nlh, len)) { |
943 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | 939 | err = audit_receive_msg(skb, nlh); |
944 | if (rlen > skb->len) | 940 | /* if err or if this message says it wants a response */ |
945 | rlen = skb->len; | 941 | if (err || (nlh->nlmsg_flags & NLM_F_ACK)) |
946 | if ((err = audit_receive_msg(skb, nlh))) { | ||
947 | netlink_ack(skb, nlh, err); | 942 | netlink_ack(skb, nlh, err); |
948 | } else if (nlh->nlmsg_flags & NLM_F_ACK) | 943 | |
949 | netlink_ack(skb, nlh, 0); | 944 | nlh = NLMSG_NEXT(nlh, len); |
950 | skb_pull(skb, rlen); | ||
951 | } | 945 | } |
952 | } | 946 | } |
953 | 947 | ||
@@ -959,13 +953,6 @@ static void audit_receive(struct sk_buff *skb) | |||
959 | mutex_unlock(&audit_cmd_mutex); | 953 | mutex_unlock(&audit_cmd_mutex); |
960 | } | 954 | } |
961 | 955 | ||
962 | #ifdef CONFIG_AUDITSYSCALL | ||
963 | static const struct inotify_operations audit_inotify_ops = { | ||
964 | .handle_event = audit_handle_ievent, | ||
965 | .destroy_watch = audit_free_parent, | ||
966 | }; | ||
967 | #endif | ||
968 | |||
969 | /* Initialize audit support at boot time. */ | 956 | /* Initialize audit support at boot time. */ |
970 | static int __init audit_init(void) | 957 | static int __init audit_init(void) |
971 | { | 958 | { |
@@ -991,12 +978,6 @@ static int __init audit_init(void) | |||
991 | 978 | ||
992 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); | 979 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); |
993 | 980 | ||
994 | #ifdef CONFIG_AUDITSYSCALL | ||
995 | audit_ih = inotify_init(&audit_inotify_ops); | ||
996 | if (IS_ERR(audit_ih)) | ||
997 | audit_panic("cannot initialize inotify handle"); | ||
998 | #endif | ||
999 | |||
1000 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) | 981 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) |
1001 | INIT_LIST_HEAD(&audit_inode_hash[i]); | 982 | INIT_LIST_HEAD(&audit_inode_hash[i]); |
1002 | 983 | ||
@@ -1070,18 +1051,20 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | |||
1070 | goto err; | 1051 | goto err; |
1071 | } | 1052 | } |
1072 | 1053 | ||
1073 | ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask); | ||
1074 | if (!ab->skb) | ||
1075 | goto err; | ||
1076 | |||
1077 | ab->ctx = ctx; | 1054 | ab->ctx = ctx; |
1078 | ab->gfp_mask = gfp_mask; | 1055 | ab->gfp_mask = gfp_mask; |
1079 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); | 1056 | |
1080 | nlh->nlmsg_type = type; | 1057 | ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask); |
1081 | nlh->nlmsg_flags = 0; | 1058 | if (!ab->skb) |
1082 | nlh->nlmsg_pid = 0; | 1059 | goto nlmsg_failure; |
1083 | nlh->nlmsg_seq = 0; | 1060 | |
1061 | nlh = NLMSG_NEW(ab->skb, 0, 0, type, 0, 0); | ||
1062 | |||
1084 | return ab; | 1063 | return ab; |
1064 | |||
1065 | nlmsg_failure: /* Used by NLMSG_NEW */ | ||
1066 | kfree_skb(ab->skb); | ||
1067 | ab->skb = NULL; | ||
1085 | err: | 1068 | err: |
1086 | audit_buffer_free(ab); | 1069 | audit_buffer_free(ab); |
1087 | return NULL; | 1070 | return NULL; |
@@ -1452,6 +1435,15 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | |||
1452 | kfree(pathname); | 1435 | kfree(pathname); |
1453 | } | 1436 | } |
1454 | 1437 | ||
1438 | void audit_log_key(struct audit_buffer *ab, char *key) | ||
1439 | { | ||
1440 | audit_log_format(ab, " key="); | ||
1441 | if (key) | ||
1442 | audit_log_untrustedstring(ab, key); | ||
1443 | else | ||
1444 | audit_log_format(ab, "(null)"); | ||
1445 | } | ||
1446 | |||
1455 | /** | 1447 | /** |
1456 | * audit_log_end - end one audit record | 1448 | * audit_log_end - end one audit record |
1457 | * @ab: the audit_buffer | 1449 | * @ab: the audit_buffer |
@@ -1475,15 +1467,7 @@ void audit_log_end(struct audit_buffer *ab) | |||
1475 | skb_queue_tail(&audit_skb_queue, ab->skb); | 1467 | skb_queue_tail(&audit_skb_queue, ab->skb); |
1476 | wake_up_interruptible(&kauditd_wait); | 1468 | wake_up_interruptible(&kauditd_wait); |
1477 | } else { | 1469 | } else { |
1478 | if (nlh->nlmsg_type != AUDIT_EOE) { | 1470 | audit_printk_skb(ab->skb); |
1479 | if (printk_ratelimit()) { | ||
1480 | printk(KERN_NOTICE "type=%d %s\n", | ||
1481 | nlh->nlmsg_type, | ||
1482 | ab->skb->data + NLMSG_SPACE(0)); | ||
1483 | } else | ||
1484 | audit_log_lost("printk limit exceeded\n"); | ||
1485 | } | ||
1486 | audit_hold_skb(ab->skb); | ||
1487 | } | 1471 | } |
1488 | ab->skb = NULL; | 1472 | ab->skb = NULL; |
1489 | } | 1473 | } |