diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/acct.c | 4 | ||||
-rw-r--r-- | kernel/audit.c | 121 | ||||
-rw-r--r-- | kernel/audit.h | 4 | ||||
-rw-r--r-- | kernel/audit_watch.c | 2 | ||||
-rw-r--r-- | kernel/auditfilter.c | 137 | ||||
-rw-r--r-- | kernel/auditsc.c | 219 | ||||
-rw-r--r-- | kernel/cred.c | 10 | ||||
-rw-r--r-- | kernel/pid.c | 1 | ||||
-rw-r--r-- | kernel/pid_namespace.c | 2 | ||||
-rw-r--r-- | kernel/taskstats.c | 23 | ||||
-rw-r--r-- | kernel/trace/trace.c | 3 | ||||
-rw-r--r-- | kernel/trace/trace.h | 2 | ||||
-rw-r--r-- | kernel/tsacct.c | 12 | ||||
-rw-r--r-- | kernel/user.c | 8 | ||||
-rw-r--r-- | kernel/user_namespace.c | 128 |
15 files changed, 457 insertions, 219 deletions
diff --git a/kernel/acct.c b/kernel/acct.c index 02e6167a53b..6cd7529c9e6 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -507,8 +507,8 @@ static void do_acct_process(struct bsd_acct_struct *acct, | |||
507 | do_div(elapsed, AHZ); | 507 | do_div(elapsed, AHZ); |
508 | ac.ac_btime = get_seconds() - elapsed; | 508 | ac.ac_btime = get_seconds() - elapsed; |
509 | /* we really need to bite the bullet and change layout */ | 509 | /* we really need to bite the bullet and change layout */ |
510 | ac.ac_uid = orig_cred->uid; | 510 | ac.ac_uid = from_kuid_munged(file->f_cred->user_ns, orig_cred->uid); |
511 | ac.ac_gid = orig_cred->gid; | 511 | ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid); |
512 | #if ACCT_VERSION==2 | 512 | #if ACCT_VERSION==2 |
513 | ac.ac_ahz = AHZ; | 513 | ac.ac_ahz = AHZ; |
514 | #endif | 514 | #endif |
diff --git a/kernel/audit.c b/kernel/audit.c index ea3b7b6191c..511488a7bc7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/netlink.h> | 61 | #include <linux/netlink.h> |
62 | #include <linux/freezer.h> | 62 | #include <linux/freezer.h> |
63 | #include <linux/tty.h> | 63 | #include <linux/tty.h> |
64 | #include <linux/pid_namespace.h> | ||
64 | 65 | ||
65 | #include "audit.h" | 66 | #include "audit.h" |
66 | 67 | ||
@@ -104,7 +105,7 @@ static int audit_backlog_wait_time = 60 * HZ; | |||
104 | static int audit_backlog_wait_overflow = 0; | 105 | static int audit_backlog_wait_overflow = 0; |
105 | 106 | ||
106 | /* The identity of the user shutting down the audit system. */ | 107 | /* The identity of the user shutting down the audit system. */ |
107 | uid_t audit_sig_uid = -1; | 108 | kuid_t audit_sig_uid = INVALID_UID; |
108 | pid_t audit_sig_pid = -1; | 109 | pid_t audit_sig_pid = -1; |
109 | u32 audit_sig_sid = 0; | 110 | u32 audit_sig_sid = 0; |
110 | 111 | ||
@@ -264,7 +265,7 @@ void audit_log_lost(const char *message) | |||
264 | } | 265 | } |
265 | 266 | ||
266 | static int audit_log_config_change(char *function_name, int new, int old, | 267 | static int audit_log_config_change(char *function_name, int new, int old, |
267 | uid_t loginuid, u32 sessionid, u32 sid, | 268 | kuid_t loginuid, u32 sessionid, u32 sid, |
268 | int allow_changes) | 269 | int allow_changes) |
269 | { | 270 | { |
270 | struct audit_buffer *ab; | 271 | struct audit_buffer *ab; |
@@ -272,7 +273,7 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
272 | 273 | ||
273 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
274 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, | 275 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, |
275 | old, loginuid, sessionid); | 276 | old, from_kuid(&init_user_ns, loginuid), sessionid); |
276 | if (sid) { | 277 | if (sid) { |
277 | char *ctx = NULL; | 278 | char *ctx = NULL; |
278 | u32 len; | 279 | u32 len; |
@@ -292,7 +293,7 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
292 | } | 293 | } |
293 | 294 | ||
294 | static int audit_do_config_change(char *function_name, int *to_change, | 295 | static int audit_do_config_change(char *function_name, int *to_change, |
295 | int new, uid_t loginuid, u32 sessionid, | 296 | int new, kuid_t loginuid, u32 sessionid, |
296 | u32 sid) | 297 | u32 sid) |
297 | { | 298 | { |
298 | int allow_changes, rc = 0, old = *to_change; | 299 | int allow_changes, rc = 0, old = *to_change; |
@@ -319,21 +320,21 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
319 | return rc; | 320 | return rc; |
320 | } | 321 | } |
321 | 322 | ||
322 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid, | 323 | static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid, |
323 | u32 sid) | 324 | u32 sid) |
324 | { | 325 | { |
325 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | 326 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, |
326 | limit, loginuid, sessionid, sid); | 327 | limit, loginuid, sessionid, sid); |
327 | } | 328 | } |
328 | 329 | ||
329 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid, | 330 | static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid, |
330 | u32 sid) | 331 | u32 sid) |
331 | { | 332 | { |
332 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, | 333 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, |
333 | limit, loginuid, sessionid, sid); | 334 | limit, loginuid, sessionid, sid); |
334 | } | 335 | } |
335 | 336 | ||
336 | static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) | 337 | static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid) |
337 | { | 338 | { |
338 | int rc; | 339 | int rc; |
339 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 340 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) |
@@ -348,7 +349,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) | |||
348 | return rc; | 349 | return rc; |
349 | } | 350 | } |
350 | 351 | ||
351 | static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) | 352 | static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid) |
352 | { | 353 | { |
353 | if (state != AUDIT_FAIL_SILENT | 354 | if (state != AUDIT_FAIL_SILENT |
354 | && state != AUDIT_FAIL_PRINTK | 355 | && state != AUDIT_FAIL_PRINTK |
@@ -467,24 +468,6 @@ static int kauditd_thread(void *dummy) | |||
467 | return 0; | 468 | return 0; |
468 | } | 469 | } |
469 | 470 | ||
470 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) | ||
471 | { | ||
472 | struct task_struct *tsk; | ||
473 | int err; | ||
474 | |||
475 | rcu_read_lock(); | ||
476 | tsk = find_task_by_vpid(pid); | ||
477 | if (!tsk) { | ||
478 | rcu_read_unlock(); | ||
479 | return -ESRCH; | ||
480 | } | ||
481 | get_task_struct(tsk); | ||
482 | rcu_read_unlock(); | ||
483 | err = tty_audit_push_task(tsk, loginuid, sessionid); | ||
484 | put_task_struct(tsk); | ||
485 | return err; | ||
486 | } | ||
487 | |||
488 | int audit_send_list(void *_dest) | 471 | int audit_send_list(void *_dest) |
489 | { | 472 | { |
490 | struct audit_netlink_list *dest = _dest; | 473 | struct audit_netlink_list *dest = _dest; |
@@ -588,6 +571,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
588 | { | 571 | { |
589 | int err = 0; | 572 | int err = 0; |
590 | 573 | ||
574 | /* Only support the initial namespaces for now. */ | ||
575 | if ((current_user_ns() != &init_user_ns) || | ||
576 | (task_active_pid_ns(current) != &init_pid_ns)) | ||
577 | return -EPERM; | ||
578 | |||
591 | switch (msg_type) { | 579 | switch (msg_type) { |
592 | case AUDIT_GET: | 580 | case AUDIT_GET: |
593 | case AUDIT_LIST: | 581 | case AUDIT_LIST: |
@@ -619,8 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
619 | } | 607 | } |
620 | 608 | ||
621 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | 609 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, |
622 | u32 pid, u32 uid, uid_t auid, u32 ses, | 610 | kuid_t auid, u32 ses, u32 sid) |
623 | u32 sid) | ||
624 | { | 611 | { |
625 | int rc = 0; | 612 | int rc = 0; |
626 | char *ctx = NULL; | 613 | char *ctx = NULL; |
@@ -633,7 +620,9 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
633 | 620 | ||
634 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 621 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
635 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", | 622 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", |
636 | pid, uid, auid, ses); | 623 | task_tgid_vnr(current), |
624 | from_kuid(&init_user_ns, current_uid()), | ||
625 | from_kuid(&init_user_ns, auid), ses); | ||
637 | if (sid) { | 626 | if (sid) { |
638 | rc = security_secid_to_secctx(sid, &ctx, &len); | 627 | rc = security_secid_to_secctx(sid, &ctx, &len); |
639 | if (rc) | 628 | if (rc) |
@@ -649,13 +638,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
649 | 638 | ||
650 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 639 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
651 | { | 640 | { |
652 | u32 uid, pid, seq, sid; | 641 | u32 seq, sid; |
653 | void *data; | 642 | void *data; |
654 | struct audit_status *status_get, status_set; | 643 | struct audit_status *status_get, status_set; |
655 | int err; | 644 | int err; |
656 | struct audit_buffer *ab; | 645 | struct audit_buffer *ab; |
657 | u16 msg_type = nlh->nlmsg_type; | 646 | u16 msg_type = nlh->nlmsg_type; |
658 | uid_t loginuid; /* loginuid of sender */ | 647 | kuid_t loginuid; /* loginuid of sender */ |
659 | u32 sessionid; | 648 | u32 sessionid; |
660 | struct audit_sig_info *sig_data; | 649 | struct audit_sig_info *sig_data; |
661 | char *ctx = NULL; | 650 | char *ctx = NULL; |
@@ -675,8 +664,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
675 | return err; | 664 | return err; |
676 | } | 665 | } |
677 | 666 | ||
678 | pid = NETLINK_CREDS(skb)->pid; | ||
679 | uid = NETLINK_CREDS(skb)->uid; | ||
680 | loginuid = audit_get_loginuid(current); | 667 | loginuid = audit_get_loginuid(current); |
681 | sessionid = audit_get_sessionid(current); | 668 | sessionid = audit_get_sessionid(current); |
682 | security_task_getsecid(current, &sid); | 669 | security_task_getsecid(current, &sid); |
@@ -738,16 +725,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
738 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 725 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
739 | return 0; | 726 | return 0; |
740 | 727 | ||
741 | err = audit_filter_user(&NETLINK_CB(skb)); | 728 | err = audit_filter_user(); |
742 | if (err == 1) { | 729 | if (err == 1) { |
743 | err = 0; | 730 | err = 0; |
744 | if (msg_type == AUDIT_USER_TTY) { | 731 | if (msg_type == AUDIT_USER_TTY) { |
745 | err = audit_prepare_user_tty(pid, loginuid, | 732 | err = tty_audit_push_task(current, loginuid, |
746 | sessionid); | 733 | sessionid); |
747 | if (err) | 734 | if (err) |
748 | break; | 735 | break; |
749 | } | 736 | } |
750 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, | 737 | audit_log_common_recv_msg(&ab, msg_type, |
751 | loginuid, sessionid, sid); | 738 | loginuid, sessionid, sid); |
752 | 739 | ||
753 | if (msg_type != AUDIT_USER_TTY) | 740 | if (msg_type != AUDIT_USER_TTY) |
@@ -763,7 +750,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
763 | size--; | 750 | size--; |
764 | audit_log_n_untrustedstring(ab, data, size); | 751 | audit_log_n_untrustedstring(ab, data, size); |
765 | } | 752 | } |
766 | audit_set_pid(ab, pid); | 753 | audit_set_pid(ab, NETLINK_CB(skb).pid); |
767 | audit_log_end(ab); | 754 | audit_log_end(ab); |
768 | } | 755 | } |
769 | break; | 756 | break; |
@@ -772,8 +759,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
772 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | 759 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) |
773 | return -EINVAL; | 760 | return -EINVAL; |
774 | if (audit_enabled == AUDIT_LOCKED) { | 761 | if (audit_enabled == AUDIT_LOCKED) { |
775 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 762 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, |
776 | uid, loginuid, sessionid, sid); | 763 | loginuid, sessionid, sid); |
777 | 764 | ||
778 | audit_log_format(ab, " audit_enabled=%d res=0", | 765 | audit_log_format(ab, " audit_enabled=%d res=0", |
779 | audit_enabled); | 766 | audit_enabled); |
@@ -783,7 +770,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
783 | /* fallthrough */ | 770 | /* fallthrough */ |
784 | case AUDIT_LIST: | 771 | case AUDIT_LIST: |
785 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, | 772 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, |
786 | uid, seq, data, nlmsg_len(nlh), | 773 | seq, data, nlmsg_len(nlh), |
787 | loginuid, sessionid, sid); | 774 | loginuid, sessionid, sid); |
788 | break; | 775 | break; |
789 | case AUDIT_ADD_RULE: | 776 | case AUDIT_ADD_RULE: |
@@ -791,8 +778,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
791 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 778 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
792 | return -EINVAL; | 779 | return -EINVAL; |
793 | if (audit_enabled == AUDIT_LOCKED) { | 780 | if (audit_enabled == AUDIT_LOCKED) { |
794 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 781 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, |
795 | uid, loginuid, sessionid, sid); | 782 | loginuid, sessionid, sid); |
796 | 783 | ||
797 | audit_log_format(ab, " audit_enabled=%d res=0", | 784 | audit_log_format(ab, " audit_enabled=%d res=0", |
798 | audit_enabled); | 785 | audit_enabled); |
@@ -802,14 +789,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
802 | /* fallthrough */ | 789 | /* fallthrough */ |
803 | case AUDIT_LIST_RULES: | 790 | case AUDIT_LIST_RULES: |
804 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, | 791 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid, |
805 | uid, seq, data, nlmsg_len(nlh), | 792 | seq, data, nlmsg_len(nlh), |
806 | loginuid, sessionid, sid); | 793 | loginuid, sessionid, sid); |
807 | break; | 794 | break; |
808 | case AUDIT_TRIM: | 795 | case AUDIT_TRIM: |
809 | audit_trim_trees(); | 796 | audit_trim_trees(); |
810 | 797 | ||
811 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 798 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, |
812 | uid, loginuid, sessionid, sid); | 799 | loginuid, sessionid, sid); |
813 | 800 | ||
814 | audit_log_format(ab, " op=trim res=1"); | 801 | audit_log_format(ab, " op=trim res=1"); |
815 | audit_log_end(ab); | 802 | audit_log_end(ab); |
@@ -840,8 +827,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
840 | /* OK, here comes... */ | 827 | /* OK, here comes... */ |
841 | err = audit_tag_tree(old, new); | 828 | err = audit_tag_tree(old, new); |
842 | 829 | ||
843 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 830 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, |
844 | uid, loginuid, sessionid, sid); | 831 | loginuid, sessionid, sid); |
845 | 832 | ||
846 | audit_log_format(ab, " op=make_equiv old="); | 833 | audit_log_format(ab, " op=make_equiv old="); |
847 | audit_log_untrustedstring(ab, old); | 834 | audit_log_untrustedstring(ab, old); |
@@ -866,7 +853,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
866 | security_release_secctx(ctx, len); | 853 | security_release_secctx(ctx, len); |
867 | return -ENOMEM; | 854 | return -ENOMEM; |
868 | } | 855 | } |
869 | sig_data->uid = audit_sig_uid; | 856 | sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid); |
870 | sig_data->pid = audit_sig_pid; | 857 | sig_data->pid = audit_sig_pid; |
871 | if (audit_sig_sid) { | 858 | if (audit_sig_sid) { |
872 | memcpy(sig_data->ctx, ctx, len); | 859 | memcpy(sig_data->ctx, ctx, len); |
@@ -878,41 +865,29 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
878 | break; | 865 | break; |
879 | case AUDIT_TTY_GET: { | 866 | case AUDIT_TTY_GET: { |
880 | struct audit_tty_status s; | 867 | struct audit_tty_status s; |
881 | struct task_struct *tsk; | 868 | struct task_struct *tsk = current; |
882 | unsigned long flags; | 869 | |
883 | 870 | spin_lock_irq(&tsk->sighand->siglock); | |
884 | rcu_read_lock(); | 871 | s.enabled = tsk->signal->audit_tty != 0; |
885 | tsk = find_task_by_vpid(pid); | 872 | spin_unlock_irq(&tsk->sighand->siglock); |
886 | if (tsk && lock_task_sighand(tsk, &flags)) { | 873 | |
887 | s.enabled = tsk->signal->audit_tty != 0; | 874 | audit_send_reply(NETLINK_CB(skb).pid, seq, |
888 | unlock_task_sighand(tsk, &flags); | 875 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); |
889 | } else | ||
890 | err = -ESRCH; | ||
891 | rcu_read_unlock(); | ||
892 | |||
893 | if (!err) | ||
894 | audit_send_reply(NETLINK_CB(skb).pid, seq, | ||
895 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); | ||
896 | break; | 876 | break; |
897 | } | 877 | } |
898 | case AUDIT_TTY_SET: { | 878 | case AUDIT_TTY_SET: { |
899 | struct audit_tty_status *s; | 879 | struct audit_tty_status *s; |
900 | struct task_struct *tsk; | 880 | struct task_struct *tsk = current; |
901 | unsigned long flags; | ||
902 | 881 | ||
903 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | 882 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) |
904 | return -EINVAL; | 883 | return -EINVAL; |
905 | s = data; | 884 | s = data; |
906 | if (s->enabled != 0 && s->enabled != 1) | 885 | if (s->enabled != 0 && s->enabled != 1) |
907 | return -EINVAL; | 886 | return -EINVAL; |
908 | rcu_read_lock(); | 887 | |
909 | tsk = find_task_by_vpid(pid); | 888 | spin_lock_irq(&tsk->sighand->siglock); |
910 | if (tsk && lock_task_sighand(tsk, &flags)) { | 889 | tsk->signal->audit_tty = s->enabled != 0; |
911 | tsk->signal->audit_tty = s->enabled != 0; | 890 | spin_unlock_irq(&tsk->sighand->siglock); |
912 | unlock_task_sighand(tsk, &flags); | ||
913 | } else | ||
914 | err = -ESRCH; | ||
915 | rcu_read_unlock(); | ||
916 | break; | 891 | break; |
917 | } | 892 | } |
918 | default: | 893 | default: |
diff --git a/kernel/audit.h b/kernel/audit.h index 81676680337..9eb3d79482b 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -76,6 +76,8 @@ static inline int audit_hash_ino(u32 ino) | |||
76 | 76 | ||
77 | extern int audit_match_class(int class, unsigned syscall); | 77 | extern int audit_match_class(int class, unsigned syscall); |
78 | extern int audit_comparator(const u32 left, const u32 op, const u32 right); | 78 | extern int audit_comparator(const u32 left, const u32 op, const u32 right); |
79 | extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); | ||
80 | extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); | ||
79 | extern int audit_compare_dname_path(const char *dname, const char *path, | 81 | extern int audit_compare_dname_path(const char *dname, const char *path, |
80 | int *dirlen); | 82 | int *dirlen); |
81 | extern struct sk_buff * audit_make_reply(int pid, int seq, int type, | 83 | extern struct sk_buff * audit_make_reply(int pid, int seq, int type, |
@@ -144,7 +146,7 @@ extern void audit_kill_trees(struct list_head *); | |||
144 | extern char *audit_unpack_string(void **, size_t *, size_t); | 146 | extern char *audit_unpack_string(void **, size_t *, size_t); |
145 | 147 | ||
146 | extern pid_t audit_sig_pid; | 148 | extern pid_t audit_sig_pid; |
147 | extern uid_t audit_sig_uid; | 149 | extern kuid_t audit_sig_uid; |
148 | extern u32 audit_sig_sid; | 150 | extern u32 audit_sig_sid; |
149 | 151 | ||
150 | #ifdef CONFIG_AUDITSYSCALL | 152 | #ifdef CONFIG_AUDITSYSCALL |
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 3823281401b..1c22ec3d87b 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -241,7 +241,7 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc | |||
241 | struct audit_buffer *ab; | 241 | struct audit_buffer *ab; |
242 | ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); | 242 | ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); |
243 | audit_log_format(ab, "auid=%u ses=%u op=", | 243 | audit_log_format(ab, "auid=%u ses=%u op=", |
244 | audit_get_loginuid(current), | 244 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
245 | audit_get_sessionid(current)); | 245 | audit_get_sessionid(current)); |
246 | audit_log_string(ab, op); | 246 | audit_log_string(ab, op); |
247 | audit_log_format(ab, " path="); | 247 | audit_log_format(ab, " path="); |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index a6c3f1abd20..c4bcdbaf4d4 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -342,6 +342,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
342 | 342 | ||
343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); | 343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); |
344 | f->val = rule->values[i]; | 344 | f->val = rule->values[i]; |
345 | f->uid = INVALID_UID; | ||
346 | f->gid = INVALID_GID; | ||
345 | 347 | ||
346 | err = -EINVAL; | 348 | err = -EINVAL; |
347 | if (f->op == Audit_bad) | 349 | if (f->op == Audit_bad) |
@@ -350,16 +352,32 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
350 | switch(f->type) { | 352 | switch(f->type) { |
351 | default: | 353 | default: |
352 | goto exit_free; | 354 | goto exit_free; |
353 | case AUDIT_PID: | ||
354 | case AUDIT_UID: | 355 | case AUDIT_UID: |
355 | case AUDIT_EUID: | 356 | case AUDIT_EUID: |
356 | case AUDIT_SUID: | 357 | case AUDIT_SUID: |
357 | case AUDIT_FSUID: | 358 | case AUDIT_FSUID: |
359 | case AUDIT_LOGINUID: | ||
360 | /* bit ops not implemented for uid comparisons */ | ||
361 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
362 | goto exit_free; | ||
363 | |||
364 | f->uid = make_kuid(current_user_ns(), f->val); | ||
365 | if (!uid_valid(f->uid)) | ||
366 | goto exit_free; | ||
367 | break; | ||
358 | case AUDIT_GID: | 368 | case AUDIT_GID: |
359 | case AUDIT_EGID: | 369 | case AUDIT_EGID: |
360 | case AUDIT_SGID: | 370 | case AUDIT_SGID: |
361 | case AUDIT_FSGID: | 371 | case AUDIT_FSGID: |
362 | case AUDIT_LOGINUID: | 372 | /* bit ops not implemented for gid comparisons */ |
373 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
374 | goto exit_free; | ||
375 | |||
376 | f->gid = make_kgid(current_user_ns(), f->val); | ||
377 | if (!gid_valid(f->gid)) | ||
378 | goto exit_free; | ||
379 | break; | ||
380 | case AUDIT_PID: | ||
363 | case AUDIT_PERS: | 381 | case AUDIT_PERS: |
364 | case AUDIT_MSGTYPE: | 382 | case AUDIT_MSGTYPE: |
365 | case AUDIT_PPID: | 383 | case AUDIT_PPID: |
@@ -437,19 +455,39 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
437 | 455 | ||
438 | f->type = data->fields[i]; | 456 | f->type = data->fields[i]; |
439 | f->val = data->values[i]; | 457 | f->val = data->values[i]; |
458 | f->uid = INVALID_UID; | ||
459 | f->gid = INVALID_GID; | ||
440 | f->lsm_str = NULL; | 460 | f->lsm_str = NULL; |
441 | f->lsm_rule = NULL; | 461 | f->lsm_rule = NULL; |
442 | switch(f->type) { | 462 | switch(f->type) { |
443 | case AUDIT_PID: | ||
444 | case AUDIT_UID: | 463 | case AUDIT_UID: |
445 | case AUDIT_EUID: | 464 | case AUDIT_EUID: |
446 | case AUDIT_SUID: | 465 | case AUDIT_SUID: |
447 | case AUDIT_FSUID: | 466 | case AUDIT_FSUID: |
467 | case AUDIT_LOGINUID: | ||
468 | case AUDIT_OBJ_UID: | ||
469 | /* bit ops not implemented for uid comparisons */ | ||
470 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
471 | goto exit_free; | ||
472 | |||
473 | f->uid = make_kuid(current_user_ns(), f->val); | ||
474 | if (!uid_valid(f->uid)) | ||
475 | goto exit_free; | ||
476 | break; | ||
448 | case AUDIT_GID: | 477 | case AUDIT_GID: |
449 | case AUDIT_EGID: | 478 | case AUDIT_EGID: |
450 | case AUDIT_SGID: | 479 | case AUDIT_SGID: |
451 | case AUDIT_FSGID: | 480 | case AUDIT_FSGID: |
452 | case AUDIT_LOGINUID: | 481 | case AUDIT_OBJ_GID: |
482 | /* bit ops not implemented for gid comparisons */ | ||
483 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
484 | goto exit_free; | ||
485 | |||
486 | f->gid = make_kgid(current_user_ns(), f->val); | ||
487 | if (!gid_valid(f->gid)) | ||
488 | goto exit_free; | ||
489 | break; | ||
490 | case AUDIT_PID: | ||
453 | case AUDIT_PERS: | 491 | case AUDIT_PERS: |
454 | case AUDIT_MSGTYPE: | 492 | case AUDIT_MSGTYPE: |
455 | case AUDIT_PPID: | 493 | case AUDIT_PPID: |
@@ -461,8 +499,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
461 | case AUDIT_ARG1: | 499 | case AUDIT_ARG1: |
462 | case AUDIT_ARG2: | 500 | case AUDIT_ARG2: |
463 | case AUDIT_ARG3: | 501 | case AUDIT_ARG3: |
464 | case AUDIT_OBJ_UID: | ||
465 | case AUDIT_OBJ_GID: | ||
466 | break; | 502 | break; |
467 | case AUDIT_ARCH: | 503 | case AUDIT_ARCH: |
468 | entry->rule.arch_f = f; | 504 | entry->rule.arch_f = f; |
@@ -707,6 +743,23 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
707 | if (strcmp(a->filterkey, b->filterkey)) | 743 | if (strcmp(a->filterkey, b->filterkey)) |
708 | return 1; | 744 | return 1; |
709 | break; | 745 | break; |
746 | case AUDIT_UID: | ||
747 | case AUDIT_EUID: | ||
748 | case AUDIT_SUID: | ||
749 | case AUDIT_FSUID: | ||
750 | case AUDIT_LOGINUID: | ||
751 | case AUDIT_OBJ_UID: | ||
752 | if (!uid_eq(a->fields[i].uid, b->fields[i].uid)) | ||
753 | return 1; | ||
754 | break; | ||
755 | case AUDIT_GID: | ||
756 | case AUDIT_EGID: | ||
757 | case AUDIT_SGID: | ||
758 | case AUDIT_FSGID: | ||
759 | case AUDIT_OBJ_GID: | ||
760 | if (!gid_eq(a->fields[i].gid, b->fields[i].gid)) | ||
761 | return 1; | ||
762 | break; | ||
710 | default: | 763 | default: |
711 | if (a->fields[i].val != b->fields[i].val) | 764 | if (a->fields[i].val != b->fields[i].val) |
712 | return 1; | 765 | return 1; |
@@ -1056,7 +1109,7 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
1056 | } | 1109 | } |
1057 | 1110 | ||
1058 | /* Log rule additions and removals */ | 1111 | /* Log rule additions and removals */ |
1059 | static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | 1112 | static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, |
1060 | char *action, struct audit_krule *rule, | 1113 | char *action, struct audit_krule *rule, |
1061 | int res) | 1114 | int res) |
1062 | { | 1115 | { |
@@ -1068,7 +1121,8 @@ static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | |||
1068 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1121 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
1069 | if (!ab) | 1122 | if (!ab) |
1070 | return; | 1123 | return; |
1071 | audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid); | 1124 | audit_log_format(ab, "auid=%u ses=%u", |
1125 | from_kuid(&init_user_ns, loginuid), sessionid); | ||
1072 | if (sid) { | 1126 | if (sid) { |
1073 | char *ctx = NULL; | 1127 | char *ctx = NULL; |
1074 | u32 len; | 1128 | u32 len; |
@@ -1098,8 +1152,8 @@ static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, | |||
1098 | * @sessionid: sessionid for netlink audit message | 1152 | * @sessionid: sessionid for netlink audit message |
1099 | * @sid: SE Linux Security ID of sender | 1153 | * @sid: SE Linux Security ID of sender |
1100 | */ | 1154 | */ |
1101 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | 1155 | int audit_receive_filter(int type, int pid, int seq, void *data, |
1102 | size_t datasz, uid_t loginuid, u32 sessionid, u32 sid) | 1156 | size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid) |
1103 | { | 1157 | { |
1104 | struct task_struct *tsk; | 1158 | struct task_struct *tsk; |
1105 | struct audit_netlink_list *dest; | 1159 | struct audit_netlink_list *dest; |
@@ -1198,6 +1252,52 @@ int audit_comparator(u32 left, u32 op, u32 right) | |||
1198 | } | 1252 | } |
1199 | } | 1253 | } |
1200 | 1254 | ||
1255 | int audit_uid_comparator(kuid_t left, u32 op, kuid_t right) | ||
1256 | { | ||
1257 | switch (op) { | ||
1258 | case Audit_equal: | ||
1259 | return uid_eq(left, right); | ||
1260 | case Audit_not_equal: | ||
1261 | return !uid_eq(left, right); | ||
1262 | case Audit_lt: | ||
1263 | return uid_lt(left, right); | ||
1264 | case Audit_le: | ||
1265 | return uid_lte(left, right); | ||
1266 | case Audit_gt: | ||
1267 | return uid_gt(left, right); | ||
1268 | case Audit_ge: | ||
1269 | return uid_gte(left, right); | ||
1270 | case Audit_bitmask: | ||
1271 | case Audit_bittest: | ||
1272 | default: | ||
1273 | BUG(); | ||
1274 | return 0; | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | int audit_gid_comparator(kgid_t left, u32 op, kgid_t right) | ||
1279 | { | ||
1280 | switch (op) { | ||
1281 | case Audit_equal: | ||
1282 | return gid_eq(left, right); | ||
1283 | case Audit_not_equal: | ||
1284 | return !gid_eq(left, right); | ||
1285 | case Audit_lt: | ||
1286 | return gid_lt(left, right); | ||
1287 | case Audit_le: | ||
1288 | return gid_lte(left, right); | ||
1289 | case Audit_gt: | ||
1290 | return gid_gt(left, right); | ||
1291 | case Audit_ge: | ||
1292 | return gid_gte(left, right); | ||
1293 | case Audit_bitmask: | ||
1294 | case Audit_bittest: | ||
1295 | default: | ||
1296 | BUG(); | ||
1297 | return 0; | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1201 | /* Compare given dentry name with last component in given path, | 1301 | /* Compare given dentry name with last component in given path, |
1202 | * return of 0 indicates a match. */ | 1302 | * return of 0 indicates a match. */ |
1203 | int audit_compare_dname_path(const char *dname, const char *path, | 1303 | int audit_compare_dname_path(const char *dname, const char *path, |
@@ -1236,8 +1336,7 @@ int audit_compare_dname_path(const char *dname, const char *path, | |||
1236 | return strncmp(p, dname, dlen); | 1336 | return strncmp(p, dname, dlen); |
1237 | } | 1337 | } |
1238 | 1338 | ||
1239 | static int audit_filter_user_rules(struct netlink_skb_parms *cb, | 1339 | static int audit_filter_user_rules(struct audit_krule *rule, |
1240 | struct audit_krule *rule, | ||
1241 | enum audit_state *state) | 1340 | enum audit_state *state) |
1242 | { | 1341 | { |
1243 | int i; | 1342 | int i; |
@@ -1249,17 +1348,17 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb, | |||
1249 | 1348 | ||
1250 | switch (f->type) { | 1349 | switch (f->type) { |
1251 | case AUDIT_PID: | 1350 | case AUDIT_PID: |
1252 | result = audit_comparator(cb->creds.pid, f->op, f->val); | 1351 | result = audit_comparator(task_pid_vnr(current), f->op, f->val); |
1253 | break; | 1352 | break; |
1254 | case AUDIT_UID: | 1353 | case AUDIT_UID: |
1255 | result = audit_comparator(cb->creds.uid, f->op, f->val); | 1354 | result = audit_uid_comparator(current_uid(), f->op, f->uid); |
1256 | break; | 1355 | break; |
1257 | case AUDIT_GID: | 1356 | case AUDIT_GID: |
1258 | result = audit_comparator(cb->creds.gid, f->op, f->val); | 1357 | result = audit_gid_comparator(current_gid(), f->op, f->gid); |
1259 | break; | 1358 | break; |
1260 | case AUDIT_LOGINUID: | 1359 | case AUDIT_LOGINUID: |
1261 | result = audit_comparator(audit_get_loginuid(current), | 1360 | result = audit_uid_comparator(audit_get_loginuid(current), |
1262 | f->op, f->val); | 1361 | f->op, f->uid); |
1263 | break; | 1362 | break; |
1264 | case AUDIT_SUBJ_USER: | 1363 | case AUDIT_SUBJ_USER: |
1265 | case AUDIT_SUBJ_ROLE: | 1364 | case AUDIT_SUBJ_ROLE: |
@@ -1287,7 +1386,7 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb, | |||
1287 | return 1; | 1386 | return 1; |
1288 | } | 1387 | } |
1289 | 1388 | ||
1290 | int audit_filter_user(struct netlink_skb_parms *cb) | 1389 | int audit_filter_user(void) |
1291 | { | 1390 | { |
1292 | enum audit_state state = AUDIT_DISABLED; | 1391 | enum audit_state state = AUDIT_DISABLED; |
1293 | struct audit_entry *e; | 1392 | struct audit_entry *e; |
@@ -1295,7 +1394,7 @@ int audit_filter_user(struct netlink_skb_parms *cb) | |||
1295 | 1394 | ||
1296 | rcu_read_lock(); | 1395 | rcu_read_lock(); |
1297 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | 1396 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { |
1298 | if (audit_filter_user_rules(cb, &e->rule, &state)) { | 1397 | if (audit_filter_user_rules(&e->rule, &state)) { |
1299 | if (state == AUDIT_DISABLED) | 1398 | if (state == AUDIT_DISABLED) |
1300 | ret = 0; | 1399 | ret = 0; |
1301 | break; | 1400 | break; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4b96415527b..ff4798fcb48 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -113,8 +113,8 @@ struct audit_names { | |||
113 | unsigned long ino; | 113 | unsigned long ino; |
114 | dev_t dev; | 114 | dev_t dev; |
115 | umode_t mode; | 115 | umode_t mode; |
116 | uid_t uid; | 116 | kuid_t uid; |
117 | gid_t gid; | 117 | kgid_t gid; |
118 | dev_t rdev; | 118 | dev_t rdev; |
119 | u32 osid; | 119 | u32 osid; |
120 | struct audit_cap_data fcap; | 120 | struct audit_cap_data fcap; |
@@ -149,8 +149,8 @@ struct audit_aux_data_execve { | |||
149 | struct audit_aux_data_pids { | 149 | struct audit_aux_data_pids { |
150 | struct audit_aux_data d; | 150 | struct audit_aux_data d; |
151 | pid_t target_pid[AUDIT_AUX_PIDS]; | 151 | pid_t target_pid[AUDIT_AUX_PIDS]; |
152 | uid_t target_auid[AUDIT_AUX_PIDS]; | 152 | kuid_t target_auid[AUDIT_AUX_PIDS]; |
153 | uid_t target_uid[AUDIT_AUX_PIDS]; | 153 | kuid_t target_uid[AUDIT_AUX_PIDS]; |
154 | unsigned int target_sessionid[AUDIT_AUX_PIDS]; | 154 | unsigned int target_sessionid[AUDIT_AUX_PIDS]; |
155 | u32 target_sid[AUDIT_AUX_PIDS]; | 155 | u32 target_sid[AUDIT_AUX_PIDS]; |
156 | char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; | 156 | char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; |
@@ -208,14 +208,14 @@ struct audit_context { | |||
208 | size_t sockaddr_len; | 208 | size_t sockaddr_len; |
209 | /* Save things to print about task_struct */ | 209 | /* Save things to print about task_struct */ |
210 | pid_t pid, ppid; | 210 | pid_t pid, ppid; |
211 | uid_t uid, euid, suid, fsuid; | 211 | kuid_t uid, euid, suid, fsuid; |
212 | gid_t gid, egid, sgid, fsgid; | 212 | kgid_t gid, egid, sgid, fsgid; |
213 | unsigned long personality; | 213 | unsigned long personality; |
214 | int arch; | 214 | int arch; |
215 | 215 | ||
216 | pid_t target_pid; | 216 | pid_t target_pid; |
217 | uid_t target_auid; | 217 | kuid_t target_auid; |
218 | uid_t target_uid; | 218 | kuid_t target_uid; |
219 | unsigned int target_sessionid; | 219 | unsigned int target_sessionid; |
220 | u32 target_sid; | 220 | u32 target_sid; |
221 | char target_comm[TASK_COMM_LEN]; | 221 | char target_comm[TASK_COMM_LEN]; |
@@ -231,8 +231,8 @@ struct audit_context { | |||
231 | long args[6]; | 231 | long args[6]; |
232 | } socketcall; | 232 | } socketcall; |
233 | struct { | 233 | struct { |
234 | uid_t uid; | 234 | kuid_t uid; |
235 | gid_t gid; | 235 | kgid_t gid; |
236 | umode_t mode; | 236 | umode_t mode; |
237 | u32 osid; | 237 | u32 osid; |
238 | int has_perm; | 238 | int has_perm; |
@@ -464,37 +464,47 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) | |||
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | static int audit_compare_id(uid_t uid1, | 467 | static int audit_compare_uid(kuid_t uid, |
468 | struct audit_names *name, | 468 | struct audit_names *name, |
469 | unsigned long name_offset, | 469 | struct audit_field *f, |
470 | struct audit_field *f, | 470 | struct audit_context *ctx) |
471 | struct audit_context *ctx) | ||
472 | { | 471 | { |
473 | struct audit_names *n; | 472 | struct audit_names *n; |
474 | unsigned long addr; | ||
475 | uid_t uid2; | ||
476 | int rc; | 473 | int rc; |
477 | 474 | ||
478 | BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t)); | ||
479 | |||
480 | if (name) { | 475 | if (name) { |
481 | addr = (unsigned long)name; | 476 | rc = audit_uid_comparator(uid, f->op, name->uid); |
482 | addr += name_offset; | ||
483 | |||
484 | uid2 = *(uid_t *)addr; | ||
485 | rc = audit_comparator(uid1, f->op, uid2); | ||
486 | if (rc) | 477 | if (rc) |
487 | return rc; | 478 | return rc; |
488 | } | 479 | } |
489 | 480 | ||
490 | if (ctx) { | 481 | if (ctx) { |
491 | list_for_each_entry(n, &ctx->names_list, list) { | 482 | list_for_each_entry(n, &ctx->names_list, list) { |
492 | addr = (unsigned long)n; | 483 | rc = audit_uid_comparator(uid, f->op, n->uid); |
493 | addr += name_offset; | 484 | if (rc) |
494 | 485 | return rc; | |
495 | uid2 = *(uid_t *)addr; | 486 | } |
487 | } | ||
488 | return 0; | ||
489 | } | ||
496 | 490 | ||
497 | rc = audit_comparator(uid1, f->op, uid2); | 491 | static int audit_compare_gid(kgid_t gid, |
492 | struct audit_names *name, | ||
493 | struct audit_field *f, | ||
494 | struct audit_context *ctx) | ||
495 | { | ||
496 | struct audit_names *n; | ||
497 | int rc; | ||
498 | |||
499 | if (name) { | ||
500 | rc = audit_gid_comparator(gid, f->op, name->gid); | ||
501 | if (rc) | ||
502 | return rc; | ||
503 | } | ||
504 | |||
505 | if (ctx) { | ||
506 | list_for_each_entry(n, &ctx->names_list, list) { | ||
507 | rc = audit_gid_comparator(gid, f->op, n->gid); | ||
498 | if (rc) | 508 | if (rc) |
499 | return rc; | 509 | return rc; |
500 | } | 510 | } |
@@ -511,80 +521,62 @@ static int audit_field_compare(struct task_struct *tsk, | |||
511 | switch (f->val) { | 521 | switch (f->val) { |
512 | /* process to file object comparisons */ | 522 | /* process to file object comparisons */ |
513 | case AUDIT_COMPARE_UID_TO_OBJ_UID: | 523 | case AUDIT_COMPARE_UID_TO_OBJ_UID: |
514 | return audit_compare_id(cred->uid, | 524 | return audit_compare_uid(cred->uid, name, f, ctx); |
515 | name, offsetof(struct audit_names, uid), | ||
516 | f, ctx); | ||
517 | case AUDIT_COMPARE_GID_TO_OBJ_GID: | 525 | case AUDIT_COMPARE_GID_TO_OBJ_GID: |
518 | return audit_compare_id(cred->gid, | 526 | return audit_compare_gid(cred->gid, name, f, ctx); |
519 | name, offsetof(struct audit_names, gid), | ||
520 | f, ctx); | ||
521 | case AUDIT_COMPARE_EUID_TO_OBJ_UID: | 527 | case AUDIT_COMPARE_EUID_TO_OBJ_UID: |
522 | return audit_compare_id(cred->euid, | 528 | return audit_compare_uid(cred->euid, name, f, ctx); |
523 | name, offsetof(struct audit_names, uid), | ||
524 | f, ctx); | ||
525 | case AUDIT_COMPARE_EGID_TO_OBJ_GID: | 529 | case AUDIT_COMPARE_EGID_TO_OBJ_GID: |
526 | return audit_compare_id(cred->egid, | 530 | return audit_compare_gid(cred->egid, name, f, ctx); |
527 | name, offsetof(struct audit_names, gid), | ||
528 | f, ctx); | ||
529 | case AUDIT_COMPARE_AUID_TO_OBJ_UID: | 531 | case AUDIT_COMPARE_AUID_TO_OBJ_UID: |
530 | return audit_compare_id(tsk->loginuid, | 532 | return audit_compare_uid(tsk->loginuid, name, f, ctx); |
531 | name, offsetof(struct audit_names, uid), | ||
532 | f, ctx); | ||
533 | case AUDIT_COMPARE_SUID_TO_OBJ_UID: | 533 | case AUDIT_COMPARE_SUID_TO_OBJ_UID: |
534 | return audit_compare_id(cred->suid, | 534 | return audit_compare_uid(cred->suid, name, f, ctx); |
535 | name, offsetof(struct audit_names, uid), | ||
536 | f, ctx); | ||
537 | case AUDIT_COMPARE_SGID_TO_OBJ_GID: | 535 | case AUDIT_COMPARE_SGID_TO_OBJ_GID: |
538 | return audit_compare_id(cred->sgid, | 536 | return audit_compare_gid(cred->sgid, name, f, ctx); |
539 | name, offsetof(struct audit_names, gid), | ||
540 | f, ctx); | ||
541 | case AUDIT_COMPARE_FSUID_TO_OBJ_UID: | 537 | case AUDIT_COMPARE_FSUID_TO_OBJ_UID: |
542 | return audit_compare_id(cred->fsuid, | 538 | return audit_compare_uid(cred->fsuid, name, f, ctx); |
543 | name, offsetof(struct audit_names, uid), | ||
544 | f, ctx); | ||
545 | case AUDIT_COMPARE_FSGID_TO_OBJ_GID: | 539 | case AUDIT_COMPARE_FSGID_TO_OBJ_GID: |
546 | return audit_compare_id(cred->fsgid, | 540 | return audit_compare_gid(cred->fsgid, name, f, ctx); |
547 | name, offsetof(struct audit_names, gid), | ||
548 | f, ctx); | ||
549 | /* uid comparisons */ | 541 | /* uid comparisons */ |
550 | case AUDIT_COMPARE_UID_TO_AUID: | 542 | case AUDIT_COMPARE_UID_TO_AUID: |
551 | return audit_comparator(cred->uid, f->op, tsk->loginuid); | 543 | return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); |
552 | case AUDIT_COMPARE_UID_TO_EUID: | 544 | case AUDIT_COMPARE_UID_TO_EUID: |
553 | return audit_comparator(cred->uid, f->op, cred->euid); | 545 | return audit_uid_comparator(cred->uid, f->op, cred->euid); |
554 | case AUDIT_COMPARE_UID_TO_SUID: | 546 | case AUDIT_COMPARE_UID_TO_SUID: |
555 | return audit_comparator(cred->uid, f->op, cred->suid); | 547 | return audit_uid_comparator(cred->uid, f->op, cred->suid); |
556 | case AUDIT_COMPARE_UID_TO_FSUID: | 548 | case AUDIT_COMPARE_UID_TO_FSUID: |
557 | return audit_comparator(cred->uid, f->op, cred->fsuid); | 549 | return audit_uid_comparator(cred->uid, f->op, cred->fsuid); |
558 | /* auid comparisons */ | 550 | /* auid comparisons */ |
559 | case AUDIT_COMPARE_AUID_TO_EUID: | 551 | case AUDIT_COMPARE_AUID_TO_EUID: |
560 | return audit_comparator(tsk->loginuid, f->op, cred->euid); | 552 | return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); |
561 | case AUDIT_COMPARE_AUID_TO_SUID: | 553 | case AUDIT_COMPARE_AUID_TO_SUID: |
562 | return audit_comparator(tsk->loginuid, f->op, cred->suid); | 554 | return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); |
563 | case AUDIT_COMPARE_AUID_TO_FSUID: | 555 | case AUDIT_COMPARE_AUID_TO_FSUID: |
564 | return audit_comparator(tsk->loginuid, f->op, cred->fsuid); | 556 | return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); |
565 | /* euid comparisons */ | 557 | /* euid comparisons */ |
566 | case AUDIT_COMPARE_EUID_TO_SUID: | 558 | case AUDIT_COMPARE_EUID_TO_SUID: |
567 | return audit_comparator(cred->euid, f->op, cred->suid); | 559 | return audit_uid_comparator(cred->euid, f->op, cred->suid); |
568 | case AUDIT_COMPARE_EUID_TO_FSUID: | 560 | case AUDIT_COMPARE_EUID_TO_FSUID: |
569 | return audit_comparator(cred->euid, f->op, cred->fsuid); | 561 | return audit_uid_comparator(cred->euid, f->op, cred->fsuid); |
570 | /* suid comparisons */ | 562 | /* suid comparisons */ |
571 | case AUDIT_COMPARE_SUID_TO_FSUID: | 563 | case AUDIT_COMPARE_SUID_TO_FSUID: |
572 | return audit_comparator(cred->suid, f->op, cred->fsuid); | 564 | return audit_uid_comparator(cred->suid, f->op, cred->fsuid); |
573 | /* gid comparisons */ | 565 | /* gid comparisons */ |
574 | case AUDIT_COMPARE_GID_TO_EGID: | 566 | case AUDIT_COMPARE_GID_TO_EGID: |
575 | return audit_comparator(cred->gid, f->op, cred->egid); | 567 | return audit_gid_comparator(cred->gid, f->op, cred->egid); |
576 | case AUDIT_COMPARE_GID_TO_SGID: | 568 | case AUDIT_COMPARE_GID_TO_SGID: |
577 | return audit_comparator(cred->gid, f->op, cred->sgid); | 569 | return audit_gid_comparator(cred->gid, f->op, cred->sgid); |
578 | case AUDIT_COMPARE_GID_TO_FSGID: | 570 | case AUDIT_COMPARE_GID_TO_FSGID: |
579 | return audit_comparator(cred->gid, f->op, cred->fsgid); | 571 | return audit_gid_comparator(cred->gid, f->op, cred->fsgid); |
580 | /* egid comparisons */ | 572 | /* egid comparisons */ |
581 | case AUDIT_COMPARE_EGID_TO_SGID: | 573 | case AUDIT_COMPARE_EGID_TO_SGID: |
582 | return audit_comparator(cred->egid, f->op, cred->sgid); | 574 | return audit_gid_comparator(cred->egid, f->op, cred->sgid); |
583 | case AUDIT_COMPARE_EGID_TO_FSGID: | 575 | case AUDIT_COMPARE_EGID_TO_FSGID: |
584 | return audit_comparator(cred->egid, f->op, cred->fsgid); | 576 | return audit_gid_comparator(cred->egid, f->op, cred->fsgid); |
585 | /* sgid comparison */ | 577 | /* sgid comparison */ |
586 | case AUDIT_COMPARE_SGID_TO_FSGID: | 578 | case AUDIT_COMPARE_SGID_TO_FSGID: |
587 | return audit_comparator(cred->sgid, f->op, cred->fsgid); | 579 | return audit_gid_comparator(cred->sgid, f->op, cred->fsgid); |
588 | default: | 580 | default: |
589 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); | 581 | WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); |
590 | return 0; | 582 | return 0; |
@@ -630,28 +622,28 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
630 | } | 622 | } |
631 | break; | 623 | break; |
632 | case AUDIT_UID: | 624 | case AUDIT_UID: |
633 | result = audit_comparator(cred->uid, f->op, f->val); | 625 | result = audit_uid_comparator(cred->uid, f->op, f->uid); |
634 | break; | 626 | break; |
635 | case AUDIT_EUID: | 627 | case AUDIT_EUID: |
636 | result = audit_comparator(cred->euid, f->op, f->val); | 628 | result = audit_uid_comparator(cred->euid, f->op, f->uid); |
637 | break; | 629 | break; |
638 | case AUDIT_SUID: | 630 | case AUDIT_SUID: |
639 | result = audit_comparator(cred->suid, f->op, f->val); | 631 | result = audit_uid_comparator(cred->suid, f->op, f->uid); |
640 | break; | 632 | break; |
641 | case AUDIT_FSUID: | 633 | case AUDIT_FSUID: |
642 | result = audit_comparator(cred->fsuid, f->op, f->val); | 634 | result = audit_uid_comparator(cred->fsuid, f->op, f->uid); |
643 | break; | 635 | break; |
644 | case AUDIT_GID: | 636 | case AUDIT_GID: |
645 | result = audit_comparator(cred->gid, f->op, f->val); | 637 | result = audit_gid_comparator(cred->gid, f->op, f->gid); |
646 | break; | 638 | break; |
647 | case AUDIT_EGID: | 639 | case AUDIT_EGID: |
648 | result = audit_comparator(cred->egid, f->op, f->val); | 640 | result = audit_gid_comparator(cred->egid, f->op, f->gid); |
649 | break; | 641 | break; |
650 | case AUDIT_SGID: | 642 | case AUDIT_SGID: |
651 | result = audit_comparator(cred->sgid, f->op, f->val); | 643 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); |
652 | break; | 644 | break; |
653 | case AUDIT_FSGID: | 645 | case AUDIT_FSGID: |
654 | result = audit_comparator(cred->fsgid, f->op, f->val); | 646 | result = audit_gid_comparator(cred->fsgid, f->op, f->gid); |
655 | break; | 647 | break; |
656 | case AUDIT_PERS: | 648 | case AUDIT_PERS: |
657 | result = audit_comparator(tsk->personality, f->op, f->val); | 649 | result = audit_comparator(tsk->personality, f->op, f->val); |
@@ -717,10 +709,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
717 | break; | 709 | break; |
718 | case AUDIT_OBJ_UID: | 710 | case AUDIT_OBJ_UID: |
719 | if (name) { | 711 | if (name) { |
720 | result = audit_comparator(name->uid, f->op, f->val); | 712 | result = audit_uid_comparator(name->uid, f->op, f->uid); |
721 | } else if (ctx) { | 713 | } else if (ctx) { |
722 | list_for_each_entry(n, &ctx->names_list, list) { | 714 | list_for_each_entry(n, &ctx->names_list, list) { |
723 | if (audit_comparator(n->uid, f->op, f->val)) { | 715 | if (audit_uid_comparator(n->uid, f->op, f->uid)) { |
724 | ++result; | 716 | ++result; |
725 | break; | 717 | break; |
726 | } | 718 | } |
@@ -729,10 +721,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
729 | break; | 721 | break; |
730 | case AUDIT_OBJ_GID: | 722 | case AUDIT_OBJ_GID: |
731 | if (name) { | 723 | if (name) { |
732 | result = audit_comparator(name->gid, f->op, f->val); | 724 | result = audit_gid_comparator(name->gid, f->op, f->gid); |
733 | } else if (ctx) { | 725 | } else if (ctx) { |
734 | list_for_each_entry(n, &ctx->names_list, list) { | 726 | list_for_each_entry(n, &ctx->names_list, list) { |
735 | if (audit_comparator(n->gid, f->op, f->val)) { | 727 | if (audit_gid_comparator(n->gid, f->op, f->gid)) { |
736 | ++result; | 728 | ++result; |
737 | break; | 729 | break; |
738 | } | 730 | } |
@@ -750,7 +742,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
750 | case AUDIT_LOGINUID: | 742 | case AUDIT_LOGINUID: |
751 | result = 0; | 743 | result = 0; |
752 | if (ctx) | 744 | if (ctx) |
753 | result = audit_comparator(tsk->loginuid, f->op, f->val); | 745 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); |
754 | break; | 746 | break; |
755 | case AUDIT_SUBJ_USER: | 747 | case AUDIT_SUBJ_USER: |
756 | case AUDIT_SUBJ_ROLE: | 748 | case AUDIT_SUBJ_ROLE: |
@@ -1184,7 +1176,7 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk | |||
1184 | } | 1176 | } |
1185 | 1177 | ||
1186 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, | 1178 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, |
1187 | uid_t auid, uid_t uid, unsigned int sessionid, | 1179 | kuid_t auid, kuid_t uid, unsigned int sessionid, |
1188 | u32 sid, char *comm) | 1180 | u32 sid, char *comm) |
1189 | { | 1181 | { |
1190 | struct audit_buffer *ab; | 1182 | struct audit_buffer *ab; |
@@ -1196,8 +1188,9 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
1196 | if (!ab) | 1188 | if (!ab) |
1197 | return rc; | 1189 | return rc; |
1198 | 1190 | ||
1199 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid, | 1191 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, |
1200 | uid, sessionid); | 1192 | from_kuid(&init_user_ns, auid), |
1193 | from_kuid(&init_user_ns, uid), sessionid); | ||
1201 | if (security_secid_to_secctx(sid, &ctx, &len)) { | 1194 | if (security_secid_to_secctx(sid, &ctx, &len)) { |
1202 | audit_log_format(ab, " obj=(none)"); | 1195 | audit_log_format(ab, " obj=(none)"); |
1203 | rc = 1; | 1196 | rc = 1; |
@@ -1447,7 +1440,9 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
1447 | u32 osid = context->ipc.osid; | 1440 | u32 osid = context->ipc.osid; |
1448 | 1441 | ||
1449 | audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho", | 1442 | audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho", |
1450 | context->ipc.uid, context->ipc.gid, context->ipc.mode); | 1443 | from_kuid(&init_user_ns, context->ipc.uid), |
1444 | from_kgid(&init_user_ns, context->ipc.gid), | ||
1445 | context->ipc.mode); | ||
1451 | if (osid) { | 1446 | if (osid) { |
1452 | char *ctx = NULL; | 1447 | char *ctx = NULL; |
1453 | u32 len; | 1448 | u32 len; |
@@ -1560,8 +1555,8 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1560 | MAJOR(n->dev), | 1555 | MAJOR(n->dev), |
1561 | MINOR(n->dev), | 1556 | MINOR(n->dev), |
1562 | n->mode, | 1557 | n->mode, |
1563 | n->uid, | 1558 | from_kuid(&init_user_ns, n->uid), |
1564 | n->gid, | 1559 | from_kgid(&init_user_ns, n->gid), |
1565 | MAJOR(n->rdev), | 1560 | MAJOR(n->rdev), |
1566 | MINOR(n->rdev)); | 1561 | MINOR(n->rdev)); |
1567 | } | 1562 | } |
@@ -1638,11 +1633,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1638 | context->name_count, | 1633 | context->name_count, |
1639 | context->ppid, | 1634 | context->ppid, |
1640 | context->pid, | 1635 | context->pid, |
1641 | tsk->loginuid, | 1636 | from_kuid(&init_user_ns, tsk->loginuid), |
1642 | context->uid, | 1637 | from_kuid(&init_user_ns, context->uid), |
1643 | context->gid, | 1638 | from_kgid(&init_user_ns, context->gid), |
1644 | context->euid, context->suid, context->fsuid, | 1639 | from_kuid(&init_user_ns, context->euid), |
1645 | context->egid, context->sgid, context->fsgid, tty, | 1640 | from_kuid(&init_user_ns, context->suid), |
1641 | from_kuid(&init_user_ns, context->fsuid), | ||
1642 | from_kgid(&init_user_ns, context->egid), | ||
1643 | from_kgid(&init_user_ns, context->sgid), | ||
1644 | from_kgid(&init_user_ns, context->fsgid), | ||
1645 | tty, | ||
1646 | tsk->sessionid); | 1646 | tsk->sessionid); |
1647 | 1647 | ||
1648 | 1648 | ||
@@ -2299,14 +2299,14 @@ static atomic_t session_id = ATOMIC_INIT(0); | |||
2299 | * | 2299 | * |
2300 | * Called (set) from fs/proc/base.c::proc_loginuid_write(). | 2300 | * Called (set) from fs/proc/base.c::proc_loginuid_write(). |
2301 | */ | 2301 | */ |
2302 | int audit_set_loginuid(uid_t loginuid) | 2302 | int audit_set_loginuid(kuid_t loginuid) |
2303 | { | 2303 | { |
2304 | struct task_struct *task = current; | 2304 | struct task_struct *task = current; |
2305 | struct audit_context *context = task->audit_context; | 2305 | struct audit_context *context = task->audit_context; |
2306 | unsigned int sessionid; | 2306 | unsigned int sessionid; |
2307 | 2307 | ||
2308 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE | 2308 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE |
2309 | if (task->loginuid != -1) | 2309 | if (uid_valid(task->loginuid)) |
2310 | return -EPERM; | 2310 | return -EPERM; |
2311 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | 2311 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ |
2312 | if (!capable(CAP_AUDIT_CONTROL)) | 2312 | if (!capable(CAP_AUDIT_CONTROL)) |
@@ -2322,8 +2322,10 @@ int audit_set_loginuid(uid_t loginuid) | |||
2322 | audit_log_format(ab, "login pid=%d uid=%u " | 2322 | audit_log_format(ab, "login pid=%d uid=%u " |
2323 | "old auid=%u new auid=%u" | 2323 | "old auid=%u new auid=%u" |
2324 | " old ses=%u new ses=%u", | 2324 | " old ses=%u new ses=%u", |
2325 | task->pid, task_uid(task), | 2325 | task->pid, |
2326 | task->loginuid, loginuid, | 2326 | from_kuid(&init_user_ns, task_uid(task)), |
2327 | from_kuid(&init_user_ns, task->loginuid), | ||
2328 | from_kuid(&init_user_ns, loginuid), | ||
2327 | task->sessionid, sessionid); | 2329 | task->sessionid, sessionid); |
2328 | audit_log_end(ab); | 2330 | audit_log_end(ab); |
2329 | } | 2331 | } |
@@ -2546,12 +2548,12 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2546 | struct audit_aux_data_pids *axp; | 2548 | struct audit_aux_data_pids *axp; |
2547 | struct task_struct *tsk = current; | 2549 | struct task_struct *tsk = current; |
2548 | struct audit_context *ctx = tsk->audit_context; | 2550 | struct audit_context *ctx = tsk->audit_context; |
2549 | uid_t uid = current_uid(), t_uid = task_uid(t); | 2551 | kuid_t uid = current_uid(), t_uid = task_uid(t); |
2550 | 2552 | ||
2551 | if (audit_pid && t->tgid == audit_pid) { | 2553 | if (audit_pid && t->tgid == audit_pid) { |
2552 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { | 2554 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { |
2553 | audit_sig_pid = tsk->pid; | 2555 | audit_sig_pid = tsk->pid; |
2554 | if (tsk->loginuid != -1) | 2556 | if (uid_valid(tsk->loginuid)) |
2555 | audit_sig_uid = tsk->loginuid; | 2557 | audit_sig_uid = tsk->loginuid; |
2556 | else | 2558 | else |
2557 | audit_sig_uid = uid; | 2559 | audit_sig_uid = uid; |
@@ -2672,8 +2674,8 @@ void __audit_mmap_fd(int fd, int flags) | |||
2672 | 2674 | ||
2673 | static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) | 2675 | static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) |
2674 | { | 2676 | { |
2675 | uid_t auid, uid; | 2677 | kuid_t auid, uid; |
2676 | gid_t gid; | 2678 | kgid_t gid; |
2677 | unsigned int sessionid; | 2679 | unsigned int sessionid; |
2678 | 2680 | ||
2679 | auid = audit_get_loginuid(current); | 2681 | auid = audit_get_loginuid(current); |
@@ -2681,7 +2683,10 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) | |||
2681 | current_uid_gid(&uid, &gid); | 2683 | current_uid_gid(&uid, &gid); |
2682 | 2684 | ||
2683 | audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u", | 2685 | audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u", |
2684 | auid, uid, gid, sessionid); | 2686 | from_kuid(&init_user_ns, auid), |
2687 | from_kuid(&init_user_ns, uid), | ||
2688 | from_kgid(&init_user_ns, gid), | ||
2689 | sessionid); | ||
2685 | audit_log_task_context(ab); | 2690 | audit_log_task_context(ab); |
2686 | audit_log_format(ab, " pid=%d comm=", current->pid); | 2691 | audit_log_format(ab, " pid=%d comm=", current->pid); |
2687 | audit_log_untrustedstring(ab, current->comm); | 2692 | audit_log_untrustedstring(ab, current->comm); |
diff --git a/kernel/cred.c b/kernel/cred.c index de728ac50d8..48cea3da6d0 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -799,9 +799,15 @@ static void dump_invalid_creds(const struct cred *cred, const char *label, | |||
799 | atomic_read(&cred->usage), | 799 | atomic_read(&cred->usage), |
800 | read_cred_subscribers(cred)); | 800 | read_cred_subscribers(cred)); |
801 | printk(KERN_ERR "CRED: ->*uid = { %d,%d,%d,%d }\n", | 801 | printk(KERN_ERR "CRED: ->*uid = { %d,%d,%d,%d }\n", |
802 | cred->uid, cred->euid, cred->suid, cred->fsuid); | 802 | from_kuid_munged(&init_user_ns, cred->uid), |
803 | from_kuid_munged(&init_user_ns, cred->euid), | ||
804 | from_kuid_munged(&init_user_ns, cred->suid), | ||
805 | from_kuid_munged(&init_user_ns, cred->fsuid)); | ||
803 | printk(KERN_ERR "CRED: ->*gid = { %d,%d,%d,%d }\n", | 806 | printk(KERN_ERR "CRED: ->*gid = { %d,%d,%d,%d }\n", |
804 | cred->gid, cred->egid, cred->sgid, cred->fsgid); | 807 | from_kgid_munged(&init_user_ns, cred->gid), |
808 | from_kgid_munged(&init_user_ns, cred->egid), | ||
809 | from_kgid_munged(&init_user_ns, cred->sgid), | ||
810 | from_kgid_munged(&init_user_ns, cred->fsgid)); | ||
805 | #ifdef CONFIG_SECURITY | 811 | #ifdef CONFIG_SECURITY |
806 | printk(KERN_ERR "CRED: ->security is %p\n", cred->security); | 812 | printk(KERN_ERR "CRED: ->security is %p\n", cred->security); |
807 | if ((unsigned long) cred->security >= PAGE_SIZE && | 813 | if ((unsigned long) cred->security >= PAGE_SIZE && |
diff --git a/kernel/pid.c b/kernel/pid.c index e86b291ad83..aebd4f5aaf4 100644 --- a/kernel/pid.c +++ b/kernel/pid.c | |||
@@ -479,6 +479,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) | |||
479 | } | 479 | } |
480 | return nr; | 480 | return nr; |
481 | } | 481 | } |
482 | EXPORT_SYMBOL_GPL(pid_nr_ns); | ||
482 | 483 | ||
483 | pid_t pid_vnr(struct pid *pid) | 484 | pid_t pid_vnr(struct pid *pid) |
484 | { | 485 | { |
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 6144bab8fd8..478bad2745e 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
19 | #include <linux/export.h> | ||
19 | 20 | ||
20 | #define BITS_PER_PAGE (PAGE_SIZE*8) | 21 | #define BITS_PER_PAGE (PAGE_SIZE*8) |
21 | 22 | ||
@@ -144,6 +145,7 @@ void free_pid_ns(struct kref *kref) | |||
144 | if (parent != NULL) | 145 | if (parent != NULL) |
145 | put_pid_ns(parent); | 146 | put_pid_ns(parent); |
146 | } | 147 | } |
148 | EXPORT_SYMBOL_GPL(free_pid_ns); | ||
147 | 149 | ||
148 | void zap_pid_ns_processes(struct pid_namespace *pid_ns) | 150 | void zap_pid_ns_processes(struct pid_namespace *pid_ns) |
149 | { | 151 | { |
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index d0a32796550..3880df2acf0 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/cgroup.h> | 27 | #include <linux/cgroup.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/file.h> | 29 | #include <linux/file.h> |
30 | #include <linux/pid_namespace.h> | ||
30 | #include <net/genetlink.h> | 31 | #include <net/genetlink.h> |
31 | #include <linux/atomic.h> | 32 | #include <linux/atomic.h> |
32 | 33 | ||
@@ -174,7 +175,9 @@ static void send_cpu_listeners(struct sk_buff *skb, | |||
174 | up_write(&listeners->sem); | 175 | up_write(&listeners->sem); |
175 | } | 176 | } |
176 | 177 | ||
177 | static void fill_stats(struct task_struct *tsk, struct taskstats *stats) | 178 | static void fill_stats(struct user_namespace *user_ns, |
179 | struct pid_namespace *pid_ns, | ||
180 | struct task_struct *tsk, struct taskstats *stats) | ||
178 | { | 181 | { |
179 | memset(stats, 0, sizeof(*stats)); | 182 | memset(stats, 0, sizeof(*stats)); |
180 | /* | 183 | /* |
@@ -190,7 +193,7 @@ static void fill_stats(struct task_struct *tsk, struct taskstats *stats) | |||
190 | stats->version = TASKSTATS_VERSION; | 193 | stats->version = TASKSTATS_VERSION; |
191 | stats->nvcsw = tsk->nvcsw; | 194 | stats->nvcsw = tsk->nvcsw; |
192 | stats->nivcsw = tsk->nivcsw; | 195 | stats->nivcsw = tsk->nivcsw; |
193 | bacct_add_tsk(stats, tsk); | 196 | bacct_add_tsk(user_ns, pid_ns, stats, tsk); |
194 | 197 | ||
195 | /* fill in extended acct fields */ | 198 | /* fill in extended acct fields */ |
196 | xacct_add_tsk(stats, tsk); | 199 | xacct_add_tsk(stats, tsk); |
@@ -207,7 +210,7 @@ static int fill_stats_for_pid(pid_t pid, struct taskstats *stats) | |||
207 | rcu_read_unlock(); | 210 | rcu_read_unlock(); |
208 | if (!tsk) | 211 | if (!tsk) |
209 | return -ESRCH; | 212 | return -ESRCH; |
210 | fill_stats(tsk, stats); | 213 | fill_stats(current_user_ns(), task_active_pid_ns(current), tsk, stats); |
211 | put_task_struct(tsk); | 214 | put_task_struct(tsk); |
212 | return 0; | 215 | return 0; |
213 | } | 216 | } |
@@ -291,6 +294,12 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) | |||
291 | if (!cpumask_subset(mask, cpu_possible_mask)) | 294 | if (!cpumask_subset(mask, cpu_possible_mask)) |
292 | return -EINVAL; | 295 | return -EINVAL; |
293 | 296 | ||
297 | if (current_user_ns() != &init_user_ns) | ||
298 | return -EINVAL; | ||
299 | |||
300 | if (task_active_pid_ns(current) != &init_pid_ns) | ||
301 | return -EINVAL; | ||
302 | |||
294 | if (isadd == REGISTER) { | 303 | if (isadd == REGISTER) { |
295 | for_each_cpu(cpu, mask) { | 304 | for_each_cpu(cpu, mask) { |
296 | s = kmalloc_node(sizeof(struct listener), | 305 | s = kmalloc_node(sizeof(struct listener), |
@@ -631,11 +640,12 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
631 | if (rc < 0) | 640 | if (rc < 0) |
632 | return; | 641 | return; |
633 | 642 | ||
634 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid); | 643 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, |
644 | task_pid_nr_ns(tsk, &init_pid_ns)); | ||
635 | if (!stats) | 645 | if (!stats) |
636 | goto err; | 646 | goto err; |
637 | 647 | ||
638 | fill_stats(tsk, stats); | 648 | fill_stats(&init_user_ns, &init_pid_ns, tsk, stats); |
639 | 649 | ||
640 | /* | 650 | /* |
641 | * Doesn't matter if tsk is the leader or the last group member leaving | 651 | * Doesn't matter if tsk is the leader or the last group member leaving |
@@ -643,7 +653,8 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
643 | if (!is_thread_group || !group_dead) | 653 | if (!is_thread_group || !group_dead) |
644 | goto send; | 654 | goto send; |
645 | 655 | ||
646 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid); | 656 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, |
657 | task_tgid_nr_ns(tsk, &init_pid_ns)); | ||
647 | if (!stats) | 658 | if (!stats) |
648 | goto err; | 659 | goto err; |
649 | 660 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1ec5c1dab62..cdcb59450b4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2061,7 +2061,8 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter) | |||
2061 | seq_puts(m, "# -----------------\n"); | 2061 | seq_puts(m, "# -----------------\n"); |
2062 | seq_printf(m, "# | task: %.16s-%d " | 2062 | seq_printf(m, "# | task: %.16s-%d " |
2063 | "(uid:%d nice:%ld policy:%ld rt_prio:%ld)\n", | 2063 | "(uid:%d nice:%ld policy:%ld rt_prio:%ld)\n", |
2064 | data->comm, data->pid, data->uid, data->nice, | 2064 | data->comm, data->pid, |
2065 | from_kuid_munged(seq_user_ns(m), data->uid), data->nice, | ||
2065 | data->policy, data->rt_priority); | 2066 | data->policy, data->rt_priority); |
2066 | seq_puts(m, "# -----------------\n"); | 2067 | seq_puts(m, "# -----------------\n"); |
2067 | 2068 | ||
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 63a2da0b9a6..c15f528c1af 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -147,7 +147,7 @@ struct trace_array_cpu { | |||
147 | unsigned long skipped_entries; | 147 | unsigned long skipped_entries; |
148 | cycle_t preempt_timestamp; | 148 | cycle_t preempt_timestamp; |
149 | pid_t pid; | 149 | pid_t pid; |
150 | uid_t uid; | 150 | kuid_t uid; |
151 | char comm[TASK_COMM_LEN]; | 151 | char comm[TASK_COMM_LEN]; |
152 | }; | 152 | }; |
153 | 153 | ||
diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 23b4d784ebd..625df0b4469 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c | |||
@@ -26,7 +26,9 @@ | |||
26 | /* | 26 | /* |
27 | * fill in basic accounting fields | 27 | * fill in basic accounting fields |
28 | */ | 28 | */ |
29 | void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | 29 | void bacct_add_tsk(struct user_namespace *user_ns, |
30 | struct pid_namespace *pid_ns, | ||
31 | struct taskstats *stats, struct task_struct *tsk) | ||
30 | { | 32 | { |
31 | const struct cred *tcred; | 33 | const struct cred *tcred; |
32 | struct timespec uptime, ts; | 34 | struct timespec uptime, ts; |
@@ -55,13 +57,13 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | |||
55 | stats->ac_flag |= AXSIG; | 57 | stats->ac_flag |= AXSIG; |
56 | stats->ac_nice = task_nice(tsk); | 58 | stats->ac_nice = task_nice(tsk); |
57 | stats->ac_sched = tsk->policy; | 59 | stats->ac_sched = tsk->policy; |
58 | stats->ac_pid = tsk->pid; | 60 | stats->ac_pid = task_pid_nr_ns(tsk, pid_ns); |
59 | rcu_read_lock(); | 61 | rcu_read_lock(); |
60 | tcred = __task_cred(tsk); | 62 | tcred = __task_cred(tsk); |
61 | stats->ac_uid = tcred->uid; | 63 | stats->ac_uid = from_kuid_munged(user_ns, tcred->uid); |
62 | stats->ac_gid = tcred->gid; | 64 | stats->ac_gid = from_kgid_munged(user_ns, tcred->gid); |
63 | stats->ac_ppid = pid_alive(tsk) ? | 65 | stats->ac_ppid = pid_alive(tsk) ? |
64 | rcu_dereference(tsk->real_parent)->tgid : 0; | 66 | task_tgid_nr_ns(rcu_dereference(tsk->real_parent), pid_ns) : 0; |
65 | rcu_read_unlock(); | 67 | rcu_read_unlock(); |
66 | stats->ac_utime = cputime_to_usecs(tsk->utime); | 68 | stats->ac_utime = cputime_to_usecs(tsk->utime); |
67 | stats->ac_stime = cputime_to_usecs(tsk->stime); | 69 | stats->ac_stime = cputime_to_usecs(tsk->stime); |
diff --git a/kernel/user.c b/kernel/user.c index b815fefbe76..750acffbe9e 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -38,6 +38,14 @@ struct user_namespace init_user_ns = { | |||
38 | .count = 4294967295U, | 38 | .count = 4294967295U, |
39 | }, | 39 | }, |
40 | }, | 40 | }, |
41 | .projid_map = { | ||
42 | .nr_extents = 1, | ||
43 | .extent[0] = { | ||
44 | .first = 0, | ||
45 | .lower_first = 0, | ||
46 | .count = 4294967295U, | ||
47 | }, | ||
48 | }, | ||
41 | .kref = { | 49 | .kref = { |
42 | .refcount = ATOMIC_INIT(3), | 50 | .refcount = ATOMIC_INIT(3), |
43 | }, | 51 | }, |
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 86602316422..456a6b9fba3 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
20 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/projid.h> | ||
22 | 23 | ||
23 | static struct kmem_cache *user_ns_cachep __read_mostly; | 24 | static struct kmem_cache *user_ns_cachep __read_mostly; |
24 | 25 | ||
@@ -295,6 +296,75 @@ gid_t from_kgid_munged(struct user_namespace *targ, kgid_t kgid) | |||
295 | } | 296 | } |
296 | EXPORT_SYMBOL(from_kgid_munged); | 297 | EXPORT_SYMBOL(from_kgid_munged); |
297 | 298 | ||
299 | /** | ||
300 | * make_kprojid - Map a user-namespace projid pair into a kprojid. | ||
301 | * @ns: User namespace that the projid is in | ||
302 | * @projid: Project identifier | ||
303 | * | ||
304 | * Maps a user-namespace uid pair into a kernel internal kuid, | ||
305 | * and returns that kuid. | ||
306 | * | ||
307 | * When there is no mapping defined for the user-namespace projid | ||
308 | * pair INVALID_PROJID is returned. Callers are expected to test | ||
309 | * for and handle handle INVALID_PROJID being returned. INVALID_PROJID | ||
310 | * may be tested for using projid_valid(). | ||
311 | */ | ||
312 | kprojid_t make_kprojid(struct user_namespace *ns, projid_t projid) | ||
313 | { | ||
314 | /* Map the uid to a global kernel uid */ | ||
315 | return KPROJIDT_INIT(map_id_down(&ns->projid_map, projid)); | ||
316 | } | ||
317 | EXPORT_SYMBOL(make_kprojid); | ||
318 | |||
319 | /** | ||
320 | * from_kprojid - Create a projid from a kprojid user-namespace pair. | ||
321 | * @targ: The user namespace we want a projid in. | ||
322 | * @kprojid: The kernel internal project identifier to start with. | ||
323 | * | ||
324 | * Map @kprojid into the user-namespace specified by @targ and | ||
325 | * return the resulting projid. | ||
326 | * | ||
327 | * There is always a mapping into the initial user_namespace. | ||
328 | * | ||
329 | * If @kprojid has no mapping in @targ (projid_t)-1 is returned. | ||
330 | */ | ||
331 | projid_t from_kprojid(struct user_namespace *targ, kprojid_t kprojid) | ||
332 | { | ||
333 | /* Map the uid from a global kernel uid */ | ||
334 | return map_id_up(&targ->projid_map, __kprojid_val(kprojid)); | ||
335 | } | ||
336 | EXPORT_SYMBOL(from_kprojid); | ||
337 | |||
338 | /** | ||
339 | * from_kprojid_munged - Create a projiid from a kprojid user-namespace pair. | ||
340 | * @targ: The user namespace we want a projid in. | ||
341 | * @kprojid: The kernel internal projid to start with. | ||
342 | * | ||
343 | * Map @kprojid into the user-namespace specified by @targ and | ||
344 | * return the resulting projid. | ||
345 | * | ||
346 | * There is always a mapping into the initial user_namespace. | ||
347 | * | ||
348 | * Unlike from_kprojid from_kprojid_munged never fails and always | ||
349 | * returns a valid projid. This makes from_kprojid_munged | ||
350 | * appropriate for use in syscalls like stat and where | ||
351 | * failing the system call and failing to provide a valid projid are | ||
352 | * not an options. | ||
353 | * | ||
354 | * If @kprojid has no mapping in @targ OVERFLOW_PROJID is returned. | ||
355 | */ | ||
356 | projid_t from_kprojid_munged(struct user_namespace *targ, kprojid_t kprojid) | ||
357 | { | ||
358 | projid_t projid; | ||
359 | projid = from_kprojid(targ, kprojid); | ||
360 | |||
361 | if (projid == (projid_t) -1) | ||
362 | projid = OVERFLOW_PROJID; | ||
363 | return projid; | ||
364 | } | ||
365 | EXPORT_SYMBOL(from_kprojid_munged); | ||
366 | |||
367 | |||
298 | static int uid_m_show(struct seq_file *seq, void *v) | 368 | static int uid_m_show(struct seq_file *seq, void *v) |
299 | { | 369 | { |
300 | struct user_namespace *ns = seq->private; | 370 | struct user_namespace *ns = seq->private; |
@@ -337,6 +407,27 @@ static int gid_m_show(struct seq_file *seq, void *v) | |||
337 | return 0; | 407 | return 0; |
338 | } | 408 | } |
339 | 409 | ||
410 | static int projid_m_show(struct seq_file *seq, void *v) | ||
411 | { | ||
412 | struct user_namespace *ns = seq->private; | ||
413 | struct uid_gid_extent *extent = v; | ||
414 | struct user_namespace *lower_ns; | ||
415 | projid_t lower; | ||
416 | |||
417 | lower_ns = seq_user_ns(seq); | ||
418 | if ((lower_ns == ns) && lower_ns->parent) | ||
419 | lower_ns = lower_ns->parent; | ||
420 | |||
421 | lower = from_kprojid(lower_ns, KPROJIDT_INIT(extent->lower_first)); | ||
422 | |||
423 | seq_printf(seq, "%10u %10u %10u\n", | ||
424 | extent->first, | ||
425 | lower, | ||
426 | extent->count); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
340 | static void *m_start(struct seq_file *seq, loff_t *ppos, struct uid_gid_map *map) | 431 | static void *m_start(struct seq_file *seq, loff_t *ppos, struct uid_gid_map *map) |
341 | { | 432 | { |
342 | struct uid_gid_extent *extent = NULL; | 433 | struct uid_gid_extent *extent = NULL; |
@@ -362,6 +453,13 @@ static void *gid_m_start(struct seq_file *seq, loff_t *ppos) | |||
362 | return m_start(seq, ppos, &ns->gid_map); | 453 | return m_start(seq, ppos, &ns->gid_map); |
363 | } | 454 | } |
364 | 455 | ||
456 | static void *projid_m_start(struct seq_file *seq, loff_t *ppos) | ||
457 | { | ||
458 | struct user_namespace *ns = seq->private; | ||
459 | |||
460 | return m_start(seq, ppos, &ns->projid_map); | ||
461 | } | ||
462 | |||
365 | static void *m_next(struct seq_file *seq, void *v, loff_t *pos) | 463 | static void *m_next(struct seq_file *seq, void *v, loff_t *pos) |
366 | { | 464 | { |
367 | (*pos)++; | 465 | (*pos)++; |
@@ -387,6 +485,13 @@ struct seq_operations proc_gid_seq_operations = { | |||
387 | .show = gid_m_show, | 485 | .show = gid_m_show, |
388 | }; | 486 | }; |
389 | 487 | ||
488 | struct seq_operations proc_projid_seq_operations = { | ||
489 | .start = projid_m_start, | ||
490 | .stop = m_stop, | ||
491 | .next = m_next, | ||
492 | .show = projid_m_show, | ||
493 | }; | ||
494 | |||
390 | static DEFINE_MUTEX(id_map_mutex); | 495 | static DEFINE_MUTEX(id_map_mutex); |
391 | 496 | ||
392 | static ssize_t map_write(struct file *file, const char __user *buf, | 497 | static ssize_t map_write(struct file *file, const char __user *buf, |
@@ -434,7 +539,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |||
434 | /* Require the appropriate privilege CAP_SETUID or CAP_SETGID | 539 | /* Require the appropriate privilege CAP_SETUID or CAP_SETGID |
435 | * over the user namespace in order to set the id mapping. | 540 | * over the user namespace in order to set the id mapping. |
436 | */ | 541 | */ |
437 | if (!ns_capable(ns, cap_setid)) | 542 | if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid)) |
438 | goto out; | 543 | goto out; |
439 | 544 | ||
440 | /* Get a buffer */ | 545 | /* Get a buffer */ |
@@ -584,9 +689,30 @@ ssize_t proc_gid_map_write(struct file *file, const char __user *buf, size_t siz | |||
584 | &ns->gid_map, &ns->parent->gid_map); | 689 | &ns->gid_map, &ns->parent->gid_map); |
585 | } | 690 | } |
586 | 691 | ||
692 | ssize_t proc_projid_map_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos) | ||
693 | { | ||
694 | struct seq_file *seq = file->private_data; | ||
695 | struct user_namespace *ns = seq->private; | ||
696 | struct user_namespace *seq_ns = seq_user_ns(seq); | ||
697 | |||
698 | if (!ns->parent) | ||
699 | return -EPERM; | ||
700 | |||
701 | if ((seq_ns != ns) && (seq_ns != ns->parent)) | ||
702 | return -EPERM; | ||
703 | |||
704 | /* Anyone can set any valid project id no capability needed */ | ||
705 | return map_write(file, buf, size, ppos, -1, | ||
706 | &ns->projid_map, &ns->parent->projid_map); | ||
707 | } | ||
708 | |||
587 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, | 709 | static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid, |
588 | struct uid_gid_map *new_map) | 710 | struct uid_gid_map *new_map) |
589 | { | 711 | { |
712 | /* Allow anyone to set a mapping that doesn't require privilege */ | ||
713 | if (!cap_valid(cap_setid)) | ||
714 | return true; | ||
715 | |||
590 | /* Allow the specified ids if we have the appropriate capability | 716 | /* Allow the specified ids if we have the appropriate capability |
591 | * (CAP_SETUID or CAP_SETGID) over the parent user namespace. | 717 | * (CAP_SETUID or CAP_SETGID) over the parent user namespace. |
592 | */ | 718 | */ |