diff options
Diffstat (limited to 'kernel/audit.c')
| -rw-r--r-- | kernel/audit.c | 128 |
1 files changed, 79 insertions, 49 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 7f0699790d46..83096b67510a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -79,6 +79,8 @@ static int audit_rate_limit; | |||
| 79 | 79 | ||
| 80 | /* Number of outstanding audit_buffers allowed. */ | 80 | /* Number of outstanding audit_buffers allowed. */ |
| 81 | static int audit_backlog_limit = 64; | 81 | static int audit_backlog_limit = 64; |
| 82 | static int audit_backlog_wait_time = 60 * HZ; | ||
| 83 | static int audit_backlog_wait_overflow = 0; | ||
| 82 | 84 | ||
| 83 | /* The identity of the user shutting down the audit system. */ | 85 | /* The identity of the user shutting down the audit system. */ |
| 84 | uid_t audit_sig_uid = -1; | 86 | uid_t audit_sig_uid = -1; |
| @@ -106,18 +108,12 @@ static LIST_HEAD(audit_freelist); | |||
| 106 | static struct sk_buff_head audit_skb_queue; | 108 | static struct sk_buff_head audit_skb_queue; |
| 107 | static struct task_struct *kauditd_task; | 109 | static struct task_struct *kauditd_task; |
| 108 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 110 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
| 109 | 111 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | |
| 110 | /* There are three lists of rules -- one to search at task creation | ||
| 111 | * time, one to search at syscall entry time, and another to search at | ||
| 112 | * syscall exit time. */ | ||
| 113 | static LIST_HEAD(audit_tsklist); | ||
| 114 | static LIST_HEAD(audit_entlist); | ||
| 115 | static LIST_HEAD(audit_extlist); | ||
| 116 | 112 | ||
| 117 | /* The netlink socket is only to be read by 1 CPU, which lets us assume | 113 | /* The netlink socket is only to be read by 1 CPU, which lets us assume |
| 118 | * that list additions and deletions never happen simultaneously in | 114 | * that list additions and deletions never happen simultaneously in |
| 119 | * auditsc.c */ | 115 | * auditsc.c */ |
| 120 | static DECLARE_MUTEX(audit_netlink_sem); | 116 | DECLARE_MUTEX(audit_netlink_sem); |
| 121 | 117 | ||
| 122 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting | 118 | /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting |
| 123 | * audit records. Since printk uses a 1024 byte buffer, this buffer | 119 | * audit records. Since printk uses a 1024 byte buffer, this buffer |
| @@ -137,6 +133,7 @@ struct audit_buffer { | |||
| 137 | struct list_head list; | 133 | struct list_head list; |
| 138 | struct sk_buff *skb; /* formatted skb ready to send */ | 134 | struct sk_buff *skb; /* formatted skb ready to send */ |
| 139 | struct audit_context *ctx; /* NULL or associated context */ | 135 | struct audit_context *ctx; /* NULL or associated context */ |
| 136 | int gfp_mask; | ||
| 140 | }; | 137 | }; |
| 141 | 138 | ||
| 142 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | 139 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) |
| @@ -145,11 +142,6 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | |||
| 145 | nlh->nlmsg_pid = pid; | 142 | nlh->nlmsg_pid = pid; |
| 146 | } | 143 | } |
| 147 | 144 | ||
| 148 | struct audit_entry { | ||
| 149 | struct list_head list; | ||
| 150 | struct audit_rule rule; | ||
| 151 | }; | ||
| 152 | |||
| 153 | static void audit_panic(const char *message) | 145 | static void audit_panic(const char *message) |
| 154 | { | 146 | { |
| 155 | switch (audit_failure) | 147 | switch (audit_failure) |
| @@ -233,7 +225,7 @@ static int audit_set_rate_limit(int limit, uid_t loginuid) | |||
| 233 | { | 225 | { |
| 234 | int old = audit_rate_limit; | 226 | int old = audit_rate_limit; |
| 235 | audit_rate_limit = limit; | 227 | audit_rate_limit = limit; |
| 236 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 228 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 237 | "audit_rate_limit=%d old=%d by auid=%u", | 229 | "audit_rate_limit=%d old=%d by auid=%u", |
| 238 | audit_rate_limit, old, loginuid); | 230 | audit_rate_limit, old, loginuid); |
| 239 | return old; | 231 | return old; |
| @@ -243,7 +235,7 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid) | |||
| 243 | { | 235 | { |
| 244 | int old = audit_backlog_limit; | 236 | int old = audit_backlog_limit; |
| 245 | audit_backlog_limit = limit; | 237 | audit_backlog_limit = limit; |
| 246 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 238 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 247 | "audit_backlog_limit=%d old=%d by auid=%u", | 239 | "audit_backlog_limit=%d old=%d by auid=%u", |
| 248 | audit_backlog_limit, old, loginuid); | 240 | audit_backlog_limit, old, loginuid); |
| 249 | return old; | 241 | return old; |
| @@ -255,7 +247,7 @@ static int audit_set_enabled(int state, uid_t loginuid) | |||
| 255 | if (state != 0 && state != 1) | 247 | if (state != 0 && state != 1) |
| 256 | return -EINVAL; | 248 | return -EINVAL; |
| 257 | audit_enabled = state; | 249 | audit_enabled = state; |
| 258 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 250 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 259 | "audit_enabled=%d old=%d by auid=%u", | 251 | "audit_enabled=%d old=%d by auid=%u", |
| 260 | audit_enabled, old, loginuid); | 252 | audit_enabled, old, loginuid); |
| 261 | return old; | 253 | return old; |
| @@ -269,7 +261,7 @@ static int audit_set_failure(int state, uid_t loginuid) | |||
| 269 | && state != AUDIT_FAIL_PANIC) | 261 | && state != AUDIT_FAIL_PANIC) |
| 270 | return -EINVAL; | 262 | return -EINVAL; |
| 271 | audit_failure = state; | 263 | audit_failure = state; |
| 272 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 264 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 273 | "audit_failure=%d old=%d by auid=%u", | 265 | "audit_failure=%d old=%d by auid=%u", |
| 274 | audit_failure, old, loginuid); | 266 | audit_failure, old, loginuid); |
| 275 | return old; | 267 | return old; |
| @@ -281,6 +273,7 @@ int kauditd_thread(void *dummy) | |||
| 281 | 273 | ||
| 282 | while (1) { | 274 | while (1) { |
| 283 | skb = skb_dequeue(&audit_skb_queue); | 275 | skb = skb_dequeue(&audit_skb_queue); |
| 276 | wake_up(&audit_backlog_wait); | ||
| 284 | if (skb) { | 277 | if (skb) { |
| 285 | if (audit_pid) { | 278 | if (audit_pid) { |
| 286 | int err = netlink_unicast(audit_sock, skb, audit_pid, 0); | 279 | int err = netlink_unicast(audit_sock, skb, audit_pid, 0); |
| @@ -290,7 +283,7 @@ int kauditd_thread(void *dummy) | |||
| 290 | audit_pid = 0; | 283 | audit_pid = 0; |
| 291 | } | 284 | } |
| 292 | } else { | 285 | } else { |
| 293 | printk(KERN_ERR "%s\n", skb->data + NLMSG_SPACE(0)); | 286 | printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0)); |
| 294 | kfree_skb(skb); | 287 | kfree_skb(skb); |
| 295 | } | 288 | } |
| 296 | } else { | 289 | } else { |
| @@ -423,7 +416,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 423 | if (status_get->mask & AUDIT_STATUS_PID) { | 416 | if (status_get->mask & AUDIT_STATUS_PID) { |
| 424 | int old = audit_pid; | 417 | int old = audit_pid; |
| 425 | audit_pid = status_get->pid; | 418 | audit_pid = status_get->pid; |
| 426 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 419 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 427 | "audit_pid=%d old=%d by auid=%u", | 420 | "audit_pid=%d old=%d by auid=%u", |
| 428 | audit_pid, old, loginuid); | 421 | audit_pid, old, loginuid); |
| 429 | } | 422 | } |
| @@ -435,15 +428,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 435 | break; | 428 | break; |
| 436 | case AUDIT_USER: | 429 | case AUDIT_USER: |
| 437 | case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: | 430 | case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: |
| 438 | ab = audit_log_start(NULL, msg_type); | 431 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
| 439 | if (!ab) | 432 | return 0; |
| 440 | break; /* audit_panic has been called */ | 433 | |
| 441 | audit_log_format(ab, | 434 | err = audit_filter_user(&NETLINK_CB(skb), msg_type); |
| 442 | "user pid=%d uid=%u auid=%u" | 435 | if (err == 1) { |
| 443 | " msg='%.1024s'", | 436 | err = 0; |
| 444 | pid, uid, loginuid, (char *)data); | 437 | ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 445 | audit_set_pid(ab, pid); | 438 | if (ab) { |
| 446 | audit_log_end(ab); | 439 | audit_log_format(ab, |
| 440 | "user pid=%d uid=%u auid=%u msg='%.1024s'", | ||
| 441 | pid, uid, loginuid, (char *)data); | ||
| 442 | audit_set_pid(ab, pid); | ||
| 443 | audit_log_end(ab); | ||
| 444 | } | ||
| 445 | } | ||
| 447 | break; | 446 | break; |
| 448 | case AUDIT_ADD: | 447 | case AUDIT_ADD: |
| 449 | case AUDIT_DEL: | 448 | case AUDIT_DEL: |
| @@ -523,7 +522,7 @@ static int __init audit_init(void) | |||
| 523 | skb_queue_head_init(&audit_skb_queue); | 522 | skb_queue_head_init(&audit_skb_queue); |
| 524 | audit_initialized = 1; | 523 | audit_initialized = 1; |
| 525 | audit_enabled = audit_default; | 524 | audit_enabled = audit_default; |
| 526 | audit_log(NULL, AUDIT_KERNEL, "initialized"); | 525 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); |
| 527 | return 0; | 526 | return 0; |
| 528 | } | 527 | } |
| 529 | __initcall(audit_init); | 528 | __initcall(audit_init); |
| @@ -561,7 +560,7 @@ static void audit_buffer_free(struct audit_buffer *ab) | |||
| 561 | } | 560 | } |
| 562 | 561 | ||
| 563 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | 562 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, |
| 564 | int gfp_mask, int type) | 563 | unsigned int __nocast gfp_mask, int type) |
| 565 | { | 564 | { |
| 566 | unsigned long flags; | 565 | unsigned long flags; |
| 567 | struct audit_buffer *ab = NULL; | 566 | struct audit_buffer *ab = NULL; |
| @@ -587,6 +586,7 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | |||
| 587 | goto err; | 586 | goto err; |
| 588 | 587 | ||
| 589 | ab->ctx = ctx; | 588 | ab->ctx = ctx; |
| 589 | ab->gfp_mask = gfp_mask; | ||
| 590 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); | 590 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); |
| 591 | nlh->nlmsg_type = type; | 591 | nlh->nlmsg_type = type; |
| 592 | nlh->nlmsg_flags = 0; | 592 | nlh->nlmsg_flags = 0; |
| @@ -606,26 +606,27 @@ err: | |||
| 606 | * (timestamp,serial) tuple is unique for each syscall and is live from | 606 | * (timestamp,serial) tuple is unique for each syscall and is live from |
| 607 | * syscall entry to syscall exit. | 607 | * syscall entry to syscall exit. |
| 608 | * | 608 | * |
| 609 | * Atomic values are only guaranteed to be 24-bit, so we count down. | ||
| 610 | * | ||
| 611 | * NOTE: Another possibility is to store the formatted records off the | 609 | * NOTE: Another possibility is to store the formatted records off the |
| 612 | * audit context (for those records that have a context), and emit them | 610 | * audit context (for those records that have a context), and emit them |
| 613 | * all at syscall exit. However, this could delay the reporting of | 611 | * all at syscall exit. However, this could delay the reporting of |
| 614 | * significant errors until syscall exit (or never, if the system | 612 | * significant errors until syscall exit (or never, if the system |
| 615 | * halts). */ | 613 | * halts). */ |
| 614 | |||
| 616 | unsigned int audit_serial(void) | 615 | unsigned int audit_serial(void) |
| 617 | { | 616 | { |
| 618 | static atomic_t serial = ATOMIC_INIT(0xffffff); | 617 | static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED; |
| 619 | unsigned int a, b; | 618 | static unsigned int serial = 0; |
| 619 | |||
| 620 | unsigned long flags; | ||
| 621 | unsigned int ret; | ||
| 620 | 622 | ||
| 623 | spin_lock_irqsave(&serial_lock, flags); | ||
| 621 | do { | 624 | do { |
| 622 | a = atomic_read(&serial); | 625 | ret = ++serial; |
| 623 | if (atomic_dec_and_test(&serial)) | 626 | } while (unlikely(!ret)); |
| 624 | atomic_set(&serial, 0xffffff); | 627 | spin_unlock_irqrestore(&serial_lock, flags); |
| 625 | b = atomic_read(&serial); | ||
| 626 | } while (b != a - 1); | ||
| 627 | 628 | ||
| 628 | return 0xffffff - b; | 629 | return ret; |
| 629 | } | 630 | } |
| 630 | 631 | ||
| 631 | static inline void audit_get_stamp(struct audit_context *ctx, | 632 | static inline void audit_get_stamp(struct audit_context *ctx, |
| @@ -645,17 +646,43 @@ static inline void audit_get_stamp(struct audit_context *ctx, | |||
| 645 | * syscall, then the syscall is marked as auditable and an audit record | 646 | * syscall, then the syscall is marked as auditable and an audit record |
| 646 | * will be written at syscall exit. If there is no associated task, tsk | 647 | * will be written at syscall exit. If there is no associated task, tsk |
| 647 | * should be NULL. */ | 648 | * should be NULL. */ |
| 648 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) | 649 | |
| 650 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, | ||
| 651 | int type) | ||
| 649 | { | 652 | { |
| 650 | struct audit_buffer *ab = NULL; | 653 | struct audit_buffer *ab = NULL; |
| 651 | struct timespec t; | 654 | struct timespec t; |
| 652 | unsigned int serial; | 655 | unsigned int serial; |
| 656 | int reserve; | ||
| 657 | unsigned long timeout_start = jiffies; | ||
| 653 | 658 | ||
| 654 | if (!audit_initialized) | 659 | if (!audit_initialized) |
| 655 | return NULL; | 660 | return NULL; |
| 656 | 661 | ||
| 657 | if (audit_backlog_limit | 662 | if (gfp_mask & __GFP_WAIT) |
| 658 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) { | 663 | reserve = 0; |
| 664 | else | ||
| 665 | reserve = 5; /* Allow atomic callers to go up to five | ||
| 666 | entries over the normal backlog limit */ | ||
| 667 | |||
| 668 | while (audit_backlog_limit | ||
| 669 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { | ||
| 670 | if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time | ||
| 671 | && time_before(jiffies, timeout_start + audit_backlog_wait_time)) { | ||
| 672 | |||
| 673 | /* Wait for auditd to drain the queue a little */ | ||
| 674 | DECLARE_WAITQUEUE(wait, current); | ||
| 675 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 676 | add_wait_queue(&audit_backlog_wait, &wait); | ||
| 677 | |||
| 678 | if (audit_backlog_limit && | ||
| 679 | skb_queue_len(&audit_skb_queue) > audit_backlog_limit) | ||
| 680 | schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies); | ||
| 681 | |||
| 682 | __set_current_state(TASK_RUNNING); | ||
| 683 | remove_wait_queue(&audit_backlog_wait, &wait); | ||
| 684 | continue; | ||
| 685 | } | ||
| 659 | if (audit_rate_check()) | 686 | if (audit_rate_check()) |
| 660 | printk(KERN_WARNING | 687 | printk(KERN_WARNING |
| 661 | "audit: audit_backlog=%d > " | 688 | "audit: audit_backlog=%d > " |
| @@ -663,10 +690,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) | |||
| 663 | skb_queue_len(&audit_skb_queue), | 690 | skb_queue_len(&audit_skb_queue), |
| 664 | audit_backlog_limit); | 691 | audit_backlog_limit); |
| 665 | audit_log_lost("backlog limit exceeded"); | 692 | audit_log_lost("backlog limit exceeded"); |
| 693 | audit_backlog_wait_time = audit_backlog_wait_overflow; | ||
| 694 | wake_up(&audit_backlog_wait); | ||
| 666 | return NULL; | 695 | return NULL; |
| 667 | } | 696 | } |
| 668 | 697 | ||
| 669 | ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type); | 698 | ab = audit_buffer_alloc(ctx, gfp_mask, type); |
| 670 | if (!ab) { | 699 | if (!ab) { |
| 671 | audit_log_lost("out of memory in audit_log_start"); | 700 | audit_log_lost("out of memory in audit_log_start"); |
| 672 | return NULL; | 701 | return NULL; |
| @@ -690,7 +719,7 @@ static inline int audit_expand(struct audit_buffer *ab, int extra) | |||
| 690 | { | 719 | { |
| 691 | struct sk_buff *skb = ab->skb; | 720 | struct sk_buff *skb = ab->skb; |
| 692 | int ret = pskb_expand_head(skb, skb_headroom(skb), extra, | 721 | int ret = pskb_expand_head(skb, skb_headroom(skb), extra, |
| 693 | GFP_ATOMIC); | 722 | ab->gfp_mask); |
| 694 | if (ret < 0) { | 723 | if (ret < 0) { |
| 695 | audit_log_lost("out of memory in audit_expand"); | 724 | audit_log_lost("out of memory in audit_expand"); |
| 696 | return 0; | 725 | return 0; |
| @@ -809,7 +838,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | |||
| 809 | audit_log_format(ab, " %s", prefix); | 838 | audit_log_format(ab, " %s", prefix); |
| 810 | 839 | ||
| 811 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 840 | /* We will allow 11 spaces for ' (deleted)' to be appended */ |
| 812 | path = kmalloc(PATH_MAX+11, GFP_KERNEL); | 841 | path = kmalloc(PATH_MAX+11, ab->gfp_mask); |
| 813 | if (!path) { | 842 | if (!path) { |
| 814 | audit_log_format(ab, "<no memory>"); | 843 | audit_log_format(ab, "<no memory>"); |
| 815 | return; | 844 | return; |
| @@ -841,7 +870,7 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 841 | ab->skb = NULL; | 870 | ab->skb = NULL; |
| 842 | wake_up_interruptible(&kauditd_wait); | 871 | wake_up_interruptible(&kauditd_wait); |
| 843 | } else { | 872 | } else { |
| 844 | printk("%s\n", ab->skb->data + NLMSG_SPACE(0)); | 873 | printk(KERN_NOTICE "%s\n", ab->skb->data + NLMSG_SPACE(0)); |
| 845 | } | 874 | } |
| 846 | } | 875 | } |
| 847 | audit_buffer_free(ab); | 876 | audit_buffer_free(ab); |
| @@ -850,12 +879,13 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 850 | /* Log an audit record. This is a convenience function that calls | 879 | /* Log an audit record. This is a convenience function that calls |
| 851 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be | 880 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be |
| 852 | * called in any context. */ | 881 | * called in any context. */ |
| 853 | void audit_log(struct audit_context *ctx, int type, const char *fmt, ...) | 882 | void audit_log(struct audit_context *ctx, int gfp_mask, int type, |
| 883 | const char *fmt, ...) | ||
| 854 | { | 884 | { |
| 855 | struct audit_buffer *ab; | 885 | struct audit_buffer *ab; |
| 856 | va_list args; | 886 | va_list args; |
| 857 | 887 | ||
| 858 | ab = audit_log_start(ctx, type); | 888 | ab = audit_log_start(ctx, gfp_mask, type); |
| 859 | if (ab) { | 889 | if (ab) { |
| 860 | va_start(args, fmt); | 890 | va_start(args, fmt); |
| 861 | audit_log_vformat(ab, fmt, args); | 891 | audit_log_vformat(ab, fmt, args); |
