aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c103
1 files changed, 55 insertions, 48 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index bce933ebb29f..0929c698affc 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -19,6 +19,7 @@
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/kexec.h> 20#include <linux/kexec.h>
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22#include <linux/capability.h>
22#include <linux/device.h> 23#include <linux/device.h>
23#include <linux/key.h> 24#include <linux/key.h>
24#include <linux/times.h> 25#include <linux/times.h>
@@ -32,6 +33,7 @@
32 33
33#include <linux/compat.h> 34#include <linux/compat.h>
34#include <linux/syscalls.h> 35#include <linux/syscalls.h>
36#include <linux/kprobes.h>
35 37
36#include <asm/uaccess.h> 38#include <asm/uaccess.h>
37#include <asm/io.h> 39#include <asm/io.h>
@@ -168,7 +170,7 @@ EXPORT_SYMBOL(notifier_chain_unregister);
168 * of the last notifier function called. 170 * of the last notifier function called.
169 */ 171 */
170 172
171int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v) 173int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
172{ 174{
173 int ret=NOTIFY_DONE; 175 int ret=NOTIFY_DONE;
174 struct notifier_block *nb = *n; 176 struct notifier_block *nb = *n;
@@ -222,6 +224,18 @@ int unregister_reboot_notifier(struct notifier_block * nb)
222 224
223EXPORT_SYMBOL(unregister_reboot_notifier); 225EXPORT_SYMBOL(unregister_reboot_notifier);
224 226
227#ifndef CONFIG_SECURITY
228int capable(int cap)
229{
230 if (cap_raised(current->cap_effective, cap)) {
231 current->flags |= PF_SUPERPRIV;
232 return 1;
233 }
234 return 0;
235}
236EXPORT_SYMBOL(capable);
237#endif
238
225static int set_one_prio(struct task_struct *p, int niceval, int error) 239static int set_one_prio(struct task_struct *p, int niceval, int error)
226{ 240{
227 int no_nice; 241 int no_nice;
@@ -426,23 +440,25 @@ void kernel_kexec(void)
426} 440}
427EXPORT_SYMBOL_GPL(kernel_kexec); 441EXPORT_SYMBOL_GPL(kernel_kexec);
428 442
443void kernel_shutdown_prepare(enum system_states state)
444{
445 notifier_call_chain(&reboot_notifier_list,
446 (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
447 system_state = state;
448 device_shutdown();
449}
429/** 450/**
430 * kernel_halt - halt the system 451 * kernel_halt - halt the system
431 * 452 *
432 * Shutdown everything and perform a clean system halt. 453 * Shutdown everything and perform a clean system halt.
433 */ 454 */
434void kernel_halt_prepare(void)
435{
436 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
437 system_state = SYSTEM_HALT;
438 device_shutdown();
439}
440void kernel_halt(void) 455void kernel_halt(void)
441{ 456{
442 kernel_halt_prepare(); 457 kernel_shutdown_prepare(SYSTEM_HALT);
443 printk(KERN_EMERG "System halted.\n"); 458 printk(KERN_EMERG "System halted.\n");
444 machine_halt(); 459 machine_halt();
445} 460}
461
446EXPORT_SYMBOL_GPL(kernel_halt); 462EXPORT_SYMBOL_GPL(kernel_halt);
447 463
448/** 464/**
@@ -450,20 +466,13 @@ EXPORT_SYMBOL_GPL(kernel_halt);
450 * 466 *
451 * Shutdown everything and perform a clean system power_off. 467 * Shutdown everything and perform a clean system power_off.
452 */ 468 */
453void kernel_power_off_prepare(void)
454{
455 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
456 system_state = SYSTEM_POWER_OFF;
457 device_shutdown();
458}
459void kernel_power_off(void) 469void kernel_power_off(void)
460{ 470{
461 kernel_power_off_prepare(); 471 kernel_shutdown_prepare(SYSTEM_POWER_OFF);
462 printk(KERN_EMERG "Power down.\n"); 472 printk(KERN_EMERG "Power down.\n");
463 machine_power_off(); 473 machine_power_off();
464} 474}
465EXPORT_SYMBOL_GPL(kernel_power_off); 475EXPORT_SYMBOL_GPL(kernel_power_off);
466
467/* 476/*
468 * Reboot system call: for obvious reasons only root may call it, 477 * Reboot system call: for obvious reasons only root may call it,
469 * and even root needs to set up some magic numbers in the registers 478 * and even root needs to set up some magic numbers in the registers
@@ -488,6 +497,12 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
488 magic2 != LINUX_REBOOT_MAGIC2C)) 497 magic2 != LINUX_REBOOT_MAGIC2C))
489 return -EINVAL; 498 return -EINVAL;
490 499
500 /* Instead of trying to make the power_off code look like
501 * halt when pm_power_off is not set do it the easy way.
502 */
503 if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
504 cmd = LINUX_REBOOT_CMD_HALT;
505
491 lock_kernel(); 506 lock_kernel();
492 switch (cmd) { 507 switch (cmd) {
493 case LINUX_REBOOT_CMD_RESTART: 508 case LINUX_REBOOT_CMD_RESTART:
@@ -1083,10 +1098,11 @@ asmlinkage long sys_times(struct tms __user * tbuf)
1083asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) 1098asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1084{ 1099{
1085 struct task_struct *p; 1100 struct task_struct *p;
1101 struct task_struct *group_leader = current->group_leader;
1086 int err = -EINVAL; 1102 int err = -EINVAL;
1087 1103
1088 if (!pid) 1104 if (!pid)
1089 pid = current->pid; 1105 pid = group_leader->pid;
1090 if (!pgid) 1106 if (!pgid)
1091 pgid = pid; 1107 pgid = pid;
1092 if (pgid < 0) 1108 if (pgid < 0)
@@ -1106,16 +1122,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1106 if (!thread_group_leader(p)) 1122 if (!thread_group_leader(p))
1107 goto out; 1123 goto out;
1108 1124
1109 if (p->parent == current || p->real_parent == current) { 1125 if (p->real_parent == group_leader) {
1110 err = -EPERM; 1126 err = -EPERM;
1111 if (p->signal->session != current->signal->session) 1127 if (p->signal->session != group_leader->signal->session)
1112 goto out; 1128 goto out;
1113 err = -EACCES; 1129 err = -EACCES;
1114 if (p->did_exec) 1130 if (p->did_exec)
1115 goto out; 1131 goto out;
1116 } else { 1132 } else {
1117 err = -ESRCH; 1133 err = -ESRCH;
1118 if (p != current) 1134 if (p != group_leader)
1119 goto out; 1135 goto out;
1120 } 1136 }
1121 1137
@@ -1127,7 +1143,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1127 struct task_struct *p; 1143 struct task_struct *p;
1128 1144
1129 do_each_task_pid(pgid, PIDTYPE_PGID, p) { 1145 do_each_task_pid(pgid, PIDTYPE_PGID, p) {
1130 if (p->signal->session == current->signal->session) 1146 if (p->signal->session == group_leader->signal->session)
1131 goto ok_pgid; 1147 goto ok_pgid;
1132 } while_each_task_pid(pgid, PIDTYPE_PGID, p); 1148 } while_each_task_pid(pgid, PIDTYPE_PGID, p);
1133 goto out; 1149 goto out;
@@ -1207,24 +1223,22 @@ asmlinkage long sys_getsid(pid_t pid)
1207 1223
1208asmlinkage long sys_setsid(void) 1224asmlinkage long sys_setsid(void)
1209{ 1225{
1226 struct task_struct *group_leader = current->group_leader;
1210 struct pid *pid; 1227 struct pid *pid;
1211 int err = -EPERM; 1228 int err = -EPERM;
1212 1229
1213 if (!thread_group_leader(current))
1214 return -EINVAL;
1215
1216 down(&tty_sem); 1230 down(&tty_sem);
1217 write_lock_irq(&tasklist_lock); 1231 write_lock_irq(&tasklist_lock);
1218 1232
1219 pid = find_pid(PIDTYPE_PGID, current->pid); 1233 pid = find_pid(PIDTYPE_PGID, group_leader->pid);
1220 if (pid) 1234 if (pid)
1221 goto out; 1235 goto out;
1222 1236
1223 current->signal->leader = 1; 1237 group_leader->signal->leader = 1;
1224 __set_special_pids(current->pid, current->pid); 1238 __set_special_pids(group_leader->pid, group_leader->pid);
1225 current->signal->tty = NULL; 1239 group_leader->signal->tty = NULL;
1226 current->signal->tty_old_pgrp = 0; 1240 group_leader->signal->tty_old_pgrp = 0;
1227 err = process_group(current); 1241 err = process_group(group_leader);
1228out: 1242out:
1229 write_unlock_irq(&tasklist_lock); 1243 write_unlock_irq(&tasklist_lock);
1230 up(&tty_sem); 1244 up(&tty_sem);
@@ -1686,7 +1700,10 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1686 if (unlikely(!p->signal)) 1700 if (unlikely(!p->signal))
1687 return; 1701 return;
1688 1702
1703 utime = stime = cputime_zero;
1704
1689 switch (who) { 1705 switch (who) {
1706 case RUSAGE_BOTH:
1690 case RUSAGE_CHILDREN: 1707 case RUSAGE_CHILDREN:
1691 spin_lock_irqsave(&p->sighand->siglock, flags); 1708 spin_lock_irqsave(&p->sighand->siglock, flags);
1692 utime = p->signal->cutime; 1709 utime = p->signal->cutime;
@@ -1696,22 +1713,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1696 r->ru_minflt = p->signal->cmin_flt; 1713 r->ru_minflt = p->signal->cmin_flt;
1697 r->ru_majflt = p->signal->cmaj_flt; 1714 r->ru_majflt = p->signal->cmaj_flt;
1698 spin_unlock_irqrestore(&p->sighand->siglock, flags); 1715 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1699 cputime_to_timeval(utime, &r->ru_utime); 1716
1700 cputime_to_timeval(stime, &r->ru_stime); 1717 if (who == RUSAGE_CHILDREN)
1701 break; 1718 break;
1719
1702 case RUSAGE_SELF: 1720 case RUSAGE_SELF:
1703 spin_lock_irqsave(&p->sighand->siglock, flags);
1704 utime = stime = cputime_zero;
1705 goto sum_group;
1706 case RUSAGE_BOTH:
1707 spin_lock_irqsave(&p->sighand->siglock, flags);
1708 utime = p->signal->cutime;
1709 stime = p->signal->cstime;
1710 r->ru_nvcsw = p->signal->cnvcsw;
1711 r->ru_nivcsw = p->signal->cnivcsw;
1712 r->ru_minflt = p->signal->cmin_flt;
1713 r->ru_majflt = p->signal->cmaj_flt;
1714 sum_group:
1715 utime = cputime_add(utime, p->signal->utime); 1721 utime = cputime_add(utime, p->signal->utime);
1716 stime = cputime_add(stime, p->signal->stime); 1722 stime = cputime_add(stime, p->signal->stime);
1717 r->ru_nvcsw += p->signal->nvcsw; 1723 r->ru_nvcsw += p->signal->nvcsw;
@@ -1728,13 +1734,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1728 r->ru_majflt += t->maj_flt; 1734 r->ru_majflt += t->maj_flt;
1729 t = next_thread(t); 1735 t = next_thread(t);
1730 } while (t != p); 1736 } while (t != p);
1731 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1732 cputime_to_timeval(utime, &r->ru_utime);
1733 cputime_to_timeval(stime, &r->ru_stime);
1734 break; 1737 break;
1738
1735 default: 1739 default:
1736 BUG(); 1740 BUG();
1737 } 1741 }
1742
1743 cputime_to_timeval(utime, &r->ru_utime);
1744 cputime_to_timeval(stime, &r->ru_stime);
1738} 1745}
1739 1746
1740int getrusage(struct task_struct *p, int who, struct rusage __user *ru) 1747int getrusage(struct task_struct *p, int who, struct rusage __user *ru)