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) |