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