aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 255475d163e..26a6b73a6b8 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>
@@ -163,6 +162,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
163 if (niceval > 19) 162 if (niceval > 19)
164 niceval = 19; 163 niceval = 19;
165 164
165 rcu_read_lock();
166 read_lock(&tasklist_lock); 166 read_lock(&tasklist_lock);
167 switch (which) { 167 switch (which) {
168 case PRIO_PROCESS: 168 case PRIO_PROCESS:
@@ -190,16 +190,17 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
190 !(user = find_user(who))) 190 !(user = find_user(who)))
191 goto out_unlock; /* No processes for this user */ 191 goto out_unlock; /* No processes for this user */
192 192
193 do_each_thread(g, p) 193 do_each_thread(g, p) {
194 if (__task_cred(p)->uid == who) 194 if (__task_cred(p)->uid == who)
195 error = set_one_prio(p, niceval, error); 195 error = set_one_prio(p, niceval, error);
196 while_each_thread(g, p); 196 } while_each_thread(g, p);
197 if (who != cred->uid) 197 if (who != cred->uid)
198 free_uid(user); /* For find_user() */ 198 free_uid(user); /* For find_user() */
199 break; 199 break;
200 } 200 }
201out_unlock: 201out_unlock:
202 read_unlock(&tasklist_lock); 202 read_unlock(&tasklist_lock);
203 rcu_read_unlock();
203out: 204out:
204 return error; 205 return error;
205} 206}
@@ -253,13 +254,13 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
253 !(user = find_user(who))) 254 !(user = find_user(who)))
254 goto out_unlock; /* No processes for this user */ 255 goto out_unlock; /* No processes for this user */
255 256
256 do_each_thread(g, p) 257 do_each_thread(g, p) {
257 if (__task_cred(p)->uid == who) { 258 if (__task_cred(p)->uid == who) {
258 niceval = 20 - task_nice(p); 259 niceval = 20 - task_nice(p);
259 if (niceval > retval) 260 if (niceval > retval)
260 retval = niceval; 261 retval = niceval;
261 } 262 }
262 while_each_thread(g, p); 263 } while_each_thread(g, p);
263 if (who != cred->uid) 264 if (who != cred->uid)
264 free_uid(user); /* for find_user() */ 265 free_uid(user); /* for find_user() */
265 break; 266 break;
@@ -349,6 +350,9 @@ void kernel_power_off(void)
349 machine_power_off(); 350 machine_power_off();
350} 351}
351EXPORT_SYMBOL_GPL(kernel_power_off); 352EXPORT_SYMBOL_GPL(kernel_power_off);
353
354static DEFINE_MUTEX(reboot_mutex);
355
352/* 356/*
353 * Reboot system call: for obvious reasons only root may call it, 357 * 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 358 * and even root needs to set up some magic numbers in the registers
@@ -381,7 +385,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
381 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) 385 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
382 cmd = LINUX_REBOOT_CMD_HALT; 386 cmd = LINUX_REBOOT_CMD_HALT;
383 387
384 lock_kernel(); 388 mutex_lock(&reboot_mutex);
385 switch (cmd) { 389 switch (cmd) {
386 case LINUX_REBOOT_CMD_RESTART: 390 case LINUX_REBOOT_CMD_RESTART:
387 kernel_restart(NULL); 391 kernel_restart(NULL);
@@ -397,20 +401,18 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
397 401
398 case LINUX_REBOOT_CMD_HALT: 402 case LINUX_REBOOT_CMD_HALT:
399 kernel_halt(); 403 kernel_halt();
400 unlock_kernel();
401 do_exit(0); 404 do_exit(0);
402 panic("cannot halt"); 405 panic("cannot halt");
403 406
404 case LINUX_REBOOT_CMD_POWER_OFF: 407 case LINUX_REBOOT_CMD_POWER_OFF:
405 kernel_power_off(); 408 kernel_power_off();
406 unlock_kernel();
407 do_exit(0); 409 do_exit(0);
408 break; 410 break;
409 411
410 case LINUX_REBOOT_CMD_RESTART2: 412 case LINUX_REBOOT_CMD_RESTART2:
411 if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) { 413 if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
412 unlock_kernel(); 414 ret = -EFAULT;
413 return -EFAULT; 415 break;
414 } 416 }
415 buffer[sizeof(buffer) - 1] = '\0'; 417 buffer[sizeof(buffer) - 1] = '\0';
416 418
@@ -433,7 +435,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
433 ret = -EINVAL; 435 ret = -EINVAL;
434 break; 436 break;
435 } 437 }
436 unlock_kernel(); 438 mutex_unlock(&reboot_mutex);
437 return ret; 439 return ret;
438} 440}
439 441
@@ -911,16 +913,15 @@ change_okay:
911 913
912void do_sys_times(struct tms *tms) 914void do_sys_times(struct tms *tms)
913{ 915{
914 struct task_cputime cputime; 916 cputime_t tgutime, tgstime, cutime, cstime;
915 cputime_t cutime, cstime;
916 917
917 thread_group_cputime(current, &cputime);
918 spin_lock_irq(&current->sighand->siglock); 918 spin_lock_irq(&current->sighand->siglock);
919 thread_group_times(current, &tgutime, &tgstime);
919 cutime = current->signal->cutime; 920 cutime = current->signal->cutime;
920 cstime = current->signal->cstime; 921 cstime = current->signal->cstime;
921 spin_unlock_irq(&current->sighand->siglock); 922 spin_unlock_irq(&current->sighand->siglock);
922 tms->tms_utime = cputime_to_clock_t(cputime.utime); 923 tms->tms_utime = cputime_to_clock_t(tgutime);
923 tms->tms_stime = cputime_to_clock_t(cputime.stime); 924 tms->tms_stime = cputime_to_clock_t(tgstime);
924 tms->tms_cutime = cputime_to_clock_t(cutime); 925 tms->tms_cutime = cputime_to_clock_t(cutime);
925 tms->tms_cstime = cputime_to_clock_t(cstime); 926 tms->tms_cstime = cputime_to_clock_t(cstime);
926} 927}
@@ -1110,6 +1111,8 @@ SYSCALL_DEFINE0(setsid)
1110 err = session; 1111 err = session;
1111out: 1112out:
1112 write_unlock_irq(&tasklist_lock); 1113 write_unlock_irq(&tasklist_lock);
1114 if (err > 0)
1115 proc_sid_connector(group_leader);
1113 return err; 1116 return err;
1114} 1117}
1115 1118
@@ -1336,16 +1339,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1336{ 1339{
1337 struct task_struct *t; 1340 struct task_struct *t;
1338 unsigned long flags; 1341 unsigned long flags;
1339 cputime_t utime, stime; 1342 cputime_t tgutime, tgstime, utime, stime;
1340 struct task_cputime cputime;
1341 unsigned long maxrss = 0; 1343 unsigned long maxrss = 0;
1342 1344
1343 memset((char *) r, 0, sizeof *r); 1345 memset((char *) r, 0, sizeof *r);
1344 utime = stime = cputime_zero; 1346 utime = stime = cputime_zero;
1345 1347
1346 if (who == RUSAGE_THREAD) { 1348 if (who == RUSAGE_THREAD) {
1347 utime = task_utime(current); 1349 task_times(current, &utime, &stime);
1348 stime = task_stime(current);
1349 accumulate_thread_rusage(p, r); 1350 accumulate_thread_rusage(p, r);
1350 maxrss = p->signal->maxrss; 1351 maxrss = p->signal->maxrss;
1351 goto out; 1352 goto out;
@@ -1371,9 +1372,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1371 break; 1372 break;
1372 1373
1373 case RUSAGE_SELF: 1374 case RUSAGE_SELF:
1374 thread_group_cputime(p, &cputime); 1375 thread_group_times(p, &tgutime, &tgstime);
1375 utime = cputime_add(utime, cputime.utime); 1376 utime = cputime_add(utime, tgutime);
1376 stime = cputime_add(stime, cputime.stime); 1377 stime = cputime_add(stime, tgstime);
1377 r->ru_nvcsw += p->signal->nvcsw; 1378 r->ru_nvcsw += p->signal->nvcsw;
1378 r->ru_nivcsw += p->signal->nivcsw; 1379 r->ru_nivcsw += p->signal->nivcsw;
1379 r->ru_minflt += p->signal->min_flt; 1380 r->ru_minflt += p->signal->min_flt;
@@ -1546,24 +1547,37 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
1546 if (arg4 | arg5) 1547 if (arg4 | arg5)
1547 return -EINVAL; 1548 return -EINVAL;
1548 switch (arg2) { 1549 switch (arg2) {
1549 case 0: 1550 case PR_MCE_KILL_CLEAR:
1550 if (arg3 != 0) 1551 if (arg3 != 0)
1551 return -EINVAL; 1552 return -EINVAL;
1552 current->flags &= ~PF_MCE_PROCESS; 1553 current->flags &= ~PF_MCE_PROCESS;
1553 break; 1554 break;
1554 case 1: 1555 case PR_MCE_KILL_SET:
1555 current->flags |= PF_MCE_PROCESS; 1556 current->flags |= PF_MCE_PROCESS;
1556 if (arg3 != 0) 1557 if (arg3 == PR_MCE_KILL_EARLY)
1557 current->flags |= PF_MCE_EARLY; 1558 current->flags |= PF_MCE_EARLY;
1558 else 1559 else if (arg3 == PR_MCE_KILL_LATE)
1559 current->flags &= ~PF_MCE_EARLY; 1560 current->flags &= ~PF_MCE_EARLY;
1561 else if (arg3 == PR_MCE_KILL_DEFAULT)
1562 current->flags &=
1563 ~(PF_MCE_EARLY|PF_MCE_PROCESS);
1564 else
1565 return -EINVAL;
1560 break; 1566 break;
1561 default: 1567 default:
1562 return -EINVAL; 1568 return -EINVAL;
1563 } 1569 }
1564 error = 0; 1570 error = 0;
1565 break; 1571 break;
1566 1572 case PR_MCE_KILL_GET:
1573 if (arg2 | arg3 | arg4 | arg5)
1574 return -EINVAL;
1575 if (current->flags & PF_MCE_PROCESS)
1576 error = (current->flags & PF_MCE_EARLY) ?
1577 PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;
1578 else
1579 error = PR_MCE_KILL_DEFAULT;
1580 break;
1567 default: 1581 default:
1568 error = -EINVAL; 1582 error = -EINVAL;
1569 break; 1583 break;