aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c123
1 files changed, 93 insertions, 30 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index ce17760d9c51..6d1a7e0f9d5b 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -8,7 +8,6 @@
8#include <linux/mm.h> 8#include <linux/mm.h>
9#include <linux/utsname.h> 9#include <linux/utsname.h>
10#include <linux/mman.h> 10#include <linux/mman.h>
11#include <linux/smp_lock.h>
12#include <linux/notifier.h> 11#include <linux/notifier.h>
13#include <linux/reboot.h> 12#include <linux/reboot.h>
14#include <linux/prctl.h> 13#include <linux/prctl.h>
@@ -34,8 +33,10 @@
34#include <linux/task_io_accounting_ops.h> 33#include <linux/task_io_accounting_ops.h>
35#include <linux/seccomp.h> 34#include <linux/seccomp.h>
36#include <linux/cpu.h> 35#include <linux/cpu.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/gfp.h>
39 40
40#include <linux/compat.h> 41#include <linux/compat.h>
41#include <linux/syscalls.h> 42#include <linux/syscalls.h>
@@ -163,6 +164,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
163 if (niceval > 19) 164 if (niceval > 19)
164 niceval = 19; 165 niceval = 19;
165 166
167 rcu_read_lock();
166 read_lock(&tasklist_lock); 168 read_lock(&tasklist_lock);
167 switch (which) { 169 switch (which) {
168 case PRIO_PROCESS: 170 case PRIO_PROCESS:
@@ -190,16 +192,17 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
190 !(user = find_user(who))) 192 !(user = find_user(who)))
191 goto out_unlock; /* No processes for this user */ 193 goto out_unlock; /* No processes for this user */
192 194
193 do_each_thread(g, p) 195 do_each_thread(g, p) {
194 if (__task_cred(p)->uid == who) 196 if (__task_cred(p)->uid == who)
195 error = set_one_prio(p, niceval, error); 197 error = set_one_prio(p, niceval, error);
196 while_each_thread(g, p); 198 } while_each_thread(g, p);
197 if (who != cred->uid) 199 if (who != cred->uid)
198 free_uid(user); /* For find_user() */ 200 free_uid(user); /* For find_user() */
199 break; 201 break;
200 } 202 }
201out_unlock: 203out_unlock:
202 read_unlock(&tasklist_lock); 204 read_unlock(&tasklist_lock);
205 rcu_read_unlock();
203out: 206out:
204 return error; 207 return error;
205} 208}
@@ -221,6 +224,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
221 if (which > PRIO_USER || which < PRIO_PROCESS) 224 if (which > PRIO_USER || which < PRIO_PROCESS)
222 return -EINVAL; 225 return -EINVAL;
223 226
227 rcu_read_lock();
224 read_lock(&tasklist_lock); 228 read_lock(&tasklist_lock);
225 switch (which) { 229 switch (which) {
226 case PRIO_PROCESS: 230 case PRIO_PROCESS:
@@ -253,19 +257,20 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
253 !(user = find_user(who))) 257 !(user = find_user(who)))
254 goto out_unlock; /* No processes for this user */ 258 goto out_unlock; /* No processes for this user */
255 259
256 do_each_thread(g, p) 260 do_each_thread(g, p) {
257 if (__task_cred(p)->uid == who) { 261 if (__task_cred(p)->uid == who) {
258 niceval = 20 - task_nice(p); 262 niceval = 20 - task_nice(p);
259 if (niceval > retval) 263 if (niceval > retval)
260 retval = niceval; 264 retval = niceval;
261 } 265 }
262 while_each_thread(g, p); 266 } while_each_thread(g, p);
263 if (who != cred->uid) 267 if (who != cred->uid)
264 free_uid(user); /* for find_user() */ 268 free_uid(user); /* for find_user() */
265 break; 269 break;
266 } 270 }
267out_unlock: 271out_unlock:
268 read_unlock(&tasklist_lock); 272 read_unlock(&tasklist_lock);
273 rcu_read_unlock();
269 274
270 return retval; 275 return retval;
271} 276}
@@ -349,6 +354,9 @@ void kernel_power_off(void)
349 machine_power_off(); 354 machine_power_off();
350} 355}
351EXPORT_SYMBOL_GPL(kernel_power_off); 356EXPORT_SYMBOL_GPL(kernel_power_off);
357
358static DEFINE_MUTEX(reboot_mutex);
359
352/* 360/*
353 * Reboot system call: for obvious reasons only root may call it, 361 * Reboot system call: for obvious reasons only root may call it,
354 * and even root needs to set up some magic numbers in the registers 362 * and even root needs to set up some magic numbers in the registers
@@ -381,7 +389,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
381 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) 389 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
382 cmd = LINUX_REBOOT_CMD_HALT; 390 cmd = LINUX_REBOOT_CMD_HALT;
383 391
384 lock_kernel(); 392 mutex_lock(&reboot_mutex);
385 switch (cmd) { 393 switch (cmd) {
386 case LINUX_REBOOT_CMD_RESTART: 394 case LINUX_REBOOT_CMD_RESTART:
387 kernel_restart(NULL); 395 kernel_restart(NULL);
@@ -397,20 +405,18 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
397 405
398 case LINUX_REBOOT_CMD_HALT: 406 case LINUX_REBOOT_CMD_HALT:
399 kernel_halt(); 407 kernel_halt();
400 unlock_kernel();
401 do_exit(0); 408 do_exit(0);
402 panic("cannot halt"); 409 panic("cannot halt");
403 410
404 case LINUX_REBOOT_CMD_POWER_OFF: 411 case LINUX_REBOOT_CMD_POWER_OFF:
405 kernel_power_off(); 412 kernel_power_off();
406 unlock_kernel();
407 do_exit(0); 413 do_exit(0);
408 break; 414 break;
409 415
410 case LINUX_REBOOT_CMD_RESTART2: 416 case LINUX_REBOOT_CMD_RESTART2:
411 if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) { 417 if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
412 unlock_kernel(); 418 ret = -EFAULT;
413 return -EFAULT; 419 break;
414 } 420 }
415 buffer[sizeof(buffer) - 1] = '\0'; 421 buffer[sizeof(buffer) - 1] = '\0';
416 422
@@ -433,7 +439,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
433 ret = -EINVAL; 439 ret = -EINVAL;
434 break; 440 break;
435 } 441 }
436 unlock_kernel(); 442 mutex_unlock(&reboot_mutex);
437 return ret; 443 return ret;
438} 444}
439 445
@@ -567,13 +573,7 @@ static int set_user(struct cred *new)
567 if (!new_user) 573 if (!new_user)
568 return -EAGAIN; 574 return -EAGAIN;
569 575
570 if (!task_can_switch_user(new_user, current)) { 576 if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
571 free_uid(new_user);
572 return -EINVAL;
573 }
574
575 if (atomic_read(&new_user->processes) >=
576 current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
577 new_user != INIT_USER) { 577 new_user != INIT_USER) {
578 free_uid(new_user); 578 free_uid(new_user);
579 return -EAGAIN; 579 return -EAGAIN;
@@ -911,16 +911,15 @@ change_okay:
911 911
912void do_sys_times(struct tms *tms) 912void do_sys_times(struct tms *tms)
913{ 913{
914 struct task_cputime cputime; 914 cputime_t tgutime, tgstime, cutime, cstime;
915 cputime_t cutime, cstime;
916 915
917 thread_group_cputime(current, &cputime);
918 spin_lock_irq(&current->sighand->siglock); 916 spin_lock_irq(&current->sighand->siglock);
917 thread_group_times(current, &tgutime, &tgstime);
919 cutime = current->signal->cutime; 918 cutime = current->signal->cutime;
920 cstime = current->signal->cstime; 919 cstime = current->signal->cstime;
921 spin_unlock_irq(&current->sighand->siglock); 920 spin_unlock_irq(&current->sighand->siglock);
922 tms->tms_utime = cputime_to_clock_t(cputime.utime); 921 tms->tms_utime = cputime_to_clock_t(tgutime);
923 tms->tms_stime = cputime_to_clock_t(cputime.stime); 922 tms->tms_stime = cputime_to_clock_t(tgstime);
924 tms->tms_cutime = cputime_to_clock_t(cutime); 923 tms->tms_cutime = cputime_to_clock_t(cutime);
925 tms->tms_cstime = cputime_to_clock_t(cstime); 924 tms->tms_cstime = cputime_to_clock_t(cstime);
926} 925}
@@ -1117,6 +1116,15 @@ out:
1117 1116
1118DECLARE_RWSEM(uts_sem); 1117DECLARE_RWSEM(uts_sem);
1119 1118
1119#ifdef COMPAT_UTS_MACHINE
1120#define override_architecture(name) \
1121 (current->personality == PER_LINUX32 && \
1122 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
1123 sizeof(COMPAT_UTS_MACHINE)))
1124#else
1125#define override_architecture(name) 0
1126#endif
1127
1120SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) 1128SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1121{ 1129{
1122 int errno = 0; 1130 int errno = 0;
@@ -1125,9 +1133,66 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
1125 if (copy_to_user(name, utsname(), sizeof *name)) 1133 if (copy_to_user(name, utsname(), sizeof *name))
1126 errno = -EFAULT; 1134 errno = -EFAULT;
1127 up_read(&uts_sem); 1135 up_read(&uts_sem);
1136
1137 if (!errno && override_architecture(name))
1138 errno = -EFAULT;
1128 return errno; 1139 return errno;
1129} 1140}
1130 1141
1142#ifdef __ARCH_WANT_SYS_OLD_UNAME
1143/*
1144 * Old cruft
1145 */
1146SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
1147{
1148 int error = 0;
1149
1150 if (!name)
1151 return -EFAULT;
1152
1153 down_read(&uts_sem);
1154 if (copy_to_user(name, utsname(), sizeof(*name)))
1155 error = -EFAULT;
1156 up_read(&uts_sem);
1157
1158 if (!error && override_architecture(name))
1159 error = -EFAULT;
1160 return error;
1161}
1162
1163SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
1164{
1165 int error;
1166
1167 if (!name)
1168 return -EFAULT;
1169 if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
1170 return -EFAULT;
1171
1172 down_read(&uts_sem);
1173 error = __copy_to_user(&name->sysname, &utsname()->sysname,
1174 __OLD_UTS_LEN);
1175 error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
1176 error |= __copy_to_user(&name->nodename, &utsname()->nodename,
1177 __OLD_UTS_LEN);
1178 error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
1179 error |= __copy_to_user(&name->release, &utsname()->release,
1180 __OLD_UTS_LEN);
1181 error |= __put_user(0, name->release + __OLD_UTS_LEN);
1182 error |= __copy_to_user(&name->version, &utsname()->version,
1183 __OLD_UTS_LEN);
1184 error |= __put_user(0, name->version + __OLD_UTS_LEN);
1185 error |= __copy_to_user(&name->machine, &utsname()->machine,
1186 __OLD_UTS_LEN);
1187 error |= __put_user(0, name->machine + __OLD_UTS_LEN);
1188 up_read(&uts_sem);
1189
1190 if (!error && override_architecture(name))
1191 error = -EFAULT;
1192 return error ? -EFAULT : 0;
1193}
1194#endif
1195
1131SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) 1196SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
1132{ 1197{
1133 int errno; 1198 int errno;
@@ -1338,16 +1403,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1338{ 1403{
1339 struct task_struct *t; 1404 struct task_struct *t;
1340 unsigned long flags; 1405 unsigned long flags;
1341 cputime_t utime, stime; 1406 cputime_t tgutime, tgstime, utime, stime;
1342 struct task_cputime cputime;
1343 unsigned long maxrss = 0; 1407 unsigned long maxrss = 0;
1344 1408
1345 memset((char *) r, 0, sizeof *r); 1409 memset((char *) r, 0, sizeof *r);
1346 utime = stime = cputime_zero; 1410 utime = stime = cputime_zero;
1347 1411
1348 if (who == RUSAGE_THREAD) { 1412 if (who == RUSAGE_THREAD) {
1349 utime = task_utime(current); 1413 task_times(current, &utime, &stime);
1350 stime = task_stime(current);
1351 accumulate_thread_rusage(p, r); 1414 accumulate_thread_rusage(p, r);
1352 maxrss = p->signal->maxrss; 1415 maxrss = p->signal->maxrss;
1353 goto out; 1416 goto out;
@@ -1373,9 +1436,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1373 break; 1436 break;
1374 1437
1375 case RUSAGE_SELF: 1438 case RUSAGE_SELF:
1376 thread_group_cputime(p, &cputime); 1439 thread_group_times(p, &tgutime, &tgstime);
1377 utime = cputime_add(utime, cputime.utime); 1440 utime = cputime_add(utime, tgutime);
1378 stime = cputime_add(stime, cputime.stime); 1441 stime = cputime_add(stime, tgstime);
1379 r->ru_nvcsw += p->signal->nvcsw; 1442 r->ru_nvcsw += p->signal->nvcsw;
1380 r->ru_nivcsw += p->signal->nivcsw; 1443 r->ru_nivcsw += p->signal->nivcsw;
1381 r->ru_minflt += p->signal->min_flt; 1444 r->ru_minflt += p->signal->min_flt;