diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 503 |
1 files changed, 345 insertions, 158 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index e7006eb6c1e4..2d39a84cd857 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <linux/personality.h> | 36 | #include <linux/personality.h> |
37 | #include <linux/ptrace.h> | 37 | #include <linux/ptrace.h> |
38 | #include <linux/fs_struct.h> | 38 | #include <linux/fs_struct.h> |
39 | #include <linux/file.h> | ||
40 | #include <linux/mount.h> | ||
39 | #include <linux/gfp.h> | 41 | #include <linux/gfp.h> |
40 | #include <linux/syscore_ops.h> | 42 | #include <linux/syscore_ops.h> |
41 | #include <linux/version.h> | 43 | #include <linux/version.h> |
@@ -93,10 +95,8 @@ | |||
93 | int overflowuid = DEFAULT_OVERFLOWUID; | 95 | int overflowuid = DEFAULT_OVERFLOWUID; |
94 | int overflowgid = DEFAULT_OVERFLOWGID; | 96 | int overflowgid = DEFAULT_OVERFLOWGID; |
95 | 97 | ||
96 | #ifdef CONFIG_UID16 | ||
97 | EXPORT_SYMBOL(overflowuid); | 98 | EXPORT_SYMBOL(overflowuid); |
98 | EXPORT_SYMBOL(overflowgid); | 99 | EXPORT_SYMBOL(overflowgid); |
99 | #endif | ||
100 | 100 | ||
101 | /* | 101 | /* |
102 | * the same as above, but for filesystems which can only store a 16-bit | 102 | * the same as above, but for filesystems which can only store a 16-bit |
@@ -133,11 +133,10 @@ static bool set_one_prio_perm(struct task_struct *p) | |||
133 | { | 133 | { |
134 | const struct cred *cred = current_cred(), *pcred = __task_cred(p); | 134 | const struct cred *cred = current_cred(), *pcred = __task_cred(p); |
135 | 135 | ||
136 | if (pcred->user->user_ns == cred->user->user_ns && | 136 | if (uid_eq(pcred->uid, cred->euid) || |
137 | (pcred->uid == cred->euid || | 137 | uid_eq(pcred->euid, cred->euid)) |
138 | pcred->euid == cred->euid)) | ||
139 | return true; | 138 | return true; |
140 | if (ns_capable(pcred->user->user_ns, CAP_SYS_NICE)) | 139 | if (ns_capable(pcred->user_ns, CAP_SYS_NICE)) |
141 | return true; | 140 | return true; |
142 | return false; | 141 | return false; |
143 | } | 142 | } |
@@ -177,6 +176,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
177 | const struct cred *cred = current_cred(); | 176 | const struct cred *cred = current_cred(); |
178 | int error = -EINVAL; | 177 | int error = -EINVAL; |
179 | struct pid *pgrp; | 178 | struct pid *pgrp; |
179 | kuid_t uid; | ||
180 | 180 | ||
181 | if (which > PRIO_USER || which < PRIO_PROCESS) | 181 | if (which > PRIO_USER || which < PRIO_PROCESS) |
182 | goto out; | 182 | goto out; |
@@ -209,18 +209,19 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
209 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 209 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
210 | break; | 210 | break; |
211 | case PRIO_USER: | 211 | case PRIO_USER: |
212 | user = (struct user_struct *) cred->user; | 212 | uid = make_kuid(cred->user_ns, who); |
213 | user = cred->user; | ||
213 | if (!who) | 214 | if (!who) |
214 | who = cred->uid; | 215 | uid = cred->uid; |
215 | else if ((who != cred->uid) && | 216 | else if (!uid_eq(uid, cred->uid) && |
216 | !(user = find_user(who))) | 217 | !(user = find_user(uid))) |
217 | goto out_unlock; /* No processes for this user */ | 218 | goto out_unlock; /* No processes for this user */ |
218 | 219 | ||
219 | do_each_thread(g, p) { | 220 | do_each_thread(g, p) { |
220 | if (__task_cred(p)->uid == who) | 221 | if (uid_eq(task_uid(p), uid)) |
221 | error = set_one_prio(p, niceval, error); | 222 | error = set_one_prio(p, niceval, error); |
222 | } while_each_thread(g, p); | 223 | } while_each_thread(g, p); |
223 | if (who != cred->uid) | 224 | if (!uid_eq(uid, cred->uid)) |
224 | free_uid(user); /* For find_user() */ | 225 | free_uid(user); /* For find_user() */ |
225 | break; | 226 | break; |
226 | } | 227 | } |
@@ -244,6 +245,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
244 | const struct cred *cred = current_cred(); | 245 | const struct cred *cred = current_cred(); |
245 | long niceval, retval = -ESRCH; | 246 | long niceval, retval = -ESRCH; |
246 | struct pid *pgrp; | 247 | struct pid *pgrp; |
248 | kuid_t uid; | ||
247 | 249 | ||
248 | if (which > PRIO_USER || which < PRIO_PROCESS) | 250 | if (which > PRIO_USER || which < PRIO_PROCESS) |
249 | return -EINVAL; | 251 | return -EINVAL; |
@@ -274,21 +276,22 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
274 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 276 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
275 | break; | 277 | break; |
276 | case PRIO_USER: | 278 | case PRIO_USER: |
277 | user = (struct user_struct *) cred->user; | 279 | uid = make_kuid(cred->user_ns, who); |
280 | user = cred->user; | ||
278 | if (!who) | 281 | if (!who) |
279 | who = cred->uid; | 282 | uid = cred->uid; |
280 | else if ((who != cred->uid) && | 283 | else if (!uid_eq(uid, cred->uid) && |
281 | !(user = find_user(who))) | 284 | !(user = find_user(uid))) |
282 | goto out_unlock; /* No processes for this user */ | 285 | goto out_unlock; /* No processes for this user */ |
283 | 286 | ||
284 | do_each_thread(g, p) { | 287 | do_each_thread(g, p) { |
285 | if (__task_cred(p)->uid == who) { | 288 | if (uid_eq(task_uid(p), uid)) { |
286 | niceval = 20 - task_nice(p); | 289 | niceval = 20 - task_nice(p); |
287 | if (niceval > retval) | 290 | if (niceval > retval) |
288 | retval = niceval; | 291 | retval = niceval; |
289 | } | 292 | } |
290 | } while_each_thread(g, p); | 293 | } while_each_thread(g, p); |
291 | if (who != cred->uid) | 294 | if (!uid_eq(uid, cred->uid)) |
292 | free_uid(user); /* for find_user() */ | 295 | free_uid(user); /* for find_user() */ |
293 | break; | 296 | break; |
294 | } | 297 | } |
@@ -553,9 +556,19 @@ void ctrl_alt_del(void) | |||
553 | */ | 556 | */ |
554 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | 557 | SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) |
555 | { | 558 | { |
559 | struct user_namespace *ns = current_user_ns(); | ||
556 | const struct cred *old; | 560 | const struct cred *old; |
557 | struct cred *new; | 561 | struct cred *new; |
558 | int retval; | 562 | int retval; |
563 | kgid_t krgid, kegid; | ||
564 | |||
565 | krgid = make_kgid(ns, rgid); | ||
566 | kegid = make_kgid(ns, egid); | ||
567 | |||
568 | if ((rgid != (gid_t) -1) && !gid_valid(krgid)) | ||
569 | return -EINVAL; | ||
570 | if ((egid != (gid_t) -1) && !gid_valid(kegid)) | ||
571 | return -EINVAL; | ||
559 | 572 | ||
560 | new = prepare_creds(); | 573 | new = prepare_creds(); |
561 | if (!new) | 574 | if (!new) |
@@ -564,25 +577,25 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) | |||
564 | 577 | ||
565 | retval = -EPERM; | 578 | retval = -EPERM; |
566 | if (rgid != (gid_t) -1) { | 579 | if (rgid != (gid_t) -1) { |
567 | if (old->gid == rgid || | 580 | if (gid_eq(old->gid, krgid) || |
568 | old->egid == rgid || | 581 | gid_eq(old->egid, krgid) || |
569 | nsown_capable(CAP_SETGID)) | 582 | nsown_capable(CAP_SETGID)) |
570 | new->gid = rgid; | 583 | new->gid = krgid; |
571 | else | 584 | else |
572 | goto error; | 585 | goto error; |
573 | } | 586 | } |
574 | if (egid != (gid_t) -1) { | 587 | if (egid != (gid_t) -1) { |
575 | if (old->gid == egid || | 588 | if (gid_eq(old->gid, kegid) || |
576 | old->egid == egid || | 589 | gid_eq(old->egid, kegid) || |
577 | old->sgid == egid || | 590 | gid_eq(old->sgid, kegid) || |
578 | nsown_capable(CAP_SETGID)) | 591 | nsown_capable(CAP_SETGID)) |
579 | new->egid = egid; | 592 | new->egid = kegid; |
580 | else | 593 | else |
581 | goto error; | 594 | goto error; |
582 | } | 595 | } |
583 | 596 | ||
584 | if (rgid != (gid_t) -1 || | 597 | if (rgid != (gid_t) -1 || |
585 | (egid != (gid_t) -1 && egid != old->gid)) | 598 | (egid != (gid_t) -1 && !gid_eq(kegid, old->gid))) |
586 | new->sgid = new->egid; | 599 | new->sgid = new->egid; |
587 | new->fsgid = new->egid; | 600 | new->fsgid = new->egid; |
588 | 601 | ||
@@ -600,9 +613,15 @@ error: | |||
600 | */ | 613 | */ |
601 | SYSCALL_DEFINE1(setgid, gid_t, gid) | 614 | SYSCALL_DEFINE1(setgid, gid_t, gid) |
602 | { | 615 | { |
616 | struct user_namespace *ns = current_user_ns(); | ||
603 | const struct cred *old; | 617 | const struct cred *old; |
604 | struct cred *new; | 618 | struct cred *new; |
605 | int retval; | 619 | int retval; |
620 | kgid_t kgid; | ||
621 | |||
622 | kgid = make_kgid(ns, gid); | ||
623 | if (!gid_valid(kgid)) | ||
624 | return -EINVAL; | ||
606 | 625 | ||
607 | new = prepare_creds(); | 626 | new = prepare_creds(); |
608 | if (!new) | 627 | if (!new) |
@@ -611,9 +630,9 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) | |||
611 | 630 | ||
612 | retval = -EPERM; | 631 | retval = -EPERM; |
613 | if (nsown_capable(CAP_SETGID)) | 632 | if (nsown_capable(CAP_SETGID)) |
614 | new->gid = new->egid = new->sgid = new->fsgid = gid; | 633 | new->gid = new->egid = new->sgid = new->fsgid = kgid; |
615 | else if (gid == old->gid || gid == old->sgid) | 634 | else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid)) |
616 | new->egid = new->fsgid = gid; | 635 | new->egid = new->fsgid = kgid; |
617 | else | 636 | else |
618 | goto error; | 637 | goto error; |
619 | 638 | ||
@@ -631,7 +650,7 @@ static int set_user(struct cred *new) | |||
631 | { | 650 | { |
632 | struct user_struct *new_user; | 651 | struct user_struct *new_user; |
633 | 652 | ||
634 | new_user = alloc_uid(current_user_ns(), new->uid); | 653 | new_user = alloc_uid(new->uid); |
635 | if (!new_user) | 654 | if (!new_user) |
636 | return -EAGAIN; | 655 | return -EAGAIN; |
637 | 656 | ||
@@ -670,9 +689,19 @@ static int set_user(struct cred *new) | |||
670 | */ | 689 | */ |
671 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | 690 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) |
672 | { | 691 | { |
692 | struct user_namespace *ns = current_user_ns(); | ||
673 | const struct cred *old; | 693 | const struct cred *old; |
674 | struct cred *new; | 694 | struct cred *new; |
675 | int retval; | 695 | int retval; |
696 | kuid_t kruid, keuid; | ||
697 | |||
698 | kruid = make_kuid(ns, ruid); | ||
699 | keuid = make_kuid(ns, euid); | ||
700 | |||
701 | if ((ruid != (uid_t) -1) && !uid_valid(kruid)) | ||
702 | return -EINVAL; | ||
703 | if ((euid != (uid_t) -1) && !uid_valid(keuid)) | ||
704 | return -EINVAL; | ||
676 | 705 | ||
677 | new = prepare_creds(); | 706 | new = prepare_creds(); |
678 | if (!new) | 707 | if (!new) |
@@ -681,29 +710,29 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
681 | 710 | ||
682 | retval = -EPERM; | 711 | retval = -EPERM; |
683 | if (ruid != (uid_t) -1) { | 712 | if (ruid != (uid_t) -1) { |
684 | new->uid = ruid; | 713 | new->uid = kruid; |
685 | if (old->uid != ruid && | 714 | if (!uid_eq(old->uid, kruid) && |
686 | old->euid != ruid && | 715 | !uid_eq(old->euid, kruid) && |
687 | !nsown_capable(CAP_SETUID)) | 716 | !nsown_capable(CAP_SETUID)) |
688 | goto error; | 717 | goto error; |
689 | } | 718 | } |
690 | 719 | ||
691 | if (euid != (uid_t) -1) { | 720 | if (euid != (uid_t) -1) { |
692 | new->euid = euid; | 721 | new->euid = keuid; |
693 | if (old->uid != euid && | 722 | if (!uid_eq(old->uid, keuid) && |
694 | old->euid != euid && | 723 | !uid_eq(old->euid, keuid) && |
695 | old->suid != euid && | 724 | !uid_eq(old->suid, keuid) && |
696 | !nsown_capable(CAP_SETUID)) | 725 | !nsown_capable(CAP_SETUID)) |
697 | goto error; | 726 | goto error; |
698 | } | 727 | } |
699 | 728 | ||
700 | if (new->uid != old->uid) { | 729 | if (!uid_eq(new->uid, old->uid)) { |
701 | retval = set_user(new); | 730 | retval = set_user(new); |
702 | if (retval < 0) | 731 | if (retval < 0) |
703 | goto error; | 732 | goto error; |
704 | } | 733 | } |
705 | if (ruid != (uid_t) -1 || | 734 | if (ruid != (uid_t) -1 || |
706 | (euid != (uid_t) -1 && euid != old->uid)) | 735 | (euid != (uid_t) -1 && !uid_eq(keuid, old->uid))) |
707 | new->suid = new->euid; | 736 | new->suid = new->euid; |
708 | new->fsuid = new->euid; | 737 | new->fsuid = new->euid; |
709 | 738 | ||
@@ -731,9 +760,15 @@ error: | |||
731 | */ | 760 | */ |
732 | SYSCALL_DEFINE1(setuid, uid_t, uid) | 761 | SYSCALL_DEFINE1(setuid, uid_t, uid) |
733 | { | 762 | { |
763 | struct user_namespace *ns = current_user_ns(); | ||
734 | const struct cred *old; | 764 | const struct cred *old; |
735 | struct cred *new; | 765 | struct cred *new; |
736 | int retval; | 766 | int retval; |
767 | kuid_t kuid; | ||
768 | |||
769 | kuid = make_kuid(ns, uid); | ||
770 | if (!uid_valid(kuid)) | ||
771 | return -EINVAL; | ||
737 | 772 | ||
738 | new = prepare_creds(); | 773 | new = prepare_creds(); |
739 | if (!new) | 774 | if (!new) |
@@ -742,17 +777,17 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
742 | 777 | ||
743 | retval = -EPERM; | 778 | retval = -EPERM; |
744 | if (nsown_capable(CAP_SETUID)) { | 779 | if (nsown_capable(CAP_SETUID)) { |
745 | new->suid = new->uid = uid; | 780 | new->suid = new->uid = kuid; |
746 | if (uid != old->uid) { | 781 | if (!uid_eq(kuid, old->uid)) { |
747 | retval = set_user(new); | 782 | retval = set_user(new); |
748 | if (retval < 0) | 783 | if (retval < 0) |
749 | goto error; | 784 | goto error; |
750 | } | 785 | } |
751 | } else if (uid != old->uid && uid != new->suid) { | 786 | } else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) { |
752 | goto error; | 787 | goto error; |
753 | } | 788 | } |
754 | 789 | ||
755 | new->fsuid = new->euid = uid; | 790 | new->fsuid = new->euid = kuid; |
756 | 791 | ||
757 | retval = security_task_fix_setuid(new, old, LSM_SETID_ID); | 792 | retval = security_task_fix_setuid(new, old, LSM_SETID_ID); |
758 | if (retval < 0) | 793 | if (retval < 0) |
@@ -772,9 +807,24 @@ error: | |||
772 | */ | 807 | */ |
773 | SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | 808 | SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) |
774 | { | 809 | { |
810 | struct user_namespace *ns = current_user_ns(); | ||
775 | const struct cred *old; | 811 | const struct cred *old; |
776 | struct cred *new; | 812 | struct cred *new; |
777 | int retval; | 813 | int retval; |
814 | kuid_t kruid, keuid, ksuid; | ||
815 | |||
816 | kruid = make_kuid(ns, ruid); | ||
817 | keuid = make_kuid(ns, euid); | ||
818 | ksuid = make_kuid(ns, suid); | ||
819 | |||
820 | if ((ruid != (uid_t) -1) && !uid_valid(kruid)) | ||
821 | return -EINVAL; | ||
822 | |||
823 | if ((euid != (uid_t) -1) && !uid_valid(keuid)) | ||
824 | return -EINVAL; | ||
825 | |||
826 | if ((suid != (uid_t) -1) && !uid_valid(ksuid)) | ||
827 | return -EINVAL; | ||
778 | 828 | ||
779 | new = prepare_creds(); | 829 | new = prepare_creds(); |
780 | if (!new) | 830 | if (!new) |
@@ -784,29 +834,29 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
784 | 834 | ||
785 | retval = -EPERM; | 835 | retval = -EPERM; |
786 | if (!nsown_capable(CAP_SETUID)) { | 836 | if (!nsown_capable(CAP_SETUID)) { |
787 | if (ruid != (uid_t) -1 && ruid != old->uid && | 837 | if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
788 | ruid != old->euid && ruid != old->suid) | 838 | !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) |
789 | goto error; | 839 | goto error; |
790 | if (euid != (uid_t) -1 && euid != old->uid && | 840 | if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
791 | euid != old->euid && euid != old->suid) | 841 | !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid)) |
792 | goto error; | 842 | goto error; |
793 | if (suid != (uid_t) -1 && suid != old->uid && | 843 | if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
794 | suid != old->euid && suid != old->suid) | 844 | !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid)) |
795 | goto error; | 845 | goto error; |
796 | } | 846 | } |
797 | 847 | ||
798 | if (ruid != (uid_t) -1) { | 848 | if (ruid != (uid_t) -1) { |
799 | new->uid = ruid; | 849 | new->uid = kruid; |
800 | if (ruid != old->uid) { | 850 | if (!uid_eq(kruid, old->uid)) { |
801 | retval = set_user(new); | 851 | retval = set_user(new); |
802 | if (retval < 0) | 852 | if (retval < 0) |
803 | goto error; | 853 | goto error; |
804 | } | 854 | } |
805 | } | 855 | } |
806 | if (euid != (uid_t) -1) | 856 | if (euid != (uid_t) -1) |
807 | new->euid = euid; | 857 | new->euid = keuid; |
808 | if (suid != (uid_t) -1) | 858 | if (suid != (uid_t) -1) |
809 | new->suid = suid; | 859 | new->suid = ksuid; |
810 | new->fsuid = new->euid; | 860 | new->fsuid = new->euid; |
811 | 861 | ||
812 | retval = security_task_fix_setuid(new, old, LSM_SETID_RES); | 862 | retval = security_task_fix_setuid(new, old, LSM_SETID_RES); |
@@ -820,14 +870,19 @@ error: | |||
820 | return retval; | 870 | return retval; |
821 | } | 871 | } |
822 | 872 | ||
823 | SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid) | 873 | SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t __user *, suidp) |
824 | { | 874 | { |
825 | const struct cred *cred = current_cred(); | 875 | const struct cred *cred = current_cred(); |
826 | int retval; | 876 | int retval; |
877 | uid_t ruid, euid, suid; | ||
878 | |||
879 | ruid = from_kuid_munged(cred->user_ns, cred->uid); | ||
880 | euid = from_kuid_munged(cred->user_ns, cred->euid); | ||
881 | suid = from_kuid_munged(cred->user_ns, cred->suid); | ||
827 | 882 | ||
828 | if (!(retval = put_user(cred->uid, ruid)) && | 883 | if (!(retval = put_user(ruid, ruidp)) && |
829 | !(retval = put_user(cred->euid, euid))) | 884 | !(retval = put_user(euid, euidp))) |
830 | retval = put_user(cred->suid, suid); | 885 | retval = put_user(suid, suidp); |
831 | 886 | ||
832 | return retval; | 887 | return retval; |
833 | } | 888 | } |
@@ -837,9 +892,22 @@ SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __u | |||
837 | */ | 892 | */ |
838 | SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | 893 | SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) |
839 | { | 894 | { |
895 | struct user_namespace *ns = current_user_ns(); | ||
840 | const struct cred *old; | 896 | const struct cred *old; |
841 | struct cred *new; | 897 | struct cred *new; |
842 | int retval; | 898 | int retval; |
899 | kgid_t krgid, kegid, ksgid; | ||
900 | |||
901 | krgid = make_kgid(ns, rgid); | ||
902 | kegid = make_kgid(ns, egid); | ||
903 | ksgid = make_kgid(ns, sgid); | ||
904 | |||
905 | if ((rgid != (gid_t) -1) && !gid_valid(krgid)) | ||
906 | return -EINVAL; | ||
907 | if ((egid != (gid_t) -1) && !gid_valid(kegid)) | ||
908 | return -EINVAL; | ||
909 | if ((sgid != (gid_t) -1) && !gid_valid(ksgid)) | ||
910 | return -EINVAL; | ||
843 | 911 | ||
844 | new = prepare_creds(); | 912 | new = prepare_creds(); |
845 | if (!new) | 913 | if (!new) |
@@ -848,23 +916,23 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) | |||
848 | 916 | ||
849 | retval = -EPERM; | 917 | retval = -EPERM; |
850 | if (!nsown_capable(CAP_SETGID)) { | 918 | if (!nsown_capable(CAP_SETGID)) { |
851 | if (rgid != (gid_t) -1 && rgid != old->gid && | 919 | if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
852 | rgid != old->egid && rgid != old->sgid) | 920 | !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) |
853 | goto error; | 921 | goto error; |
854 | if (egid != (gid_t) -1 && egid != old->gid && | 922 | if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
855 | egid != old->egid && egid != old->sgid) | 923 | !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid)) |
856 | goto error; | 924 | goto error; |
857 | if (sgid != (gid_t) -1 && sgid != old->gid && | 925 | if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
858 | sgid != old->egid && sgid != old->sgid) | 926 | !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid)) |
859 | goto error; | 927 | goto error; |
860 | } | 928 | } |
861 | 929 | ||
862 | if (rgid != (gid_t) -1) | 930 | if (rgid != (gid_t) -1) |
863 | new->gid = rgid; | 931 | new->gid = krgid; |
864 | if (egid != (gid_t) -1) | 932 | if (egid != (gid_t) -1) |
865 | new->egid = egid; | 933 | new->egid = kegid; |
866 | if (sgid != (gid_t) -1) | 934 | if (sgid != (gid_t) -1) |
867 | new->sgid = sgid; | 935 | new->sgid = ksgid; |
868 | new->fsgid = new->egid; | 936 | new->fsgid = new->egid; |
869 | 937 | ||
870 | return commit_creds(new); | 938 | return commit_creds(new); |
@@ -874,14 +942,19 @@ error: | |||
874 | return retval; | 942 | return retval; |
875 | } | 943 | } |
876 | 944 | ||
877 | SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid) | 945 | SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t __user *, sgidp) |
878 | { | 946 | { |
879 | const struct cred *cred = current_cred(); | 947 | const struct cred *cred = current_cred(); |
880 | int retval; | 948 | int retval; |
949 | gid_t rgid, egid, sgid; | ||
950 | |||
951 | rgid = from_kgid_munged(cred->user_ns, cred->gid); | ||
952 | egid = from_kgid_munged(cred->user_ns, cred->egid); | ||
953 | sgid = from_kgid_munged(cred->user_ns, cred->sgid); | ||
881 | 954 | ||
882 | if (!(retval = put_user(cred->gid, rgid)) && | 955 | if (!(retval = put_user(rgid, rgidp)) && |
883 | !(retval = put_user(cred->egid, egid))) | 956 | !(retval = put_user(egid, egidp))) |
884 | retval = put_user(cred->sgid, sgid); | 957 | retval = put_user(sgid, sgidp); |
885 | 958 | ||
886 | return retval; | 959 | return retval; |
887 | } | 960 | } |
@@ -898,18 +971,24 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) | |||
898 | const struct cred *old; | 971 | const struct cred *old; |
899 | struct cred *new; | 972 | struct cred *new; |
900 | uid_t old_fsuid; | 973 | uid_t old_fsuid; |
974 | kuid_t kuid; | ||
975 | |||
976 | old = current_cred(); | ||
977 | old_fsuid = from_kuid_munged(old->user_ns, old->fsuid); | ||
978 | |||
979 | kuid = make_kuid(old->user_ns, uid); | ||
980 | if (!uid_valid(kuid)) | ||
981 | return old_fsuid; | ||
901 | 982 | ||
902 | new = prepare_creds(); | 983 | new = prepare_creds(); |
903 | if (!new) | 984 | if (!new) |
904 | return current_fsuid(); | 985 | return old_fsuid; |
905 | old = current_cred(); | ||
906 | old_fsuid = old->fsuid; | ||
907 | 986 | ||
908 | if (uid == old->uid || uid == old->euid || | 987 | if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) || |
909 | uid == old->suid || uid == old->fsuid || | 988 | uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) || |
910 | nsown_capable(CAP_SETUID)) { | 989 | nsown_capable(CAP_SETUID)) { |
911 | if (uid != old_fsuid) { | 990 | if (!uid_eq(kuid, old->fsuid)) { |
912 | new->fsuid = uid; | 991 | new->fsuid = kuid; |
913 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) | 992 | if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) |
914 | goto change_okay; | 993 | goto change_okay; |
915 | } | 994 | } |
@@ -931,18 +1010,24 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) | |||
931 | const struct cred *old; | 1010 | const struct cred *old; |
932 | struct cred *new; | 1011 | struct cred *new; |
933 | gid_t old_fsgid; | 1012 | gid_t old_fsgid; |
1013 | kgid_t kgid; | ||
1014 | |||
1015 | old = current_cred(); | ||
1016 | old_fsgid = from_kgid_munged(old->user_ns, old->fsgid); | ||
1017 | |||
1018 | kgid = make_kgid(old->user_ns, gid); | ||
1019 | if (!gid_valid(kgid)) | ||
1020 | return old_fsgid; | ||
934 | 1021 | ||
935 | new = prepare_creds(); | 1022 | new = prepare_creds(); |
936 | if (!new) | 1023 | if (!new) |
937 | return current_fsgid(); | 1024 | return old_fsgid; |
938 | old = current_cred(); | ||
939 | old_fsgid = old->fsgid; | ||
940 | 1025 | ||
941 | if (gid == old->gid || gid == old->egid || | 1026 | if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) || |
942 | gid == old->sgid || gid == old->fsgid || | 1027 | gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) || |
943 | nsown_capable(CAP_SETGID)) { | 1028 | nsown_capable(CAP_SETGID)) { |
944 | if (gid != old_fsgid) { | 1029 | if (!gid_eq(kgid, old->fsgid)) { |
945 | new->fsgid = gid; | 1030 | new->fsgid = kgid; |
946 | goto change_okay; | 1031 | goto change_okay; |
947 | } | 1032 | } |
948 | } | 1033 | } |
@@ -1295,8 +1380,8 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) | |||
1295 | memcpy(u->nodename, tmp, len); | 1380 | memcpy(u->nodename, tmp, len); |
1296 | memset(u->nodename + len, 0, sizeof(u->nodename) - len); | 1381 | memset(u->nodename + len, 0, sizeof(u->nodename) - len); |
1297 | errno = 0; | 1382 | errno = 0; |
1383 | uts_proc_notify(UTS_PROC_HOSTNAME); | ||
1298 | } | 1384 | } |
1299 | uts_proc_notify(UTS_PROC_HOSTNAME); | ||
1300 | up_write(&uts_sem); | 1385 | up_write(&uts_sem); |
1301 | return errno; | 1386 | return errno; |
1302 | } | 1387 | } |
@@ -1346,8 +1431,8 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len) | |||
1346 | memcpy(u->domainname, tmp, len); | 1431 | memcpy(u->domainname, tmp, len); |
1347 | memset(u->domainname + len, 0, sizeof(u->domainname) - len); | 1432 | memset(u->domainname + len, 0, sizeof(u->domainname) - len); |
1348 | errno = 0; | 1433 | errno = 0; |
1434 | uts_proc_notify(UTS_PROC_DOMAINNAME); | ||
1349 | } | 1435 | } |
1350 | uts_proc_notify(UTS_PROC_DOMAINNAME); | ||
1351 | up_write(&uts_sem); | 1436 | up_write(&uts_sem); |
1352 | return errno; | 1437 | return errno; |
1353 | } | 1438 | } |
@@ -1498,15 +1583,14 @@ static int check_prlimit_permission(struct task_struct *task) | |||
1498 | return 0; | 1583 | return 0; |
1499 | 1584 | ||
1500 | tcred = __task_cred(task); | 1585 | tcred = __task_cred(task); |
1501 | if (cred->user->user_ns == tcred->user->user_ns && | 1586 | if (uid_eq(cred->uid, tcred->euid) && |
1502 | (cred->uid == tcred->euid && | 1587 | uid_eq(cred->uid, tcred->suid) && |
1503 | cred->uid == tcred->suid && | 1588 | uid_eq(cred->uid, tcred->uid) && |
1504 | cred->uid == tcred->uid && | 1589 | gid_eq(cred->gid, tcred->egid) && |
1505 | cred->gid == tcred->egid && | 1590 | gid_eq(cred->gid, tcred->sgid) && |
1506 | cred->gid == tcred->sgid && | 1591 | gid_eq(cred->gid, tcred->gid)) |
1507 | cred->gid == tcred->gid)) | ||
1508 | return 0; | 1592 | return 0; |
1509 | if (ns_capable(tcred->user->user_ns, CAP_SYS_RESOURCE)) | 1593 | if (ns_capable(tcred->user_ns, CAP_SYS_RESOURCE)) |
1510 | return 0; | 1594 | return 0; |
1511 | 1595 | ||
1512 | return -EPERM; | 1596 | return -EPERM; |
@@ -1702,77 +1786,105 @@ SYSCALL_DEFINE1(umask, int, mask) | |||
1702 | } | 1786 | } |
1703 | 1787 | ||
1704 | #ifdef CONFIG_CHECKPOINT_RESTORE | 1788 | #ifdef CONFIG_CHECKPOINT_RESTORE |
1789 | static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) | ||
1790 | { | ||
1791 | struct file *exe_file; | ||
1792 | struct dentry *dentry; | ||
1793 | int err; | ||
1794 | |||
1795 | exe_file = fget(fd); | ||
1796 | if (!exe_file) | ||
1797 | return -EBADF; | ||
1798 | |||
1799 | dentry = exe_file->f_path.dentry; | ||
1800 | |||
1801 | /* | ||
1802 | * Because the original mm->exe_file points to executable file, make | ||
1803 | * sure that this one is executable as well, to avoid breaking an | ||
1804 | * overall picture. | ||
1805 | */ | ||
1806 | err = -EACCES; | ||
1807 | if (!S_ISREG(dentry->d_inode->i_mode) || | ||
1808 | exe_file->f_path.mnt->mnt_flags & MNT_NOEXEC) | ||
1809 | goto exit; | ||
1810 | |||
1811 | err = inode_permission(dentry->d_inode, MAY_EXEC); | ||
1812 | if (err) | ||
1813 | goto exit; | ||
1814 | |||
1815 | down_write(&mm->mmap_sem); | ||
1816 | |||
1817 | /* | ||
1818 | * Forbid mm->exe_file change if old file still mapped. | ||
1819 | */ | ||
1820 | err = -EBUSY; | ||
1821 | if (mm->exe_file) { | ||
1822 | struct vm_area_struct *vma; | ||
1823 | |||
1824 | for (vma = mm->mmap; vma; vma = vma->vm_next) | ||
1825 | if (vma->vm_file && | ||
1826 | path_equal(&vma->vm_file->f_path, | ||
1827 | &mm->exe_file->f_path)) | ||
1828 | goto exit_unlock; | ||
1829 | } | ||
1830 | |||
1831 | /* | ||
1832 | * The symlink can be changed only once, just to disallow arbitrary | ||
1833 | * transitions malicious software might bring in. This means one | ||
1834 | * could make a snapshot over all processes running and monitor | ||
1835 | * /proc/pid/exe changes to notice unusual activity if needed. | ||
1836 | */ | ||
1837 | err = -EPERM; | ||
1838 | if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) | ||
1839 | goto exit_unlock; | ||
1840 | |||
1841 | err = 0; | ||
1842 | set_mm_exe_file(mm, exe_file); | ||
1843 | exit_unlock: | ||
1844 | up_write(&mm->mmap_sem); | ||
1845 | |||
1846 | exit: | ||
1847 | fput(exe_file); | ||
1848 | return err; | ||
1849 | } | ||
1850 | |||
1705 | static int prctl_set_mm(int opt, unsigned long addr, | 1851 | static int prctl_set_mm(int opt, unsigned long addr, |
1706 | unsigned long arg4, unsigned long arg5) | 1852 | unsigned long arg4, unsigned long arg5) |
1707 | { | 1853 | { |
1708 | unsigned long rlim = rlimit(RLIMIT_DATA); | 1854 | unsigned long rlim = rlimit(RLIMIT_DATA); |
1709 | unsigned long vm_req_flags; | ||
1710 | unsigned long vm_bad_flags; | ||
1711 | struct vm_area_struct *vma; | ||
1712 | int error = 0; | ||
1713 | struct mm_struct *mm = current->mm; | 1855 | struct mm_struct *mm = current->mm; |
1856 | struct vm_area_struct *vma; | ||
1857 | int error; | ||
1714 | 1858 | ||
1715 | if (arg4 | arg5) | 1859 | if (arg5 || (arg4 && opt != PR_SET_MM_AUXV)) |
1716 | return -EINVAL; | 1860 | return -EINVAL; |
1717 | 1861 | ||
1718 | if (!capable(CAP_SYS_RESOURCE)) | 1862 | if (!capable(CAP_SYS_RESOURCE)) |
1719 | return -EPERM; | 1863 | return -EPERM; |
1720 | 1864 | ||
1721 | if (addr >= TASK_SIZE) | 1865 | if (opt == PR_SET_MM_EXE_FILE) |
1866 | return prctl_set_mm_exe_file(mm, (unsigned int)addr); | ||
1867 | |||
1868 | if (addr >= TASK_SIZE || addr < mmap_min_addr) | ||
1722 | return -EINVAL; | 1869 | return -EINVAL; |
1723 | 1870 | ||
1871 | error = -EINVAL; | ||
1872 | |||
1724 | down_read(&mm->mmap_sem); | 1873 | down_read(&mm->mmap_sem); |
1725 | vma = find_vma(mm, addr); | 1874 | vma = find_vma(mm, addr); |
1726 | 1875 | ||
1727 | if (opt != PR_SET_MM_START_BRK && opt != PR_SET_MM_BRK) { | ||
1728 | /* It must be existing VMA */ | ||
1729 | if (!vma || vma->vm_start > addr) | ||
1730 | goto out; | ||
1731 | } | ||
1732 | |||
1733 | error = -EINVAL; | ||
1734 | switch (opt) { | 1876 | switch (opt) { |
1735 | case PR_SET_MM_START_CODE: | 1877 | case PR_SET_MM_START_CODE: |
1878 | mm->start_code = addr; | ||
1879 | break; | ||
1736 | case PR_SET_MM_END_CODE: | 1880 | case PR_SET_MM_END_CODE: |
1737 | vm_req_flags = VM_READ | VM_EXEC; | 1881 | mm->end_code = addr; |
1738 | vm_bad_flags = VM_WRITE | VM_MAYSHARE; | ||
1739 | |||
1740 | if ((vma->vm_flags & vm_req_flags) != vm_req_flags || | ||
1741 | (vma->vm_flags & vm_bad_flags)) | ||
1742 | goto out; | ||
1743 | |||
1744 | if (opt == PR_SET_MM_START_CODE) | ||
1745 | mm->start_code = addr; | ||
1746 | else | ||
1747 | mm->end_code = addr; | ||
1748 | break; | 1882 | break; |
1749 | |||
1750 | case PR_SET_MM_START_DATA: | 1883 | case PR_SET_MM_START_DATA: |
1751 | case PR_SET_MM_END_DATA: | 1884 | mm->start_data = addr; |
1752 | vm_req_flags = VM_READ | VM_WRITE; | ||
1753 | vm_bad_flags = VM_EXEC | VM_MAYSHARE; | ||
1754 | |||
1755 | if ((vma->vm_flags & vm_req_flags) != vm_req_flags || | ||
1756 | (vma->vm_flags & vm_bad_flags)) | ||
1757 | goto out; | ||
1758 | |||
1759 | if (opt == PR_SET_MM_START_DATA) | ||
1760 | mm->start_data = addr; | ||
1761 | else | ||
1762 | mm->end_data = addr; | ||
1763 | break; | 1885 | break; |
1764 | 1886 | case PR_SET_MM_END_DATA: | |
1765 | case PR_SET_MM_START_STACK: | 1887 | mm->end_data = addr; |
1766 | |||
1767 | #ifdef CONFIG_STACK_GROWSUP | ||
1768 | vm_req_flags = VM_READ | VM_WRITE | VM_GROWSUP; | ||
1769 | #else | ||
1770 | vm_req_flags = VM_READ | VM_WRITE | VM_GROWSDOWN; | ||
1771 | #endif | ||
1772 | if ((vma->vm_flags & vm_req_flags) != vm_req_flags) | ||
1773 | goto out; | ||
1774 | |||
1775 | mm->start_stack = addr; | ||
1776 | break; | 1888 | break; |
1777 | 1889 | ||
1778 | case PR_SET_MM_START_BRK: | 1890 | case PR_SET_MM_START_BRK: |
@@ -1799,24 +1911,89 @@ static int prctl_set_mm(int opt, unsigned long addr, | |||
1799 | mm->brk = addr; | 1911 | mm->brk = addr; |
1800 | break; | 1912 | break; |
1801 | 1913 | ||
1914 | /* | ||
1915 | * If command line arguments and environment | ||
1916 | * are placed somewhere else on stack, we can | ||
1917 | * set them up here, ARG_START/END to setup | ||
1918 | * command line argumets and ENV_START/END | ||
1919 | * for environment. | ||
1920 | */ | ||
1921 | case PR_SET_MM_START_STACK: | ||
1922 | case PR_SET_MM_ARG_START: | ||
1923 | case PR_SET_MM_ARG_END: | ||
1924 | case PR_SET_MM_ENV_START: | ||
1925 | case PR_SET_MM_ENV_END: | ||
1926 | if (!vma) { | ||
1927 | error = -EFAULT; | ||
1928 | goto out; | ||
1929 | } | ||
1930 | if (opt == PR_SET_MM_START_STACK) | ||
1931 | mm->start_stack = addr; | ||
1932 | else if (opt == PR_SET_MM_ARG_START) | ||
1933 | mm->arg_start = addr; | ||
1934 | else if (opt == PR_SET_MM_ARG_END) | ||
1935 | mm->arg_end = addr; | ||
1936 | else if (opt == PR_SET_MM_ENV_START) | ||
1937 | mm->env_start = addr; | ||
1938 | else if (opt == PR_SET_MM_ENV_END) | ||
1939 | mm->env_end = addr; | ||
1940 | break; | ||
1941 | |||
1942 | /* | ||
1943 | * This doesn't move auxiliary vector itself | ||
1944 | * since it's pinned to mm_struct, but allow | ||
1945 | * to fill vector with new values. It's up | ||
1946 | * to a caller to provide sane values here | ||
1947 | * otherwise user space tools which use this | ||
1948 | * vector might be unhappy. | ||
1949 | */ | ||
1950 | case PR_SET_MM_AUXV: { | ||
1951 | unsigned long user_auxv[AT_VECTOR_SIZE]; | ||
1952 | |||
1953 | if (arg4 > sizeof(user_auxv)) | ||
1954 | goto out; | ||
1955 | up_read(&mm->mmap_sem); | ||
1956 | |||
1957 | if (copy_from_user(user_auxv, (const void __user *)addr, arg4)) | ||
1958 | return -EFAULT; | ||
1959 | |||
1960 | /* Make sure the last entry is always AT_NULL */ | ||
1961 | user_auxv[AT_VECTOR_SIZE - 2] = 0; | ||
1962 | user_auxv[AT_VECTOR_SIZE - 1] = 0; | ||
1963 | |||
1964 | BUILD_BUG_ON(sizeof(user_auxv) != sizeof(mm->saved_auxv)); | ||
1965 | |||
1966 | task_lock(current); | ||
1967 | memcpy(mm->saved_auxv, user_auxv, arg4); | ||
1968 | task_unlock(current); | ||
1969 | |||
1970 | return 0; | ||
1971 | } | ||
1802 | default: | 1972 | default: |
1803 | error = -EINVAL; | ||
1804 | goto out; | 1973 | goto out; |
1805 | } | 1974 | } |
1806 | 1975 | ||
1807 | error = 0; | 1976 | error = 0; |
1808 | |||
1809 | out: | 1977 | out: |
1810 | up_read(&mm->mmap_sem); | 1978 | up_read(&mm->mmap_sem); |
1811 | |||
1812 | return error; | 1979 | return error; |
1813 | } | 1980 | } |
1981 | |||
1982 | static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) | ||
1983 | { | ||
1984 | return put_user(me->clear_child_tid, tid_addr); | ||
1985 | } | ||
1986 | |||
1814 | #else /* CONFIG_CHECKPOINT_RESTORE */ | 1987 | #else /* CONFIG_CHECKPOINT_RESTORE */ |
1815 | static int prctl_set_mm(int opt, unsigned long addr, | 1988 | static int prctl_set_mm(int opt, unsigned long addr, |
1816 | unsigned long arg4, unsigned long arg5) | 1989 | unsigned long arg4, unsigned long arg5) |
1817 | { | 1990 | { |
1818 | return -EINVAL; | 1991 | return -EINVAL; |
1819 | } | 1992 | } |
1993 | static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) | ||
1994 | { | ||
1995 | return -EINVAL; | ||
1996 | } | ||
1820 | #endif | 1997 | #endif |
1821 | 1998 | ||
1822 | SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | 1999 | SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, |
@@ -1908,7 +2085,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1908 | error = prctl_get_seccomp(); | 2085 | error = prctl_get_seccomp(); |
1909 | break; | 2086 | break; |
1910 | case PR_SET_SECCOMP: | 2087 | case PR_SET_SECCOMP: |
1911 | error = prctl_set_seccomp(arg2); | 2088 | error = prctl_set_seccomp(arg2, (char __user *)arg3); |
1912 | break; | 2089 | break; |
1913 | case PR_GET_TSC: | 2090 | case PR_GET_TSC: |
1914 | error = GET_TSC_CTL(arg2); | 2091 | error = GET_TSC_CTL(arg2); |
@@ -1971,6 +2148,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1971 | case PR_SET_MM: | 2148 | case PR_SET_MM: |
1972 | error = prctl_set_mm(arg2, arg3, arg4, arg5); | 2149 | error = prctl_set_mm(arg2, arg3, arg4, arg5); |
1973 | break; | 2150 | break; |
2151 | case PR_GET_TID_ADDRESS: | ||
2152 | error = prctl_get_tid_address(me, (int __user **)arg2); | ||
2153 | break; | ||
1974 | case PR_SET_CHILD_SUBREAPER: | 2154 | case PR_SET_CHILD_SUBREAPER: |
1975 | me->signal->is_child_subreaper = !!arg2; | 2155 | me->signal->is_child_subreaper = !!arg2; |
1976 | error = 0; | 2156 | error = 0; |
@@ -1979,6 +2159,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
1979 | error = put_user(me->signal->is_child_subreaper, | 2159 | error = put_user(me->signal->is_child_subreaper, |
1980 | (int __user *) arg2); | 2160 | (int __user *) arg2); |
1981 | break; | 2161 | break; |
2162 | case PR_SET_NO_NEW_PRIVS: | ||
2163 | if (arg2 != 1 || arg3 || arg4 || arg5) | ||
2164 | return -EINVAL; | ||
2165 | |||
2166 | current->no_new_privs = 1; | ||
2167 | break; | ||
2168 | case PR_GET_NO_NEW_PRIVS: | ||
2169 | if (arg2 || arg3 || arg4 || arg5) | ||
2170 | return -EINVAL; | ||
2171 | return current->no_new_privs ? 1 : 0; | ||
1982 | default: | 2172 | default: |
1983 | error = -EINVAL; | 2173 | error = -EINVAL; |
1984 | break; | 2174 | break; |
@@ -2022,7 +2212,6 @@ int orderly_poweroff(bool force) | |||
2022 | NULL | 2212 | NULL |
2023 | }; | 2213 | }; |
2024 | int ret = -ENOMEM; | 2214 | int ret = -ENOMEM; |
2025 | struct subprocess_info *info; | ||
2026 | 2215 | ||
2027 | if (argv == NULL) { | 2216 | if (argv == NULL) { |
2028 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", | 2217 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", |
@@ -2030,18 +2219,16 @@ int orderly_poweroff(bool force) | |||
2030 | goto out; | 2219 | goto out; |
2031 | } | 2220 | } |
2032 | 2221 | ||
2033 | info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC); | 2222 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, |
2034 | if (info == NULL) { | 2223 | NULL, argv_cleanup, NULL); |
2035 | argv_free(argv); | 2224 | out: |
2036 | goto out; | 2225 | if (likely(!ret)) |
2037 | } | 2226 | return 0; |
2038 | |||
2039 | call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL); | ||
2040 | 2227 | ||
2041 | ret = call_usermodehelper_exec(info, UMH_NO_WAIT); | 2228 | if (ret == -ENOMEM) |
2229 | argv_free(argv); | ||
2042 | 2230 | ||
2043 | out: | 2231 | if (force) { |
2044 | if (ret && force) { | ||
2045 | printk(KERN_WARNING "Failed to start orderly shutdown: " | 2232 | printk(KERN_WARNING "Failed to start orderly shutdown: " |
2046 | "forcing the issue\n"); | 2233 | "forcing the issue\n"); |
2047 | 2234 | ||