aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c100
1 files changed, 53 insertions, 47 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index eecf84526afe..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>
@@ -223,6 +224,18 @@ int unregister_reboot_notifier(struct notifier_block * nb)
223 224
224EXPORT_SYMBOL(unregister_reboot_notifier); 225EXPORT_SYMBOL(unregister_reboot_notifier);
225 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
226static 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)
227{ 240{
228 int no_nice; 241 int no_nice;
@@ -427,23 +440,25 @@ void kernel_kexec(void)
427} 440}
428EXPORT_SYMBOL_GPL(kernel_kexec); 441EXPORT_SYMBOL_GPL(kernel_kexec);
429 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}
430/** 450/**
431 * kernel_halt - halt the system 451 * kernel_halt - halt the system
432 * 452 *
433 * Shutdown everything and perform a clean system halt. 453 * Shutdown everything and perform a clean system halt.
434 */ 454 */
435void kernel_halt_prepare(void)
436{
437 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
438 system_state = SYSTEM_HALT;
439 device_shutdown();
440}
441void kernel_halt(void) 455void kernel_halt(void)
442{ 456{
443 kernel_halt_prepare(); 457 kernel_shutdown_prepare(SYSTEM_HALT);
444 printk(KERN_EMERG "System halted.\n"); 458 printk(KERN_EMERG "System halted.\n");
445 machine_halt(); 459 machine_halt();
446} 460}
461
447EXPORT_SYMBOL_GPL(kernel_halt); 462EXPORT_SYMBOL_GPL(kernel_halt);
448 463
449/** 464/**
@@ -451,20 +466,13 @@ EXPORT_SYMBOL_GPL(kernel_halt);
451 * 466 *
452 * Shutdown everything and perform a clean system power_off. 467 * Shutdown everything and perform a clean system power_off.
453 */ 468 */
454void kernel_power_off_prepare(void)
455{
456 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
457 system_state = SYSTEM_POWER_OFF;
458 device_shutdown();
459}
460void kernel_power_off(void) 469void kernel_power_off(void)
461{ 470{
462 kernel_power_off_prepare(); 471 kernel_shutdown_prepare(SYSTEM_POWER_OFF);
463 printk(KERN_EMERG "Power down.\n"); 472 printk(KERN_EMERG "Power down.\n");
464 machine_power_off(); 473 machine_power_off();
465} 474}
466EXPORT_SYMBOL_GPL(kernel_power_off); 475EXPORT_SYMBOL_GPL(kernel_power_off);
467
468/* 476/*
469 * Reboot system call: for obvious reasons only root may call it, 477 * Reboot system call: for obvious reasons only root may call it,
470 * 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
@@ -489,6 +497,12 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
489 magic2 != LINUX_REBOOT_MAGIC2C)) 497 magic2 != LINUX_REBOOT_MAGIC2C))
490 return -EINVAL; 498 return -EINVAL;
491 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
492 lock_kernel(); 506 lock_kernel();
493 switch (cmd) { 507 switch (cmd) {
494 case LINUX_REBOOT_CMD_RESTART: 508 case LINUX_REBOOT_CMD_RESTART:
@@ -1084,10 +1098,11 @@ asmlinkage long sys_times(struct tms __user * tbuf)
1084asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) 1098asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1085{ 1099{
1086 struct task_struct *p; 1100 struct task_struct *p;
1101 struct task_struct *group_leader = current->group_leader;
1087 int err = -EINVAL; 1102 int err = -EINVAL;
1088 1103
1089 if (!pid) 1104 if (!pid)
1090 pid = current->pid; 1105 pid = group_leader->pid;
1091 if (!pgid) 1106 if (!pgid)
1092 pgid = pid; 1107 pgid = pid;
1093 if (pgid < 0) 1108 if (pgid < 0)
@@ -1107,16 +1122,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1107 if (!thread_group_leader(p)) 1122 if (!thread_group_leader(p))
1108 goto out; 1123 goto out;
1109 1124
1110 if (p->parent == current || p->real_parent == current) { 1125 if (p->real_parent == group_leader) {
1111 err = -EPERM; 1126 err = -EPERM;
1112 if (p->signal->session != current->signal->session) 1127 if (p->signal->session != group_leader->signal->session)
1113 goto out; 1128 goto out;
1114 err = -EACCES; 1129 err = -EACCES;
1115 if (p->did_exec) 1130 if (p->did_exec)
1116 goto out; 1131 goto out;
1117 } else { 1132 } else {
1118 err = -ESRCH; 1133 err = -ESRCH;
1119 if (p != current) 1134 if (p != group_leader)
1120 goto out; 1135 goto out;
1121 } 1136 }
1122 1137
@@ -1128,7 +1143,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1128 struct task_struct *p; 1143 struct task_struct *p;
1129 1144
1130 do_each_task_pid(pgid, PIDTYPE_PGID, p) { 1145 do_each_task_pid(pgid, PIDTYPE_PGID, p) {
1131 if (p->signal->session == current->signal->session) 1146 if (p->signal->session == group_leader->signal->session)
1132 goto ok_pgid; 1147 goto ok_pgid;
1133 } while_each_task_pid(pgid, PIDTYPE_PGID, p); 1148 } while_each_task_pid(pgid, PIDTYPE_PGID, p);
1134 goto out; 1149 goto out;
@@ -1208,24 +1223,22 @@ asmlinkage long sys_getsid(pid_t pid)
1208 1223
1209asmlinkage long sys_setsid(void) 1224asmlinkage long sys_setsid(void)
1210{ 1225{
1226 struct task_struct *group_leader = current->group_leader;
1211 struct pid *pid; 1227 struct pid *pid;
1212 int err = -EPERM; 1228 int err = -EPERM;
1213 1229
1214 if (!thread_group_leader(current))
1215 return -EINVAL;
1216
1217 down(&tty_sem); 1230 down(&tty_sem);
1218 write_lock_irq(&tasklist_lock); 1231 write_lock_irq(&tasklist_lock);
1219 1232
1220 pid = find_pid(PIDTYPE_PGID, current->pid); 1233 pid = find_pid(PIDTYPE_PGID, group_leader->pid);
1221 if (pid) 1234 if (pid)
1222 goto out; 1235 goto out;
1223 1236
1224 current->signal->leader = 1; 1237 group_leader->signal->leader = 1;
1225 __set_special_pids(current->pid, current->pid); 1238 __set_special_pids(group_leader->pid, group_leader->pid);
1226 current->signal->tty = NULL; 1239 group_leader->signal->tty = NULL;
1227 current->signal->tty_old_pgrp = 0; 1240 group_leader->signal->tty_old_pgrp = 0;
1228 err = process_group(current); 1241 err = process_group(group_leader);
1229out: 1242out:
1230 write_unlock_irq(&tasklist_lock); 1243 write_unlock_irq(&tasklist_lock);
1231 up(&tty_sem); 1244 up(&tty_sem);
@@ -1687,7 +1700,10 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1687 if (unlikely(!p->signal)) 1700 if (unlikely(!p->signal))
1688 return; 1701 return;
1689 1702
1703 utime = stime = cputime_zero;
1704
1690 switch (who) { 1705 switch (who) {
1706 case RUSAGE_BOTH:
1691 case RUSAGE_CHILDREN: 1707 case RUSAGE_CHILDREN:
1692 spin_lock_irqsave(&p->sighand->siglock, flags); 1708 spin_lock_irqsave(&p->sighand->siglock, flags);
1693 utime = p->signal->cutime; 1709 utime = p->signal->cutime;
@@ -1697,22 +1713,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1697 r->ru_minflt = p->signal->cmin_flt; 1713 r->ru_minflt = p->signal->cmin_flt;
1698 r->ru_majflt = p->signal->cmaj_flt; 1714 r->ru_majflt = p->signal->cmaj_flt;
1699 spin_unlock_irqrestore(&p->sighand->siglock, flags); 1715 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1700 cputime_to_timeval(utime, &r->ru_utime); 1716
1701 cputime_to_timeval(stime, &r->ru_stime); 1717 if (who == RUSAGE_CHILDREN)
1702 break; 1718 break;
1719
1703 case RUSAGE_SELF: 1720 case RUSAGE_SELF:
1704 spin_lock_irqsave(&p->sighand->siglock, flags);
1705 utime = stime = cputime_zero;
1706 goto sum_group;
1707 case RUSAGE_BOTH:
1708 spin_lock_irqsave(&p->sighand->siglock, flags);
1709 utime = p->signal->cutime;
1710 stime = p->signal->cstime;
1711 r->ru_nvcsw = p->signal->cnvcsw;
1712 r->ru_nivcsw = p->signal->cnivcsw;
1713 r->ru_minflt = p->signal->cmin_flt;
1714 r->ru_majflt = p->signal->cmaj_flt;
1715 sum_group:
1716 utime = cputime_add(utime, p->signal->utime); 1721 utime = cputime_add(utime, p->signal->utime);
1717 stime = cputime_add(stime, p->signal->stime); 1722 stime = cputime_add(stime, p->signal->stime);
1718 r->ru_nvcsw += p->signal->nvcsw; 1723 r->ru_nvcsw += p->signal->nvcsw;
@@ -1729,13 +1734,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
1729 r->ru_majflt += t->maj_flt; 1734 r->ru_majflt += t->maj_flt;
1730 t = next_thread(t); 1735 t = next_thread(t);
1731 } while (t != p); 1736 } while (t != p);
1732 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1733 cputime_to_timeval(utime, &r->ru_utime);
1734 cputime_to_timeval(stime, &r->ru_stime);
1735 break; 1737 break;
1738
1736 default: 1739 default:
1737 BUG(); 1740 BUG();
1738 } 1741 }
1742
1743 cputime_to_timeval(utime, &r->ru_utime);
1744 cputime_to_timeval(stime, &r->ru_stime);
1739} 1745}
1740 1746
1741int getrusage(struct task_struct *p, int who, struct rusage __user *ru) 1747int getrusage(struct task_struct *p, int who, struct rusage __user *ru)