diff options
Diffstat (limited to 'kernel/audit.c')
| -rw-r--r-- | kernel/audit.c | 97 |
1 files changed, 89 insertions, 8 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index d13276d41410..eb0f9165b401 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/selinux.h> | 58 | #include <linux/selinux.h> |
| 59 | #include <linux/inotify.h> | 59 | #include <linux/inotify.h> |
| 60 | #include <linux/freezer.h> | 60 | #include <linux/freezer.h> |
| 61 | #include <linux/tty.h> | ||
| 61 | 62 | ||
| 62 | #include "audit.h" | 63 | #include "audit.h" |
| 63 | 64 | ||
| @@ -391,6 +392,7 @@ static int kauditd_thread(void *dummy) | |||
| 391 | { | 392 | { |
| 392 | struct sk_buff *skb; | 393 | struct sk_buff *skb; |
| 393 | 394 | ||
| 395 | set_freezable(); | ||
| 394 | while (!kthread_should_stop()) { | 396 | while (!kthread_should_stop()) { |
| 395 | skb = skb_dequeue(&audit_skb_queue); | 397 | skb = skb_dequeue(&audit_skb_queue); |
| 396 | wake_up(&audit_backlog_wait); | 398 | wake_up(&audit_backlog_wait); |
| @@ -423,6 +425,31 @@ static int kauditd_thread(void *dummy) | |||
| 423 | return 0; | 425 | return 0; |
| 424 | } | 426 | } |
| 425 | 427 | ||
| 428 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid) | ||
| 429 | { | ||
| 430 | struct task_struct *tsk; | ||
| 431 | int err; | ||
| 432 | |||
| 433 | read_lock(&tasklist_lock); | ||
| 434 | tsk = find_task_by_pid(pid); | ||
| 435 | err = -ESRCH; | ||
| 436 | if (!tsk) | ||
| 437 | goto out; | ||
| 438 | err = 0; | ||
| 439 | |||
| 440 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 441 | if (!tsk->signal->audit_tty) | ||
| 442 | err = -EPERM; | ||
| 443 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 444 | if (err) | ||
| 445 | goto out; | ||
| 446 | |||
| 447 | tty_audit_push_task(tsk, loginuid); | ||
| 448 | out: | ||
| 449 | read_unlock(&tasklist_lock); | ||
| 450 | return err; | ||
| 451 | } | ||
| 452 | |||
| 426 | int audit_send_list(void *_dest) | 453 | int audit_send_list(void *_dest) |
| 427 | { | 454 | { |
| 428 | struct audit_netlink_list *dest = _dest; | 455 | struct audit_netlink_list *dest = _dest; |
| @@ -511,6 +538,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 511 | case AUDIT_DEL: | 538 | case AUDIT_DEL: |
| 512 | case AUDIT_DEL_RULE: | 539 | case AUDIT_DEL_RULE: |
| 513 | case AUDIT_SIGNAL_INFO: | 540 | case AUDIT_SIGNAL_INFO: |
| 541 | case AUDIT_TTY_GET: | ||
| 542 | case AUDIT_TTY_SET: | ||
| 514 | if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) | 543 | if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) |
| 515 | err = -EPERM; | 544 | err = -EPERM; |
| 516 | break; | 545 | break; |
| @@ -622,6 +651,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 622 | err = audit_filter_user(&NETLINK_CB(skb), msg_type); | 651 | err = audit_filter_user(&NETLINK_CB(skb), msg_type); |
| 623 | if (err == 1) { | 652 | if (err == 1) { |
| 624 | err = 0; | 653 | err = 0; |
| 654 | if (msg_type == AUDIT_USER_TTY) { | ||
| 655 | err = audit_prepare_user_tty(pid, loginuid); | ||
| 656 | if (err) | ||
| 657 | break; | ||
| 658 | } | ||
| 625 | ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 659 | ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 626 | if (ab) { | 660 | if (ab) { |
| 627 | audit_log_format(ab, | 661 | audit_log_format(ab, |
| @@ -638,8 +672,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 638 | " subj=%s", ctx); | 672 | " subj=%s", ctx); |
| 639 | kfree(ctx); | 673 | kfree(ctx); |
| 640 | } | 674 | } |
| 641 | audit_log_format(ab, " msg='%.1024s'", | 675 | if (msg_type != AUDIT_USER_TTY) |
| 642 | (char *)data); | 676 | audit_log_format(ab, " msg='%.1024s'", |
| 677 | (char *)data); | ||
| 678 | else { | ||
| 679 | int size; | ||
| 680 | |||
| 681 | audit_log_format(ab, " msg="); | ||
| 682 | size = nlmsg_len(nlh); | ||
| 683 | audit_log_n_untrustedstring(ab, size, | ||
| 684 | data); | ||
| 685 | } | ||
| 643 | audit_set_pid(ab, pid); | 686 | audit_set_pid(ab, pid); |
| 644 | audit_log_end(ab); | 687 | audit_log_end(ab); |
| 645 | } | 688 | } |
| @@ -730,6 +773,45 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 730 | 0, 0, sig_data, sizeof(*sig_data) + len); | 773 | 0, 0, sig_data, sizeof(*sig_data) + len); |
| 731 | kfree(sig_data); | 774 | kfree(sig_data); |
| 732 | break; | 775 | break; |
| 776 | case AUDIT_TTY_GET: { | ||
| 777 | struct audit_tty_status s; | ||
| 778 | struct task_struct *tsk; | ||
| 779 | |||
| 780 | read_lock(&tasklist_lock); | ||
| 781 | tsk = find_task_by_pid(pid); | ||
| 782 | if (!tsk) | ||
| 783 | err = -ESRCH; | ||
| 784 | else { | ||
| 785 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 786 | s.enabled = tsk->signal->audit_tty != 0; | ||
| 787 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 788 | } | ||
| 789 | read_unlock(&tasklist_lock); | ||
| 790 | audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0, | ||
| 791 | &s, sizeof(s)); | ||
| 792 | break; | ||
| 793 | } | ||
| 794 | case AUDIT_TTY_SET: { | ||
| 795 | struct audit_tty_status *s; | ||
| 796 | struct task_struct *tsk; | ||
| 797 | |||
| 798 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | ||
| 799 | return -EINVAL; | ||
| 800 | s = data; | ||
| 801 | if (s->enabled != 0 && s->enabled != 1) | ||
| 802 | return -EINVAL; | ||
| 803 | read_lock(&tasklist_lock); | ||
| 804 | tsk = find_task_by_pid(pid); | ||
| 805 | if (!tsk) | ||
| 806 | err = -ESRCH; | ||
| 807 | else { | ||
| 808 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 809 | tsk->signal->audit_tty = s->enabled != 0; | ||
| 810 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 811 | } | ||
| 812 | read_unlock(&tasklist_lock); | ||
| 813 | break; | ||
| 814 | } | ||
| 733 | default: | 815 | default: |
| 734 | err = -EINVAL; | 816 | err = -EINVAL; |
| 735 | break; | 817 | break; |
| @@ -1185,7 +1267,7 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
| 1185 | } | 1267 | } |
| 1186 | 1268 | ||
| 1187 | /** | 1269 | /** |
| 1188 | * audit_log_n_unstrustedstring - log a string that may contain random characters | 1270 | * audit_log_n_untrustedstring - log a string that may contain random characters |
| 1189 | * @ab: audit_buffer | 1271 | * @ab: audit_buffer |
| 1190 | * @len: lenth of string (not including trailing null) | 1272 | * @len: lenth of string (not including trailing null) |
| 1191 | * @string: string to be logged | 1273 | * @string: string to be logged |
| @@ -1201,25 +1283,24 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | |||
| 1201 | const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | 1283 | const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, |
| 1202 | const char *string) | 1284 | const char *string) |
| 1203 | { | 1285 | { |
| 1204 | const unsigned char *p = string; | 1286 | const unsigned char *p; |
| 1205 | 1287 | ||
| 1206 | while (*p) { | 1288 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { |
| 1207 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { | 1289 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { |
| 1208 | audit_log_hex(ab, string, len); | 1290 | audit_log_hex(ab, string, len); |
| 1209 | return string + len + 1; | 1291 | return string + len + 1; |
| 1210 | } | 1292 | } |
| 1211 | p++; | ||
| 1212 | } | 1293 | } |
| 1213 | audit_log_n_string(ab, len, string); | 1294 | audit_log_n_string(ab, len, string); |
| 1214 | return p + 1; | 1295 | return p + 1; |
| 1215 | } | 1296 | } |
| 1216 | 1297 | ||
| 1217 | /** | 1298 | /** |
| 1218 | * audit_log_unstrustedstring - log a string that may contain random characters | 1299 | * audit_log_untrustedstring - log a string that may contain random characters |
| 1219 | * @ab: audit_buffer | 1300 | * @ab: audit_buffer |
| 1220 | * @string: string to be logged | 1301 | * @string: string to be logged |
| 1221 | * | 1302 | * |
| 1222 | * Same as audit_log_n_unstrustedstring(), except that strlen is used to | 1303 | * Same as audit_log_n_untrustedstring(), except that strlen is used to |
| 1223 | * determine string length. | 1304 | * determine string length. |
| 1224 | */ | 1305 | */ |
| 1225 | const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1306 | const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
