diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index eecf84526afe..d09cac23fdfd 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 | ||
| 224 | EXPORT_SYMBOL(unregister_reboot_notifier); | 225 | EXPORT_SYMBOL(unregister_reboot_notifier); |
| 225 | 226 | ||
| 227 | #ifndef CONFIG_SECURITY | ||
| 228 | int 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 | } | ||
| 236 | EXPORT_SYMBOL(capable); | ||
| 237 | #endif | ||
| 238 | |||
| 226 | static int set_one_prio(struct task_struct *p, int niceval, int error) | 239 | static int set_one_prio(struct task_struct *p, int niceval, int error) |
| 227 | { | 240 | { |
| 228 | int no_nice; | 241 | int no_nice; |
| @@ -489,6 +502,12 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user | |||
| 489 | magic2 != LINUX_REBOOT_MAGIC2C)) | 502 | magic2 != LINUX_REBOOT_MAGIC2C)) |
| 490 | return -EINVAL; | 503 | return -EINVAL; |
| 491 | 504 | ||
| 505 | /* Instead of trying to make the power_off code look like | ||
| 506 | * halt when pm_power_off is not set do it the easy way. | ||
| 507 | */ | ||
| 508 | if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) | ||
| 509 | cmd = LINUX_REBOOT_CMD_HALT; | ||
| 510 | |||
| 492 | lock_kernel(); | 511 | lock_kernel(); |
| 493 | switch (cmd) { | 512 | switch (cmd) { |
| 494 | case LINUX_REBOOT_CMD_RESTART: | 513 | case LINUX_REBOOT_CMD_RESTART: |
| @@ -1084,10 +1103,11 @@ asmlinkage long sys_times(struct tms __user * tbuf) | |||
| 1084 | asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | 1103 | asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) |
| 1085 | { | 1104 | { |
| 1086 | struct task_struct *p; | 1105 | struct task_struct *p; |
| 1106 | struct task_struct *group_leader = current->group_leader; | ||
| 1087 | int err = -EINVAL; | 1107 | int err = -EINVAL; |
| 1088 | 1108 | ||
| 1089 | if (!pid) | 1109 | if (!pid) |
| 1090 | pid = current->pid; | 1110 | pid = group_leader->pid; |
| 1091 | if (!pgid) | 1111 | if (!pgid) |
| 1092 | pgid = pid; | 1112 | pgid = pid; |
| 1093 | if (pgid < 0) | 1113 | if (pgid < 0) |
| @@ -1107,16 +1127,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | |||
| 1107 | if (!thread_group_leader(p)) | 1127 | if (!thread_group_leader(p)) |
| 1108 | goto out; | 1128 | goto out; |
| 1109 | 1129 | ||
| 1110 | if (p->parent == current || p->real_parent == current) { | 1130 | if (p->real_parent == group_leader) { |
| 1111 | err = -EPERM; | 1131 | err = -EPERM; |
| 1112 | if (p->signal->session != current->signal->session) | 1132 | if (p->signal->session != group_leader->signal->session) |
| 1113 | goto out; | 1133 | goto out; |
| 1114 | err = -EACCES; | 1134 | err = -EACCES; |
| 1115 | if (p->did_exec) | 1135 | if (p->did_exec) |
| 1116 | goto out; | 1136 | goto out; |
| 1117 | } else { | 1137 | } else { |
| 1118 | err = -ESRCH; | 1138 | err = -ESRCH; |
| 1119 | if (p != current) | 1139 | if (p != group_leader) |
| 1120 | goto out; | 1140 | goto out; |
| 1121 | } | 1141 | } |
| 1122 | 1142 | ||
| @@ -1128,7 +1148,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) | |||
| 1128 | struct task_struct *p; | 1148 | struct task_struct *p; |
| 1129 | 1149 | ||
| 1130 | do_each_task_pid(pgid, PIDTYPE_PGID, p) { | 1150 | do_each_task_pid(pgid, PIDTYPE_PGID, p) { |
| 1131 | if (p->signal->session == current->signal->session) | 1151 | if (p->signal->session == group_leader->signal->session) |
| 1132 | goto ok_pgid; | 1152 | goto ok_pgid; |
| 1133 | } while_each_task_pid(pgid, PIDTYPE_PGID, p); | 1153 | } while_each_task_pid(pgid, PIDTYPE_PGID, p); |
| 1134 | goto out; | 1154 | goto out; |
| @@ -1208,24 +1228,22 @@ asmlinkage long sys_getsid(pid_t pid) | |||
| 1208 | 1228 | ||
| 1209 | asmlinkage long sys_setsid(void) | 1229 | asmlinkage long sys_setsid(void) |
| 1210 | { | 1230 | { |
| 1231 | struct task_struct *group_leader = current->group_leader; | ||
| 1211 | struct pid *pid; | 1232 | struct pid *pid; |
| 1212 | int err = -EPERM; | 1233 | int err = -EPERM; |
| 1213 | 1234 | ||
| 1214 | if (!thread_group_leader(current)) | ||
| 1215 | return -EINVAL; | ||
| 1216 | |||
| 1217 | down(&tty_sem); | 1235 | down(&tty_sem); |
| 1218 | write_lock_irq(&tasklist_lock); | 1236 | write_lock_irq(&tasklist_lock); |
| 1219 | 1237 | ||
| 1220 | pid = find_pid(PIDTYPE_PGID, current->pid); | 1238 | pid = find_pid(PIDTYPE_PGID, group_leader->pid); |
| 1221 | if (pid) | 1239 | if (pid) |
| 1222 | goto out; | 1240 | goto out; |
| 1223 | 1241 | ||
| 1224 | current->signal->leader = 1; | 1242 | group_leader->signal->leader = 1; |
| 1225 | __set_special_pids(current->pid, current->pid); | 1243 | __set_special_pids(group_leader->pid, group_leader->pid); |
| 1226 | current->signal->tty = NULL; | 1244 | group_leader->signal->tty = NULL; |
| 1227 | current->signal->tty_old_pgrp = 0; | 1245 | group_leader->signal->tty_old_pgrp = 0; |
| 1228 | err = process_group(current); | 1246 | err = process_group(group_leader); |
| 1229 | out: | 1247 | out: |
| 1230 | write_unlock_irq(&tasklist_lock); | 1248 | write_unlock_irq(&tasklist_lock); |
| 1231 | up(&tty_sem); | 1249 | up(&tty_sem); |
| @@ -1687,7 +1705,10 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
| 1687 | if (unlikely(!p->signal)) | 1705 | if (unlikely(!p->signal)) |
| 1688 | return; | 1706 | return; |
| 1689 | 1707 | ||
| 1708 | utime = stime = cputime_zero; | ||
| 1709 | |||
| 1690 | switch (who) { | 1710 | switch (who) { |
| 1711 | case RUSAGE_BOTH: | ||
| 1691 | case RUSAGE_CHILDREN: | 1712 | case RUSAGE_CHILDREN: |
| 1692 | spin_lock_irqsave(&p->sighand->siglock, flags); | 1713 | spin_lock_irqsave(&p->sighand->siglock, flags); |
| 1693 | utime = p->signal->cutime; | 1714 | utime = p->signal->cutime; |
| @@ -1697,22 +1718,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
| 1697 | r->ru_minflt = p->signal->cmin_flt; | 1718 | r->ru_minflt = p->signal->cmin_flt; |
| 1698 | r->ru_majflt = p->signal->cmaj_flt; | 1719 | r->ru_majflt = p->signal->cmaj_flt; |
| 1699 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 1720 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
| 1700 | cputime_to_timeval(utime, &r->ru_utime); | 1721 | |
| 1701 | cputime_to_timeval(stime, &r->ru_stime); | 1722 | if (who == RUSAGE_CHILDREN) |
| 1702 | break; | 1723 | break; |
| 1724 | |||
| 1703 | case RUSAGE_SELF: | 1725 | 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); | 1726 | utime = cputime_add(utime, p->signal->utime); |
| 1717 | stime = cputime_add(stime, p->signal->stime); | 1727 | stime = cputime_add(stime, p->signal->stime); |
| 1718 | r->ru_nvcsw += p->signal->nvcsw; | 1728 | r->ru_nvcsw += p->signal->nvcsw; |
| @@ -1729,13 +1739,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
| 1729 | r->ru_majflt += t->maj_flt; | 1739 | r->ru_majflt += t->maj_flt; |
| 1730 | t = next_thread(t); | 1740 | t = next_thread(t); |
| 1731 | } while (t != p); | 1741 | } 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; | 1742 | break; |
| 1743 | |||
| 1736 | default: | 1744 | default: |
| 1737 | BUG(); | 1745 | BUG(); |
| 1738 | } | 1746 | } |
| 1747 | |||
| 1748 | cputime_to_timeval(utime, &r->ru_utime); | ||
| 1749 | cputime_to_timeval(stime, &r->ru_stime); | ||
| 1739 | } | 1750 | } |
| 1740 | 1751 | ||
| 1741 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) | 1752 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) |
