#include <linux/kernel.h>
#include <linux/kexec.h>
#include <linux/workqueue.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/key.h>
#include <linux/times.h>
#include <linux/suspend.h>
#include <linux/tty.h>
#include <linux/signal.h>
+#include <linux/cn_proc.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
+#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/io.h>
* of the last notifier function called.
*/
-int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
+int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
{
int ret=NOTIFY_DONE;
struct notifier_block *nb = *n;
EXPORT_SYMBOL(unregister_reboot_notifier);
+#ifndef CONFIG_SECURITY
+int capable(int cap)
+{
+ if (cap_raised(current->cap_effective, cap)) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(capable);
+#endif
+
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
int no_nice;
return retval;
}
-void kernel_restart(char *cmd)
+/**
+ * emergency_restart - reboot the system
+ *
+ * Without shutting down any hardware or taking any locks
+ * reboot the system. This is called when we know we are in
+ * trouble so this is our best effort to reboot. This is
+ * safe to call in interrupt context.
+ */
+void emergency_restart(void)
+{
+ machine_emergency_restart();
+}
+EXPORT_SYMBOL_GPL(emergency_restart);
+
+void kernel_restart_prepare(char *cmd)
{
notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
- device_suspend(PMSG_FREEZE);
device_shutdown();
+}
+
+/**
+ * kernel_restart - reboot the system
+ * @cmd: pointer to buffer containing command to execute for restart
+ * or %NULL
+ *
+ * Shutdown everything and perform a clean reboot.
+ * This is not safe to call in interrupt context.
+ */
+void kernel_restart(char *cmd)
+{
+ kernel_restart_prepare(cmd);
if (!cmd) {
printk(KERN_EMERG "Restarting system.\n");
} else {
}
EXPORT_SYMBOL_GPL(kernel_restart);
+/**
+ * kernel_kexec - reboot the system
+ *
+ * Move into place and start executing a preloaded standalone
+ * executable. If nothing was preloaded return an error.
+ */
void kernel_kexec(void)
{
#ifdef CONFIG_KEXEC
if (!image) {
return;
}
- notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
- system_state = SYSTEM_RESTART;
- device_suspend(PMSG_FREEZE);
- device_shutdown();
+ kernel_restart_prepare(NULL);
printk(KERN_EMERG "Starting new kernel\n");
machine_shutdown();
machine_kexec(image);
}
EXPORT_SYMBOL_GPL(kernel_kexec);
-void kernel_halt(void)
+/**
+ * kernel_halt - halt the system
+ *
+ * Shutdown everything and perform a clean system halt.
+ */
+void kernel_halt_prepare(void)
{
notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
system_state = SYSTEM_HALT;
- device_suspend(PMSG_SUSPEND);
device_shutdown();
+}
+void kernel_halt(void)
+{
+ kernel_halt_prepare();
printk(KERN_EMERG "System halted.\n");
machine_halt();
}
EXPORT_SYMBOL_GPL(kernel_halt);
-void kernel_power_off(void)
+/**
+ * kernel_power_off - power_off the system
+ *
+ * Shutdown everything and perform a clean system power_off.
+ */
+void kernel_power_off_prepare(void)
{
notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
system_state = SYSTEM_POWER_OFF;
- device_suspend(PMSG_SUSPEND);
device_shutdown();
+}
+void kernel_power_off(void)
+{
+ kernel_power_off_prepare();
printk(KERN_EMERG "Power down.\n");
machine_power_off();
}
magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;
+ /* Instead of trying to make the power_off code look like
+ * halt when pm_power_off is not set do it the easy way.
+ */
+ if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
+ cmd = LINUX_REBOOT_CMD_HALT;
+
lock_kernel();
switch (cmd) {
case LINUX_REBOOT_CMD_RESTART:
current->egid = new_egid;
current->gid = new_rgid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
return -EPERM;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
current->fsuid = current->euid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
current->suid = new_suid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
current->suid = suid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
current->sgid = sgid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
}
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
}
current->fsgid = gid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
}
return old_fsgid;
}
asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
{
struct task_struct *p;
+ struct task_struct *group_leader = current->group_leader;
int err = -EINVAL;
if (!pid)
- pid = current->pid;
+ pid = group_leader->pid;
if (!pgid)
pgid = pid;
if (pgid < 0)
if (!thread_group_leader(p))
goto out;
- if (p->parent == current || p->real_parent == current) {
+ if (p->real_parent == group_leader) {
err = -EPERM;
- if (p->signal->session != current->signal->session)
+ if (p->signal->session != group_leader->signal->session)
goto out;
err = -EACCES;
if (p->did_exec)
goto out;
} else {
err = -ESRCH;
- if (p != current)
+ if (p != group_leader)
goto out;
}
struct task_struct *p;
do_each_task_pid(pgid, PIDTYPE_PGID, p) {
- if (p->signal->session == current->signal->session)
+ if (p->signal->session == group_leader->signal->session)
goto ok_pgid;
} while_each_task_pid(pgid, PIDTYPE_PGID, p);
goto out;
asmlinkage long sys_setsid(void)
{
+ struct task_struct *group_leader = current->group_leader;
struct pid *pid;
int err = -EPERM;
- if (!thread_group_leader(current))
- return -EINVAL;
-
down(&tty_sem);
write_lock_irq(&tasklist_lock);
- pid = find_pid(PIDTYPE_PGID, current->pid);
+ pid = find_pid(PIDTYPE_PGID, group_leader->pid);
if (pid)
goto out;
- current->signal->leader = 1;
- __set_special_pids(current->pid, current->pid);
- current->signal->tty = NULL;
- current->signal->tty_old_pgrp = 0;
- err = process_group(current);
+ group_leader->signal->leader = 1;
+ __set_special_pids(group_leader->pid, group_leader->pid);
+ group_leader->signal->tty = NULL;
+ group_leader->signal->tty_old_pgrp = 0;
+ err = process_group(group_leader);
out:
write_unlock_irq(&tasklist_lock);
up(&tty_sem);
if (unlikely(!p->signal))
return;
+ utime = stime = cputime_zero;
+
switch (who) {
+ case RUSAGE_BOTH:
case RUSAGE_CHILDREN:
spin_lock_irqsave(&p->sighand->siglock, flags);
utime = p->signal->cutime;
r->ru_minflt = p->signal->cmin_flt;
r->ru_majflt = p->signal->cmaj_flt;
spin_unlock_irqrestore(&p->sighand->siglock, flags);
- cputime_to_timeval(utime, &r->ru_utime);
- cputime_to_timeval(stime, &r->ru_stime);
- break;
+
+ if (who == RUSAGE_CHILDREN)
+ break;
+
case RUSAGE_SELF:
- spin_lock_irqsave(&p->sighand->siglock, flags);
- utime = stime = cputime_zero;
- goto sum_group;
- case RUSAGE_BOTH:
- spin_lock_irqsave(&p->sighand->siglock, flags);
- utime = p->signal->cutime;
- stime = p->signal->cstime;
- r->ru_nvcsw = p->signal->cnvcsw;
- r->ru_nivcsw = p->signal->cnivcsw;
- r->ru_minflt = p->signal->cmin_flt;
- r->ru_majflt = p->signal->cmaj_flt;
- sum_group:
utime = cputime_add(utime, p->signal->utime);
stime = cputime_add(stime, p->signal->stime);
r->ru_nvcsw += p->signal->nvcsw;
r->ru_majflt += t->maj_flt;
t = next_thread(t);
} while (t != p);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
- cputime_to_timeval(utime, &r->ru_utime);
- cputime_to_timeval(stime, &r->ru_stime);
break;
+
default:
BUG();
}
+
+ cputime_to_timeval(utime, &r->ru_utime);
+ cputime_to_timeval(stime, &r->ru_stime);
}
int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
unsigned long arg4, unsigned long arg5)
{
long error;
- int sig;
error = security_task_prctl(option, arg2, arg3, arg4, arg5);
if (error)
switch (option) {
case PR_SET_PDEATHSIG:
- sig = arg2;
- if (!valid_signal(sig)) {
+ if (!valid_signal(arg2)) {
error = -EINVAL;
break;
}
- current->pdeath_signal = sig;
+ current->pdeath_signal = arg2;
break;
case PR_GET_PDEATHSIG:
error = put_user(current->pdeath_signal, (int __user *)arg2);
break;
case PR_GET_DUMPABLE:
- if (current->mm->dumpable)
- error = 1;
+ error = current->mm->dumpable;
break;
case PR_SET_DUMPABLE:
if (arg2 < 0 || arg2 > 2) {