[PATCH] move capable() to capability.h
[safe/jmp/linux-2.6] / kernel / sys.c
index 0bcaed6..d09cac2 100644 (file)
@@ -19,6 +19,7 @@
 #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>
@@ -167,7 +170,7 @@ EXPORT_SYMBOL(notifier_chain_unregister);
  *     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;
@@ -221,6 +224,18 @@ int unregister_reboot_notifier(struct notifier_block * nb)
 
 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;
@@ -361,17 +376,38 @@ out_unlock:
        return retval;
 }
 
+/**
+ *     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(char *cmd)
+void kernel_restart_prepare(char *cmd)
 {
        notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
        system_state = SYSTEM_RESTART;
        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 {
@@ -382,6 +418,12 @@ void kernel_restart(char *cmd)
 }
 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
@@ -390,9 +432,7 @@ void kernel_kexec(void)
        if (!image) {
                return;
        }
-       notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
-       system_state = SYSTEM_RESTART;
-       device_shutdown();
+       kernel_restart_prepare(NULL);
        printk(KERN_EMERG "Starting new kernel\n");
        machine_shutdown();
        machine_kexec(image);
@@ -400,21 +440,39 @@ void kernel_kexec(void)
 }
 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_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_shutdown();
+}
+void kernel_power_off(void)
+{
+       kernel_power_off_prepare();
        printk(KERN_EMERG "Power down.\n");
        machine_power_off();
 }
@@ -444,6 +502,12 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
                        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:
@@ -583,6 +647,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
        current->egid = new_egid;
        current->gid = new_rgid;
        key_fsgid_changed(current);
+       proc_id_connector(current, PROC_EVENT_GID);
        return 0;
 }
 
@@ -622,6 +687,7 @@ asmlinkage long sys_setgid(gid_t gid)
                return -EPERM;
 
        key_fsgid_changed(current);
+       proc_id_connector(current, PROC_EVENT_GID);
        return 0;
 }
   
@@ -711,6 +777,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
        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);
 }
@@ -758,6 +825,7 @@ asmlinkage long sys_setuid(uid_t uid)
        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);
 }
@@ -806,6 +874,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
                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);
 }
@@ -858,6 +927,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
                current->sgid = sgid;
 
        key_fsgid_changed(current);
+       proc_id_connector(current, PROC_EVENT_GID);
        return 0;
 }
 
@@ -900,6 +970,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
        }
 
        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);
 
@@ -928,6 +999,7 @@ asmlinkage long sys_setfsgid(gid_t gid)
                }
                current->fsgid = gid;
                key_fsgid_changed(current);
+               proc_id_connector(current, PROC_EVENT_GID);
        }
        return old_fsgid;
 }
@@ -1031,10 +1103,11 @@ asmlinkage long sys_times(struct tms __user * tbuf)
 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)
@@ -1054,16 +1127,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
        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;
        }
 
@@ -1075,7 +1148,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
                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;
@@ -1155,24 +1228,22 @@ asmlinkage long sys_getsid(pid_t pid)
 
 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);
@@ -1634,7 +1705,10 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
        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;
@@ -1644,22 +1718,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
                        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;
@@ -1676,13 +1739,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
                                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)
@@ -1711,7 +1775,6 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
                          unsigned long arg4, unsigned long arg5)
 {
        long error;
-       int sig;
 
        error = security_task_prctl(option, arg2, arg3, arg4, arg5);
        if (error)
@@ -1719,19 +1782,17 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 
        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) {