diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 78 | ||||
-rw-r--r-- | kernel/auditsc.c | 42 |
2 files changed, 80 insertions, 40 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 187164572bd0..4e940c05ede8 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -140,6 +140,12 @@ struct audit_buffer { | |||
140 | struct audit_context *ctx; /* NULL or associated context */ | 140 | struct audit_context *ctx; /* NULL or associated context */ |
141 | }; | 141 | }; |
142 | 142 | ||
143 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | ||
144 | { | ||
145 | struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data; | ||
146 | nlh->nlmsg_pid = pid; | ||
147 | } | ||
148 | |||
143 | struct audit_entry { | 149 | struct audit_entry { |
144 | struct list_head list; | 150 | struct list_head list; |
145 | struct audit_rule rule; | 151 | struct audit_rule rule; |
@@ -233,7 +239,8 @@ static int audit_set_rate_limit(int limit, uid_t loginuid) | |||
233 | { | 239 | { |
234 | int old = audit_rate_limit; | 240 | int old = audit_rate_limit; |
235 | audit_rate_limit = limit; | 241 | audit_rate_limit = limit; |
236 | audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u", | 242 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
243 | "audit_rate_limit=%d old=%d by auid %u", | ||
237 | audit_rate_limit, old, loginuid); | 244 | audit_rate_limit, old, loginuid); |
238 | return old; | 245 | return old; |
239 | } | 246 | } |
@@ -242,7 +249,8 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid) | |||
242 | { | 249 | { |
243 | int old = audit_backlog_limit; | 250 | int old = audit_backlog_limit; |
244 | audit_backlog_limit = limit; | 251 | audit_backlog_limit = limit; |
245 | audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u", | 252 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
253 | "audit_backlog_limit=%d old=%d by auid %u", | ||
246 | audit_backlog_limit, old, loginuid); | 254 | audit_backlog_limit, old, loginuid); |
247 | return old; | 255 | return old; |
248 | } | 256 | } |
@@ -253,8 +261,9 @@ static int audit_set_enabled(int state, uid_t loginuid) | |||
253 | if (state != 0 && state != 1) | 261 | if (state != 0 && state != 1) |
254 | return -EINVAL; | 262 | return -EINVAL; |
255 | audit_enabled = state; | 263 | audit_enabled = state; |
256 | audit_log(NULL, "audit_enabled=%d old=%d by auid %u", | 264 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
257 | audit_enabled, old, loginuid); | 265 | "audit_enabled=%d old=%d by auid %u", |
266 | audit_enabled, old, loginuid); | ||
258 | return old; | 267 | return old; |
259 | } | 268 | } |
260 | 269 | ||
@@ -266,8 +275,9 @@ static int audit_set_failure(int state, uid_t loginuid) | |||
266 | && state != AUDIT_FAIL_PANIC) | 275 | && state != AUDIT_FAIL_PANIC) |
267 | return -EINVAL; | 276 | return -EINVAL; |
268 | audit_failure = state; | 277 | audit_failure = state; |
269 | audit_log(NULL, "audit_failure=%d old=%d by auid %u", | 278 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
270 | audit_failure, old, loginuid); | 279 | "audit_failure=%d old=%d by auid %u", |
280 | audit_failure, old, loginuid); | ||
271 | return old; | 281 | return old; |
272 | } | 282 | } |
273 | 283 | ||
@@ -316,6 +326,14 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type) | |||
316 | err = -EPERM; | 326 | err = -EPERM; |
317 | break; | 327 | break; |
318 | case AUDIT_USER: | 328 | case AUDIT_USER: |
329 | case AUDIT_USER_AUTH: | ||
330 | case AUDIT_USER_ACCT: | ||
331 | case AUDIT_USER_MGMT: | ||
332 | case AUDIT_CRED_ACQ: | ||
333 | case AUDIT_CRED_DISP: | ||
334 | case AUDIT_USER_START: | ||
335 | case AUDIT_USER_END: | ||
336 | case AUDIT_USER_AVC: | ||
319 | if (!cap_raised(eff_cap, CAP_AUDIT_WRITE)) | 337 | if (!cap_raised(eff_cap, CAP_AUDIT_WRITE)) |
320 | err = -EPERM; | 338 | err = -EPERM; |
321 | break; | 339 | break; |
@@ -332,6 +350,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
332 | void *data; | 350 | void *data; |
333 | struct audit_status *status_get, status_set; | 351 | struct audit_status *status_get, status_set; |
334 | int err; | 352 | int err; |
353 | struct audit_buffer *ab; | ||
335 | u16 msg_type = nlh->nlmsg_type; | 354 | u16 msg_type = nlh->nlmsg_type; |
336 | uid_t loginuid; /* loginuid of sender */ | 355 | uid_t loginuid; /* loginuid of sender */ |
337 | struct audit_sig_info sig_data; | 356 | struct audit_sig_info sig_data; |
@@ -373,7 +392,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
373 | if (status_get->mask & AUDIT_STATUS_PID) { | 392 | if (status_get->mask & AUDIT_STATUS_PID) { |
374 | int old = audit_pid; | 393 | int old = audit_pid; |
375 | audit_pid = status_get->pid; | 394 | audit_pid = status_get->pid; |
376 | audit_log(NULL, "audit_pid=%d old=%d by auid %u", | 395 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
396 | "audit_pid=%d old=%d by auid %u", | ||
377 | audit_pid, old, loginuid); | 397 | audit_pid, old, loginuid); |
378 | } | 398 | } |
379 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) | 399 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) |
@@ -383,13 +403,26 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
383 | loginuid); | 403 | loginuid); |
384 | break; | 404 | break; |
385 | case AUDIT_USER: | 405 | case AUDIT_USER: |
386 | audit_log_type(NULL, AUDIT_USER, pid, | 406 | case AUDIT_USER_AUTH: |
407 | case AUDIT_USER_ACCT: | ||
408 | case AUDIT_USER_MGMT: | ||
409 | case AUDIT_CRED_ACQ: | ||
410 | case AUDIT_CRED_DISP: | ||
411 | case AUDIT_USER_START: | ||
412 | case AUDIT_USER_END: | ||
413 | case AUDIT_USER_AVC: | ||
414 | ab = audit_log_start(NULL, msg_type); | ||
415 | if (!ab) | ||
416 | break; /* audit_panic has been called */ | ||
417 | audit_log_format(ab, | ||
387 | "user pid=%d uid=%d length=%d loginuid=%u" | 418 | "user pid=%d uid=%d length=%d loginuid=%u" |
388 | " msg='%.1024s'", | 419 | " msg='%.1024s'", |
389 | pid, uid, | 420 | pid, uid, |
390 | (int)(nlh->nlmsg_len | 421 | (int)(nlh->nlmsg_len |
391 | - ((char *)data - (char *)nlh)), | 422 | - ((char *)data - (char *)nlh)), |
392 | loginuid, (char *)data); | 423 | loginuid, (char *)data); |
424 | audit_set_pid(ab, pid); | ||
425 | audit_log_end(ab); | ||
393 | break; | 426 | break; |
394 | case AUDIT_ADD: | 427 | case AUDIT_ADD: |
395 | case AUDIT_DEL: | 428 | case AUDIT_DEL: |
@@ -504,7 +537,7 @@ static int __init audit_init(void) | |||
504 | 537 | ||
505 | audit_initialized = 1; | 538 | audit_initialized = 1; |
506 | audit_enabled = audit_default; | 539 | audit_enabled = audit_default; |
507 | audit_log(NULL, "initialized"); | 540 | audit_log(NULL, AUDIT_KERNEL, "initialized"); |
508 | return 0; | 541 | return 0; |
509 | } | 542 | } |
510 | __initcall(audit_init); | 543 | __initcall(audit_init); |
@@ -541,10 +574,12 @@ static void audit_buffer_free(struct audit_buffer *ab) | |||
541 | spin_unlock_irqrestore(&audit_freelist_lock, flags); | 574 | spin_unlock_irqrestore(&audit_freelist_lock, flags); |
542 | } | 575 | } |
543 | 576 | ||
544 | static struct audit_buffer * audit_buffer_alloc(int gfp_mask) | 577 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, |
578 | int gfp_mask, int type) | ||
545 | { | 579 | { |
546 | unsigned long flags; | 580 | unsigned long flags; |
547 | struct audit_buffer *ab = NULL; | 581 | struct audit_buffer *ab = NULL; |
582 | struct nlmsghdr *nlh; | ||
548 | 583 | ||
549 | spin_lock_irqsave(&audit_freelist_lock, flags); | 584 | spin_lock_irqsave(&audit_freelist_lock, flags); |
550 | if (!list_empty(&audit_freelist)) { | 585 | if (!list_empty(&audit_freelist)) { |
@@ -566,6 +601,12 @@ static struct audit_buffer * audit_buffer_alloc(int gfp_mask) | |||
566 | if (!ab->skb) | 601 | if (!ab->skb) |
567 | goto err; | 602 | goto err; |
568 | 603 | ||
604 | ab->ctx = ctx; | ||
605 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); | ||
606 | nlh->nlmsg_type = type; | ||
607 | nlh->nlmsg_flags = 0; | ||
608 | nlh->nlmsg_pid = 0; | ||
609 | nlh->nlmsg_seq = 0; | ||
569 | return ab; | 610 | return ab; |
570 | err: | 611 | err: |
571 | audit_buffer_free(ab); | 612 | audit_buffer_free(ab); |
@@ -578,12 +619,11 @@ err: | |||
578 | * syscall, then the syscall is marked as auditable and an audit record | 619 | * syscall, then the syscall is marked as auditable and an audit record |
579 | * will be written at syscall exit. If there is no associated task, tsk | 620 | * will be written at syscall exit. If there is no associated task, tsk |
580 | * should be NULL. */ | 621 | * should be NULL. */ |
581 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pid) | 622 | struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) |
582 | { | 623 | { |
583 | struct audit_buffer *ab = NULL; | 624 | struct audit_buffer *ab = NULL; |
584 | struct timespec t; | 625 | struct timespec t; |
585 | unsigned int serial; | 626 | unsigned int serial; |
586 | struct nlmsghdr *nlh; | ||
587 | 627 | ||
588 | if (!audit_initialized) | 628 | if (!audit_initialized) |
589 | return NULL; | 629 | return NULL; |
@@ -600,19 +640,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pi | |||
600 | return NULL; | 640 | return NULL; |
601 | } | 641 | } |
602 | 642 | ||
603 | ab = audit_buffer_alloc(GFP_ATOMIC); | 643 | ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type); |
604 | if (!ab) { | 644 | if (!ab) { |
605 | audit_log_lost("out of memory in audit_log_start"); | 645 | audit_log_lost("out of memory in audit_log_start"); |
606 | return NULL; | 646 | return NULL; |
607 | } | 647 | } |
608 | 648 | ||
609 | ab->ctx = ctx; | ||
610 | nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0)); | ||
611 | nlh->nlmsg_type = type; | ||
612 | nlh->nlmsg_flags = 0; | ||
613 | nlh->nlmsg_pid = pid; | ||
614 | nlh->nlmsg_seq = 0; | ||
615 | |||
616 | if (!audit_get_stamp(ab->ctx, &t, &serial)) { | 649 | if (!audit_get_stamp(ab->ctx, &t, &serial)) { |
617 | t = CURRENT_TIME; | 650 | t = CURRENT_TIME; |
618 | serial = 0; | 651 | serial = 0; |
@@ -809,13 +842,12 @@ void audit_log_end(struct audit_buffer *ab) | |||
809 | /* Log an audit record. This is a convenience function that calls | 842 | /* Log an audit record. This is a convenience function that calls |
810 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be | 843 | * audit_log_start, audit_log_vformat, and audit_log_end. It may be |
811 | * called in any context. */ | 844 | * called in any context. */ |
812 | void audit_log_type(struct audit_context *ctx, int type, int pid, | 845 | void audit_log(struct audit_context *ctx, int type, const char *fmt, ...) |
813 | const char *fmt, ...) | ||
814 | { | 846 | { |
815 | struct audit_buffer *ab; | 847 | struct audit_buffer *ab; |
816 | va_list args; | 848 | va_list args; |
817 | 849 | ||
818 | ab = audit_log_start(ctx, type, pid); | 850 | ab = audit_log_start(ctx, type); |
819 | if (ab) { | 851 | if (ab) { |
820 | va_start(args, fmt); | 852 | va_start(args, fmt); |
821 | audit_log_vformat(ab, fmt, args); | 853 | audit_log_vformat(ab, fmt, args); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d089263253a7..1b7c91f9d5ff 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -286,7 +286,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
286 | err = audit_add_rule(entry, &audit_entlist); | 286 | err = audit_add_rule(entry, &audit_entlist); |
287 | if (!err && (flags & AUDIT_AT_EXIT)) | 287 | if (!err && (flags & AUDIT_AT_EXIT)) |
288 | err = audit_add_rule(entry, &audit_extlist); | 288 | err = audit_add_rule(entry, &audit_extlist); |
289 | audit_log(NULL, "auid %u added an audit rule\n", loginuid); | 289 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
290 | "auid %u added an audit rule\n", loginuid); | ||
290 | break; | 291 | break; |
291 | case AUDIT_DEL: | 292 | case AUDIT_DEL: |
292 | flags =((struct audit_rule *)data)->flags; | 293 | flags =((struct audit_rule *)data)->flags; |
@@ -296,7 +297,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
296 | err = audit_del_rule(data, &audit_entlist); | 297 | err = audit_del_rule(data, &audit_entlist); |
297 | if (!err && (flags & AUDIT_AT_EXIT)) | 298 | if (!err && (flags & AUDIT_AT_EXIT)) |
298 | err = audit_del_rule(data, &audit_extlist); | 299 | err = audit_del_rule(data, &audit_extlist); |
299 | audit_log(NULL, "auid %u removed an audit rule\n", loginuid); | 300 | audit_log(NULL, AUDIT_CONFIG_CHANGE, |
301 | "auid %u removed an audit rule\n", loginuid); | ||
300 | break; | 302 | break; |
301 | default: | 303 | default: |
302 | return -EINVAL; | 304 | return -EINVAL; |
@@ -648,7 +650,7 @@ static void audit_log_exit(struct audit_context *context) | |||
648 | int i; | 650 | int i; |
649 | struct audit_buffer *ab; | 651 | struct audit_buffer *ab; |
650 | 652 | ||
651 | ab = audit_log_start(context, AUDIT_KERNEL, 0); | 653 | ab = audit_log_start(context, AUDIT_SYSCALL); |
652 | if (!ab) | 654 | if (!ab) |
653 | return; /* audit_panic has been called */ | 655 | return; /* audit_panic has been called */ |
654 | audit_log_format(ab, "syscall=%d", context->major); | 656 | audit_log_format(ab, "syscall=%d", context->major); |
@@ -680,28 +682,28 @@ static void audit_log_exit(struct audit_context *context) | |||
680 | while (context->aux) { | 682 | while (context->aux) { |
681 | struct audit_aux_data *aux; | 683 | struct audit_aux_data *aux; |
682 | 684 | ||
683 | ab = audit_log_start(context, AUDIT_KERNEL, 0); | 685 | aux = context->aux; |
686 | |||
687 | ab = audit_log_start(context, aux->type); | ||
684 | if (!ab) | 688 | if (!ab) |
685 | continue; /* audit_panic has been called */ | 689 | continue; /* audit_panic has been called */ |
686 | 690 | ||
687 | aux = context->aux; | ||
688 | context->aux = aux->next; | ||
689 | |||
690 | audit_log_format(ab, "auxitem=%d", aux->type); | ||
691 | switch (aux->type) { | 691 | switch (aux->type) { |
692 | case AUDIT_AUX_IPCPERM: { | 692 | case AUDIT_IPC: { |
693 | struct audit_aux_data_ipcctl *axi = (void *)aux; | 693 | struct audit_aux_data_ipcctl *axi = (void *)aux; |
694 | audit_log_format(ab, | 694 | audit_log_format(ab, |
695 | " qbytes=%lx uid=%d gid=%d mode=%x", | 695 | " qbytes=%lx iuid=%d igid=%d mode=%x", |
696 | axi->qbytes, axi->uid, axi->gid, axi->mode); | 696 | axi->qbytes, axi->uid, axi->gid, axi->mode); |
697 | } | 697 | } |
698 | } | 698 | } |
699 | audit_log_end(ab); | 699 | audit_log_end(ab); |
700 | |||
701 | context->aux = aux->next; | ||
700 | kfree(aux); | 702 | kfree(aux); |
701 | } | 703 | } |
702 | 704 | ||
703 | for (i = 0; i < context->name_count; i++) { | 705 | for (i = 0; i < context->name_count; i++) { |
704 | ab = audit_log_start(context, AUDIT_KERNEL, 0); | 706 | ab = audit_log_start(context, AUDIT_PATH); |
705 | if (!ab) | 707 | if (!ab) |
706 | continue; /* audit_panic has been called */ | 708 | continue; /* audit_panic has been called */ |
707 | audit_log_format(ab, "item=%d", i); | 709 | audit_log_format(ab, "item=%d", i); |
@@ -711,7 +713,7 @@ static void audit_log_exit(struct audit_context *context) | |||
711 | } | 713 | } |
712 | if (context->names[i].ino != (unsigned long)-1) | 714 | if (context->names[i].ino != (unsigned long)-1) |
713 | audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" | 715 | audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" |
714 | " uid=%d gid=%d rdev=%02x:%02x", | 716 | " ouid=%d ogid=%d rdev=%02x:%02x", |
715 | context->names[i].ino, | 717 | context->names[i].ino, |
716 | MAJOR(context->names[i].dev), | 718 | MAJOR(context->names[i].dev), |
717 | MINOR(context->names[i].dev), | 719 | MINOR(context->names[i].dev), |
@@ -1008,10 +1010,16 @@ int audit_get_stamp(struct audit_context *ctx, | |||
1008 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) | 1010 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) |
1009 | { | 1011 | { |
1010 | if (task->audit_context) { | 1012 | if (task->audit_context) { |
1011 | audit_log_type(NULL, AUDIT_LOGIN, 0, | 1013 | struct audit_buffer *ab; |
1012 | "login pid=%d uid=%u old loginuid=%u new loginuid=%u", | 1014 | |
1013 | task->pid, task->uid, task->audit_context->loginuid, | 1015 | ab = audit_log_start(NULL, AUDIT_LOGIN); |
1014 | loginuid); | 1016 | if (ab) { |
1017 | audit_log_format(ab, "login pid=%d uid=%u " | ||
1018 | "old loginuid=%u new loginuid=%u", | ||
1019 | task->pid, task->uid, | ||
1020 | task->audit_context->loginuid, loginuid); | ||
1021 | audit_log_end(ab); | ||
1022 | } | ||
1015 | task->audit_context->loginuid = loginuid; | 1023 | task->audit_context->loginuid = loginuid; |
1016 | } | 1024 | } |
1017 | return 0; | 1025 | return 0; |
@@ -1039,7 +1047,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) | |||
1039 | ax->gid = gid; | 1047 | ax->gid = gid; |
1040 | ax->mode = mode; | 1048 | ax->mode = mode; |
1041 | 1049 | ||
1042 | ax->d.type = AUDIT_AUX_IPCPERM; | 1050 | ax->d.type = AUDIT_IPC; |
1043 | ax->d.next = context->aux; | 1051 | ax->d.next = context->aux; |
1044 | context->aux = (void *)ax; | 1052 | context->aux = (void *)ax; |
1045 | return 0; | 1053 | return 0; |