aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c115
1 files changed, 74 insertions, 41 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 26a6b73a6b85..e83ddbbaf89d 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -33,8 +33,10 @@
33#include <linux/task_io_accounting_ops.h> 33#include <linux/task_io_accounting_ops.h>
34#include <linux/seccomp.h> 34#include <linux/seccomp.h>
35#include <linux/cpu.h> 35#include <linux/cpu.h>
36#include <linux/personality.h>
36#include <linux/ptrace.h> 37#include <linux/ptrace.h>
37#include <linux/fs_struct.h> 38#include <linux/fs_struct.h>
39#include <linux/gfp.h>
38 40
39#include <linux/compat.h> 41#include <linux/compat.h>
40#include <linux/syscalls.h> 42#include <linux/syscalls.h>
@@ -222,6 +224,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
222 if (which > PRIO_USER || which < PRIO_PROCESS) 224 if (which > PRIO_USER || which < PRIO_PROCESS)
223 return -EINVAL; 225 return -EINVAL;
224 226
227 rcu_read_lock();
225 read_lock(&tasklist_lock); 228 read_lock(&tasklist_lock);
226 switch (which) { 229 switch (which) {
227 case PRIO_PROCESS: 230 case PRIO_PROCESS:
@@ -267,6 +270,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
267 } 270 }
268out_unlock: 271out_unlock:
269 read_unlock(&tasklist_lock); 272 read_unlock(&tasklist_lock);
273 rcu_read_unlock();
270 274
271 return retval; 275 return retval;
272} 276}
@@ -488,10 +492,6 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
488 return -ENOMEM; 492 return -ENOMEM;
489 old = current_cred(); 493 old = current_cred();
490 494
491 retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
492 if (retval)
493 goto error;
494
495 retval = -EPERM; 495 retval = -EPERM;
496 if (rgid != (gid_t) -1) { 496 if (rgid != (gid_t) -1) {
497 if (old->gid == rgid || 497 if (old->gid == rgid ||
@@ -539,10 +539,6 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
539 return -ENOMEM; 539 return -ENOMEM;
540 old = current_cred(); 540 old = current_cred();
541 541
542 retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
543 if (retval)
544 goto error;
545
546 retval = -EPERM; 542 retval = -EPERM;
547 if (capable(CAP_SETGID)) 543 if (capable(CAP_SETGID))
548 new->gid = new->egid = new->sgid = new->fsgid = gid; 544 new->gid = new->egid = new->sgid = new->fsgid = gid;
@@ -569,13 +565,7 @@ static int set_user(struct cred *new)
569 if (!new_user) 565 if (!new_user)
570 return -EAGAIN; 566 return -EAGAIN;
571 567
572 if (!task_can_switch_user(new_user, current)) { 568 if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
573 free_uid(new_user);
574 return -EINVAL;
575 }
576
577 if (atomic_read(&new_user->processes) >=
578 current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
579 new_user != INIT_USER) { 569 new_user != INIT_USER) {
580 free_uid(new_user); 570 free_uid(new_user);
581 return -EAGAIN; 571 return -EAGAIN;
@@ -612,10 +602,6 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
612 return -ENOMEM; 602 return -ENOMEM;
613 old = current_cred(); 603 old = current_cred();
614 604
615 retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
616 if (retval)
617 goto error;
618
619 retval = -EPERM; 605 retval = -EPERM;
620 if (ruid != (uid_t) -1) { 606 if (ruid != (uid_t) -1) {
621 new->uid = ruid; 607 new->uid = ruid;
@@ -677,10 +663,6 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
677 return -ENOMEM; 663 return -ENOMEM;
678 old = current_cred(); 664 old = current_cred();
679 665
680 retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
681 if (retval)
682 goto error;
683
684 retval = -EPERM; 666 retval = -EPERM;
685 if (capable(CAP_SETUID)) { 667 if (capable(CAP_SETUID)) {
686 new->suid = new->uid = uid; 668 new->suid = new->uid = uid;
@@ -721,9 +703,6 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
721 if (!new) 703 if (!new)
722 return -ENOMEM; 704 return -ENOMEM;
723 705
724 retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
725 if (retval)
726 goto error;
727 old = current_cred(); 706 old = current_cred();
728 707
729 retval = -EPERM; 708 retval = -EPERM;
@@ -790,10 +769,6 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
790 return -ENOMEM; 769 return -ENOMEM;
791 old = current_cred(); 770 old = current_cred();
792 771
793 retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
794 if (retval)
795 goto error;
796
797 retval = -EPERM; 772 retval = -EPERM;
798 if (!capable(CAP_SETGID)) { 773 if (!capable(CAP_SETGID)) {
799 if (rgid != (gid_t) -1 && rgid != old->gid && 774 if (rgid != (gid_t) -1 && rgid != old->gid &&
@@ -853,9 +828,6 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
853 old = current_cred(); 828 old = current_cred();
854 old_fsuid = old->fsuid; 829 old_fsuid = old->fsuid;
855 830
856 if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS) < 0)
857 goto error;
858
859 if (uid == old->uid || uid == old->euid || 831 if (uid == old->uid || uid == old->euid ||
860 uid == old->suid || uid == old->fsuid || 832 uid == old->suid || uid == old->fsuid ||
861 capable(CAP_SETUID)) { 833 capable(CAP_SETUID)) {
@@ -866,7 +838,6 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
866 } 838 }
867 } 839 }
868 840
869error:
870 abort_creds(new); 841 abort_creds(new);
871 return old_fsuid; 842 return old_fsuid;
872 843
@@ -890,9 +861,6 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
890 old = current_cred(); 861 old = current_cred();
891 old_fsgid = old->fsgid; 862 old_fsgid = old->fsgid;
892 863
893 if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
894 goto error;
895
896 if (gid == old->gid || gid == old->egid || 864 if (gid == old->gid || gid == old->egid ||
897 gid == old->sgid || gid == old->fsgid || 865 gid == old->sgid || gid == old->fsgid ||
898 capable(CAP_SETGID)) { 866 capable(CAP_SETGID)) {
@@ -902,7 +870,6 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
902 } 870 }
903 } 871 }
904 872
905error:
906 abort_creds(new); 873 abort_creds(new);
907 return old_fsgid; 874 return old_fsgid;
908 875
@@ -1118,6 +1085,15 @@ out:
1118 1085
1119DECLARE_RWSEM(uts_sem); 1086DECLARE_RWSEM(uts_sem);
1120 1087
1088#ifdef COMPAT_UTS_MACHINE
1089#define override_architecture(name) \
1090 (personality(current->personality) == PER_LINUX32 && \
1091 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
1092 sizeof(COMPAT_UTS_MACHINE)))
1093#else
1094#define override_architecture(name) 0
1095#endif
1096
1121SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) 1097SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1122{ 1098{
1123 int errno = 0; 1099 int errno = 0;
@@ -1126,9 +1102,66 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1126 if (copy_to_user(name, utsname(), sizeof *name)) 1102 if (copy_to_user(name, utsname(), sizeof *name))
1127 errno = -EFAULT; 1103 errno = -EFAULT;
1128 up_read(&uts_sem); 1104 up_read(&uts_sem);
1105
1106 if (!errno && override_architecture(name))
1107 errno = -EFAULT;
1129 return errno; 1108 return errno;
1130} 1109}
1131 1110
1111#ifdef __ARCH_WANT_SYS_OLD_UNAME
1112/*
1113 * Old cruft
1114 */
1115SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
1116{
1117 int error = 0;
1118
1119 if (!name)
1120 return -EFAULT;
1121
1122 down_read(&uts_sem);
1123 if (copy_to_user(name, utsname(), sizeof(*name)))
1124 error = -EFAULT;
1125 up_read(&uts_sem);
1126
1127 if (!error && override_architecture(name))
1128 error = -EFAULT;
1129 return error;
1130}
1131
1132SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
1133{
1134 int error;
1135
1136 if (!name)
1137 return -EFAULT;
1138 if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
1139 return -EFAULT;
1140
1141 down_read(&uts_sem);
1142 error = __copy_to_user(&name->sysname, &utsname()->sysname,
1143 __OLD_UTS_LEN);
1144 error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
1145 error |= __copy_to_user(&name->nodename, &utsname()->nodename,
1146 __OLD_UTS_LEN);
1147 error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
1148 error |= __copy_to_user(&name->release, &utsname()->release,
1149 __OLD_UTS_LEN);
1150 error |= __put_user(0, name->release + __OLD_UTS_LEN);
1151 error |= __copy_to_user(&name->version, &utsname()->version,
1152 __OLD_UTS_LEN);
1153 error |= __put_user(0, name->version + __OLD_UTS_LEN);
1154 error |= __copy_to_user(&name->machine, &utsname()->machine,
1155 __OLD_UTS_LEN);
1156 error |= __put_user(0, name->machine + __OLD_UTS_LEN);
1157 up_read(&uts_sem);
1158
1159 if (!error && override_architecture(name))
1160 error = -EFAULT;
1161 return error ? -EFAULT : 0;
1162}
1163#endif
1164
1132SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) 1165SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
1133{ 1166{
1134 int errno; 1167 int errno;
@@ -1599,9 +1632,9 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
1599 1632
1600char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; 1633char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
1601 1634
1602static void argv_cleanup(char **argv, char **envp) 1635static void argv_cleanup(struct subprocess_info *info)
1603{ 1636{
1604 argv_free(argv); 1637 argv_free(info->argv);
1605} 1638}
1606 1639
1607/** 1640/**
@@ -1635,7 +1668,7 @@ int orderly_poweroff(bool force)
1635 goto out; 1668 goto out;
1636 } 1669 }
1637 1670
1638 call_usermodehelper_setcleanup(info, argv_cleanup); 1671 call_usermodehelper_setfns(info, NULL, argv_cleanup, NULL);
1639 1672
1640 ret = call_usermodehelper_exec(info, UMH_NO_WAIT); 1673 ret = call_usermodehelper_exec(info, UMH_NO_WAIT);
1641 1674