diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 60 | ||||
-rw-r--r-- | kernel/auditsc.c | 14 |
2 files changed, 52 insertions, 22 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 09a37581213b..644ab825118b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -106,6 +106,7 @@ static LIST_HEAD(audit_freelist); | |||
106 | static struct sk_buff_head audit_skb_queue; | 106 | static struct sk_buff_head audit_skb_queue; |
107 | static struct task_struct *kauditd_task; | 107 | static struct task_struct *kauditd_task; |
108 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 108 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
109 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | ||
109 | 110 | ||
110 | /* The netlink socket is only to be read by 1 CPU, which lets us assume | 111 | /* The netlink socket is only to be read by 1 CPU, which lets us assume |
111 | * that list additions and deletions never happen simultaneously in | 112 | * that list additions and deletions never happen simultaneously in |
@@ -130,6 +131,7 @@ struct audit_buffer { | |||
130 | struct list_head list; | 131 | struct list_head list; |
131 | struct sk_buff *skb; /* formatted skb ready to send */ | 132 | struct sk_buff *skb; /* formatted skb ready to send */ |
132 | struct audit_context *ctx; /* NULL or associated context */ | 133 | struct audit_context *ctx; /* NULL or associated context */ |
134 | int gfp_mask; | ||
133 | }; | 135 | }; |
134 | 136 | ||
135 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | 137 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) |
@@ -226,7 +228,7 @@ static int audit_set_rate_limit(int limit, uid_t loginuid) | |||
226 | { | 228 | { |
227 | int old = audit_rate_limit; | 229 | int old = audit_rate_limit; |
228 | audit_rate_limit = limit; | 230 | audit_rate_limit = limit; |
229 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 231 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
230 | "audit_rate_limit=%d old=%d by auid=%u", | 232 | "audit_rate_limit=%d old=%d by auid=%u", |
231 | audit_rate_limit, old, loginuid); | 233 | audit_rate_limit, old, loginuid); |
232 | return old; | 234 | return old; |
@@ -236,7 +238,7 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid) | |||
236 | { | 238 | { |
237 | int old = audit_backlog_limit; | 239 | int old = audit_backlog_limit; |
238 | audit_backlog_limit = limit; | 240 | audit_backlog_limit = limit; |
239 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 241 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
240 | "audit_backlog_limit=%d old=%d by auid=%u", | 242 | "audit_backlog_limit=%d old=%d by auid=%u", |
241 | audit_backlog_limit, old, loginuid); | 243 | audit_backlog_limit, old, loginuid); |
242 | return old; | 244 | return old; |
@@ -248,7 +250,7 @@ static int audit_set_enabled(int state, uid_t loginuid) | |||
248 | if (state != 0 && state != 1) | 250 | if (state != 0 && state != 1) |
249 | return -EINVAL; | 251 | return -EINVAL; |
250 | audit_enabled = state; | 252 | audit_enabled = state; |
251 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 253 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
252 | "audit_enabled=%d old=%d by auid=%u", | 254 | "audit_enabled=%d old=%d by auid=%u", |
253 | audit_enabled, old, loginuid); | 255 | audit_enabled, old, loginuid); |
254 | return old; | 256 | return old; |
@@ -262,7 +264,7 @@ static int audit_set_failure(int state, uid_t loginuid) | |||
262 | && state != AUDIT_FAIL_PANIC) | 264 | && state != AUDIT_FAIL_PANIC) |
263 | return -EINVAL; | 265 | return -EINVAL; |
264 | audit_failure = state; | 266 | audit_failure = state; |
265 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 267 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
266 | "audit_failure=%d old=%d by auid=%u", | 268 | "audit_failure=%d old=%d by auid=%u", |
267 | audit_failure, old, loginuid); | 269 | audit_failure, old, loginuid); |
268 | return old; | 270 | return old; |
@@ -274,6 +276,7 @@ int kauditd_thread(void *dummy) | |||
274 | 276 | ||
275 | while (1) { | 277 | while (1) { |
276 | skb = skb_dequeue(&audit_skb_queue); | 278 | skb = skb_dequeue(&audit_skb_queue); |
279 | wake_up(&audit_backlog_wait); | ||
277 | if (skb) { | 280 | if (skb) { |
278 | if (audit_pid) { | 281 | if (audit_pid) { |
279 | int err = netlink_unicast(audit_sock, skb, audit_pid, 0); | 282 | int err = netlink_unicast(audit_sock, skb, audit_pid, 0); |
@@ -417,7 +420,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
417 | if (status_get->mask & AUDIT_STATUS_PID) { | 420 | if (status_get->mask & AUDIT_STATUS_PID) { |
418 | int old = audit_pid; | 421 | int old = audit_pid; |
419 | audit_pid = status_get->pid; | 422 | audit_pid = status_get->pid; |
420 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 423 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
421 | "audit_pid=%d old=%d by auid=%u", | 424 | "audit_pid=%d old=%d by auid=%u", |
422 | audit_pid, old, loginuid); | 425 | audit_pid, old, loginuid); |
423 | } | 426 | } |
@@ -435,7 +438,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
435 | err = audit_filter_user(pid, msg_type); | 438 | err = audit_filter_user(pid, msg_type); |
436 | if (err == 1) { | 439 | if (err == 1) { |
437 | err = 0; | 440 | err = 0; |
438 | ab = audit_log_start(NULL, msg_type); | 441 | ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
439 | if (ab) { | 442 | if (ab) { |
440 | audit_log_format(ab, | 443 | audit_log_format(ab, |
441 | "user pid=%d uid=%u auid=%u msg='%.1024s'", | 444 | "user pid=%d uid=%u auid=%u msg='%.1024s'", |
@@ -522,7 +525,7 @@ static int __init audit_init(void) | |||
522 | skb_queue_head_init(&audit_skb_queue); | 525 | skb_queue_head_init(&audit_skb_queue); |
523 | audit_initialized = 1; | 526 | audit_initialized = 1; |
524 | audit_enabled = audit_default; | 527 | audit_enabled = audit_default; |
525 | audit_log(NULL, AUDIT_KERNEL, "initialized"); | 528 | audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); |
526 | return 0; | 529 | return 0; |
527 | } | 530 | } |
528 | __initcall(audit_init); | 531 | __initcall(audit_init); |
@@ -586,6 +589,7 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | |||
586 | goto err; | 589 | goto err; |
587 | 590 | ||
588 | ab->ctx = ctx; | 591 | ab->ctx = ctx; |
592 | ab->gfp_mask = gfp_mask; | ||
589 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); | 593 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); |
590 | nlh->nlmsg_type = type; | 594 | nlh->nlmsg_type = type; |
591 | nlh->nlmsg_flags = 0; | 595 | nlh->nlmsg_flags = 0; |
@@ -644,17 +648,42 @@ static inline void audit_get_stamp(struct audit_context *ctx, | |||
644 | * syscall, then the syscall is marked as auditable and an audit record | 648 | * syscall, then the syscall is marked as auditable and an audit record |
645 | * will be written at syscall exit. If there is no associated task, tsk | 649 | * will be written at syscall exit. If there is no associated task, tsk |
646 | * should be NULL. */ | 650 | * should be NULL. */ |
647 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) | 651 | |
652 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask, | ||
653 | int type) | ||
648 | { | 654 | { |
649 | struct audit_buffer *ab = NULL; | 655 | struct audit_buffer *ab = NULL; |
650 | struct timespec t; | 656 | struct timespec t; |
651 | unsigned int serial; | 657 | unsigned int serial; |
658 | int reserve; | ||
652 | 659 | ||
653 | if (!audit_initialized) | 660 | if (!audit_initialized) |
654 | return NULL; | 661 | return NULL; |
655 | 662 | ||
656 | if (audit_backlog_limit | 663 | if (gfp_mask & __GFP_WAIT) |
657 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) { | 664 | reserve = 0; |
665 | else | ||
666 | reserve = 5; /* Allow atomic callers to go up to five | ||
667 | entries over the normal backlog limit */ | ||
668 | |||
669 | while (audit_backlog_limit | ||
670 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { | ||
671 | if (gfp_mask & __GFP_WAIT) { | ||
672 | int ret = 1; | ||
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 | ret = schedule_timeout(HZ * 60); | ||
681 | |||
682 | __set_current_state(TASK_RUNNING); | ||
683 | remove_wait_queue(&audit_backlog_wait, &wait); | ||
684 | if (ret) | ||
685 | continue; | ||
686 | } | ||
658 | if (audit_rate_check()) | 687 | if (audit_rate_check()) |
659 | printk(KERN_WARNING | 688 | printk(KERN_WARNING |
660 | "audit: audit_backlog=%d > " | 689 | "audit: audit_backlog=%d > " |
@@ -665,7 +694,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) | |||
665 | return NULL; | 694 | return NULL; |
666 | } | 695 | } |
667 | 696 | ||
668 | ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type); | 697 | ab = audit_buffer_alloc(ctx, gfp_mask, type); |
669 | if (!ab) { | 698 | if (!ab) { |
670 | audit_log_lost("out of memory in audit_log_start"); | 699 | audit_log_lost("out of memory in audit_log_start"); |
671 | return NULL; | 700 | return NULL; |
@@ -689,7 +718,7 @@ static inline int audit_expand(struct audit_buffer *ab, int extra) | |||
689 | { | 718 | { |
690 | struct sk_buff *skb = ab->skb; | 719 | struct sk_buff *skb = ab->skb; |
691 | int ret = pskb_expand_head(skb, skb_headroom(skb), extra, | 720 | int ret = pskb_expand_head(skb, skb_headroom(skb), extra, |
692 | GFP_ATOMIC); | 721 | ab->gfp_mask); |
693 | if (ret < 0) { | 722 | if (ret < 0) { |
694 | audit_log_lost("out of memory in audit_expand"); | 723 | audit_log_lost("out of memory in audit_expand"); |
695 | return 0; | 724 | return 0; |
@@ -808,7 +837,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | |||
808 | audit_log_format(ab, " %s", prefix); | 837 | audit_log_format(ab, " %s", prefix); |
809 | 838 | ||
810 | /* We will allow 11 spaces for ' (deleted)' to be appended */ | 839 | /* We will allow 11 spaces for ' (deleted)' to be appended */ |
811 | path = kmalloc(PATH_MAX+11, GFP_KERNEL); | 840 | path = kmalloc(PATH_MAX+11, ab->gfp_mask); |
812 | if (!path) { | 841 | if (!path) { |
813 | audit_log_format(ab, "<no memory>"); | 842 | audit_log_format(ab, "<no memory>"); |
814 | return; | 843 | return; |
@@ -849,12 +878,13 @@ void audit_log_end(struct audit_buffer *ab) | |||
849 | /* Log an audit record. This is a convenience function that calls | 878 | /* Log an audit record. This is a convenience function that calls |
850 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be | 879 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be |
851 | * called in any context. */ | 880 | * called in any context. */ |
852 | void audit_log(struct audit_context *ctx, int type, const char *fmt, ...) | 881 | void audit_log(struct audit_context *ctx, int gfp_mask, int type, |
882 | const char *fmt, ...) | ||
853 | { | 883 | { |
854 | struct audit_buffer *ab; | 884 | struct audit_buffer *ab; |
855 | va_list args; | 885 | va_list args; |
856 | 886 | ||
857 | ab = audit_log_start(ctx, type); | 887 | ab = audit_log_start(ctx, gfp_mask, type); |
858 | if (ab) { | 888 | if (ab) { |
859 | va_start(args, fmt); | 889 | va_start(args, fmt); |
860 | audit_log_vformat(ab, fmt, args); | 890 | audit_log_vformat(ab, fmt, args); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fc858b0c044a..f463fd230846 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -346,7 +346,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
346 | } | 346 | } |
347 | listnr = entry->rule.flags & ~AUDIT_FILTER_PREPEND; | 347 | listnr = entry->rule.flags & ~AUDIT_FILTER_PREPEND; |
348 | audit_add_rule(entry, &audit_filter_list[listnr]); | 348 | audit_add_rule(entry, &audit_filter_list[listnr]); |
349 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 349 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
350 | "auid=%u added an audit rule\n", loginuid); | 350 | "auid=%u added an audit rule\n", loginuid); |
351 | break; | 351 | break; |
352 | case AUDIT_DEL: | 352 | case AUDIT_DEL: |
@@ -356,7 +356,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
356 | 356 | ||
357 | err = audit_del_rule(data, &audit_filter_list[listnr]); | 357 | err = audit_del_rule(data, &audit_filter_list[listnr]); |
358 | if (!err) | 358 | if (!err) |
359 | audit_log(NULL, AUDIT_CONFIG_CHANGE, | 359 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
360 | "auid=%u removed an audit rule\n", loginuid); | 360 | "auid=%u removed an audit rule\n", loginuid); |
361 | break; | 361 | break; |
362 | default: | 362 | default: |
@@ -756,7 +756,7 @@ static void audit_log_exit(struct audit_context *context) | |||
756 | struct audit_buffer *ab; | 756 | struct audit_buffer *ab; |
757 | struct audit_aux_data *aux; | 757 | struct audit_aux_data *aux; |
758 | 758 | ||
759 | ab = audit_log_start(context, AUDIT_SYSCALL); | 759 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
760 | if (!ab) | 760 | if (!ab) |
761 | return; /* audit_panic has been called */ | 761 | return; /* audit_panic has been called */ |
762 | audit_log_format(ab, "arch=%x syscall=%d", | 762 | audit_log_format(ab, "arch=%x syscall=%d", |
@@ -788,7 +788,7 @@ static void audit_log_exit(struct audit_context *context) | |||
788 | 788 | ||
789 | for (aux = context->aux; aux; aux = aux->next) { | 789 | for (aux = context->aux; aux; aux = aux->next) { |
790 | 790 | ||
791 | ab = audit_log_start(context, aux->type); | 791 | ab = audit_log_start(context, GFP_KERNEL, aux->type); |
792 | if (!ab) | 792 | if (!ab) |
793 | continue; /* audit_panic has been called */ | 793 | continue; /* audit_panic has been called */ |
794 | 794 | ||
@@ -825,14 +825,14 @@ static void audit_log_exit(struct audit_context *context) | |||
825 | } | 825 | } |
826 | 826 | ||
827 | if (context->pwd && context->pwdmnt) { | 827 | if (context->pwd && context->pwdmnt) { |
828 | ab = audit_log_start(context, AUDIT_CWD); | 828 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); |
829 | if (ab) { | 829 | if (ab) { |
830 | audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt); | 830 | audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt); |
831 | audit_log_end(ab); | 831 | audit_log_end(ab); |
832 | } | 832 | } |
833 | } | 833 | } |
834 | for (i = 0; i < context->name_count; i++) { | 834 | for (i = 0; i < context->name_count; i++) { |
835 | ab = audit_log_start(context, AUDIT_PATH); | 835 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); |
836 | if (!ab) | 836 | if (!ab) |
837 | continue; /* audit_panic has been called */ | 837 | continue; /* audit_panic has been called */ |
838 | 838 | ||
@@ -1118,7 +1118,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid) | |||
1118 | if (task->audit_context) { | 1118 | if (task->audit_context) { |
1119 | struct audit_buffer *ab; | 1119 | struct audit_buffer *ab; |
1120 | 1120 | ||
1121 | ab = audit_log_start(NULL, AUDIT_LOGIN); | 1121 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
1122 | if (ab) { | 1122 | if (ab) { |
1123 | audit_log_format(ab, "login pid=%d uid=%u " | 1123 | audit_log_format(ab, "login pid=%d uid=%u " |
1124 | "old auid=%u new auid=%u", | 1124 | "old auid=%u new auid=%u", |