OSDN Git Service

Merge git://www.linux-watchdog.org/linux-watchdog
[android-x86/kernel.git] / kernel / sys.c
index 8326105..81f5644 100644 (file)
@@ -434,11 +434,12 @@ static DEFINE_MUTEX(reboot_mutex);
 SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                void __user *, arg)
 {
+       struct pid_namespace *pid_ns = task_active_pid_ns(current);
        char buffer[256];
        int ret = 0;
 
        /* We only trust the superuser with rebooting the system. */
-       if (!capable(CAP_SYS_BOOT))
+       if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
                return -EPERM;
 
        /* For safety, we require "magic" arguments. */
@@ -454,7 +455,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
         * pid_namespace, the command is handled by reboot_pid_ns() which will
         * call do_exit().
         */
-       ret = reboot_pid_ns(task_active_pid_ns(current), cmd);
+       ret = reboot_pid_ns(pid_ns, cmd);
        if (ret)
                return ret;
 
@@ -1793,14 +1794,14 @@ SYSCALL_DEFINE1(umask, int, mask)
 static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
 {
        struct fd exe;
-       struct dentry *dentry;
+       struct inode *inode;
        int err;
 
        exe = fdget(fd);
        if (!exe.file)
                return -EBADF;
 
-       dentry = exe.file->f_path.dentry;
+       inode = file_inode(exe.file);
 
        /*
         * Because the original mm->exe_file points to executable file, make
@@ -1808,11 +1809,11 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
         * overall picture.
         */
        err = -EACCES;
-       if (!S_ISREG(dentry->d_inode->i_mode)   ||
+       if (!S_ISREG(inode->i_mode)     ||
            exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
                goto exit;
 
-       err = inode_permission(dentry->d_inode, MAY_EXEC);
+       err = inode_permission(inode, MAY_EXEC);
        if (err)
                goto exit;
 
@@ -2013,161 +2014,159 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 
        error = 0;
        switch (option) {
-               case PR_SET_PDEATHSIG:
-                       if (!valid_signal(arg2)) {
-                               error = -EINVAL;
-                               break;
-                       }
-                       me->pdeath_signal = arg2;
-                       break;
-               case PR_GET_PDEATHSIG:
-                       error = put_user(me->pdeath_signal, (int __user *)arg2);
-                       break;
-               case PR_GET_DUMPABLE:
-                       error = get_dumpable(me->mm);
+       case PR_SET_PDEATHSIG:
+               if (!valid_signal(arg2)) {
+                       error = -EINVAL;
                        break;
-               case PR_SET_DUMPABLE:
-                       if (arg2 != SUID_DUMP_DISABLE &&
-                           arg2 != SUID_DUMP_USER) {
-                               error = -EINVAL;
-                               break;
-                       }
-                       set_dumpable(me->mm, arg2);
+               }
+               me->pdeath_signal = arg2;
+               break;
+       case PR_GET_PDEATHSIG:
+               error = put_user(me->pdeath_signal, (int __user *)arg2);
+               break;
+       case PR_GET_DUMPABLE:
+               error = get_dumpable(me->mm);
+               break;
+       case PR_SET_DUMPABLE:
+               if (arg2 != SUID_DUMP_DISABLE && arg2 != SUID_DUMP_USER) {
+                       error = -EINVAL;
                        break;
+               }
+               set_dumpable(me->mm, arg2);
+               break;
 
-               case PR_SET_UNALIGN:
-                       error = SET_UNALIGN_CTL(me, arg2);
-                       break;
-               case PR_GET_UNALIGN:
-                       error = GET_UNALIGN_CTL(me, arg2);
-                       break;
-               case PR_SET_FPEMU:
-                       error = SET_FPEMU_CTL(me, arg2);
-                       break;
-               case PR_GET_FPEMU:
-                       error = GET_FPEMU_CTL(me, arg2);
-                       break;
-               case PR_SET_FPEXC:
-                       error = SET_FPEXC_CTL(me, arg2);
-                       break;
-               case PR_GET_FPEXC:
-                       error = GET_FPEXC_CTL(me, arg2);
-                       break;
-               case PR_GET_TIMING:
-                       error = PR_TIMING_STATISTICAL;
-                       break;
-               case PR_SET_TIMING:
-                       if (arg2 != PR_TIMING_STATISTICAL)
-                               error = -EINVAL;
-                       break;
-               case PR_SET_NAME:
-                       comm[sizeof(me->comm)-1] = 0;
-                       if (strncpy_from_user(comm, (char __user *)arg2,
-                                             sizeof(me->comm) - 1) < 0)
-                               return -EFAULT;
-                       set_task_comm(me, comm);
-                       proc_comm_connector(me);
-                       break;
-               case PR_GET_NAME:
-                       get_task_comm(comm, me);
-                       if (copy_to_user((char __user *)arg2, comm,
-                                        sizeof(comm)))
-                               return -EFAULT;
-                       break;
-               case PR_GET_ENDIAN:
-                       error = GET_ENDIAN(me, arg2);
-                       break;
-               case PR_SET_ENDIAN:
-                       error = SET_ENDIAN(me, arg2);
-                       break;
-               case PR_GET_SECCOMP:
-                       error = prctl_get_seccomp();
-                       break;
-               case PR_SET_SECCOMP:
-                       error = prctl_set_seccomp(arg2, (char __user *)arg3);
-                       break;
-               case PR_GET_TSC:
-                       error = GET_TSC_CTL(arg2);
-                       break;
-               case PR_SET_TSC:
-                       error = SET_TSC_CTL(arg2);
-                       break;
-               case PR_TASK_PERF_EVENTS_DISABLE:
-                       error = perf_event_task_disable();
-                       break;
-               case PR_TASK_PERF_EVENTS_ENABLE:
-                       error = perf_event_task_enable();
-                       break;
-               case PR_GET_TIMERSLACK:
-                       error = current->timer_slack_ns;
-                       break;
-               case PR_SET_TIMERSLACK:
-                       if (arg2 <= 0)
-                               current->timer_slack_ns =
+       case PR_SET_UNALIGN:
+               error = SET_UNALIGN_CTL(me, arg2);
+               break;
+       case PR_GET_UNALIGN:
+               error = GET_UNALIGN_CTL(me, arg2);
+               break;
+       case PR_SET_FPEMU:
+               error = SET_FPEMU_CTL(me, arg2);
+               break;
+       case PR_GET_FPEMU:
+               error = GET_FPEMU_CTL(me, arg2);
+               break;
+       case PR_SET_FPEXC:
+               error = SET_FPEXC_CTL(me, arg2);
+               break;
+       case PR_GET_FPEXC:
+               error = GET_FPEXC_CTL(me, arg2);
+               break;
+       case PR_GET_TIMING:
+               error = PR_TIMING_STATISTICAL;
+               break;
+       case PR_SET_TIMING:
+               if (arg2 != PR_TIMING_STATISTICAL)
+                       error = -EINVAL;
+               break;
+       case PR_SET_NAME:
+               comm[sizeof(me->comm) - 1] = 0;
+               if (strncpy_from_user(comm, (char __user *)arg2,
+                                     sizeof(me->comm) - 1) < 0)
+                       return -EFAULT;
+               set_task_comm(me, comm);
+               proc_comm_connector(me);
+               break;
+       case PR_GET_NAME:
+               get_task_comm(comm, me);
+               if (copy_to_user((char __user *)arg2, comm, sizeof(comm)))
+                       return -EFAULT;
+               break;
+       case PR_GET_ENDIAN:
+               error = GET_ENDIAN(me, arg2);
+               break;
+       case PR_SET_ENDIAN:
+               error = SET_ENDIAN(me, arg2);
+               break;
+       case PR_GET_SECCOMP:
+               error = prctl_get_seccomp();
+               break;
+       case PR_SET_SECCOMP:
+               error = prctl_set_seccomp(arg2, (char __user *)arg3);
+               break;
+       case PR_GET_TSC:
+               error = GET_TSC_CTL(arg2);
+               break;
+       case PR_SET_TSC:
+               error = SET_TSC_CTL(arg2);
+               break;
+       case PR_TASK_PERF_EVENTS_DISABLE:
+               error = perf_event_task_disable();
+               break;
+       case PR_TASK_PERF_EVENTS_ENABLE:
+               error = perf_event_task_enable();
+               break;
+       case PR_GET_TIMERSLACK:
+               error = current->timer_slack_ns;
+               break;
+       case PR_SET_TIMERSLACK:
+               if (arg2 <= 0)
+                       current->timer_slack_ns =
                                        current->default_timer_slack_ns;
-                       else
-                               current->timer_slack_ns = arg2;
-                       break;
-               case PR_MCE_KILL:
-                       if (arg4 | arg5)
-                               return -EINVAL;
-                       switch (arg2) {
-                       case PR_MCE_KILL_CLEAR:
-                               if (arg3 != 0)
-                                       return -EINVAL;
-                               current->flags &= ~PF_MCE_PROCESS;
-                               break;
-                       case PR_MCE_KILL_SET:
-                               current->flags |= PF_MCE_PROCESS;
-                               if (arg3 == PR_MCE_KILL_EARLY)
-                                       current->flags |= PF_MCE_EARLY;
-                               else if (arg3 == PR_MCE_KILL_LATE)
-                                       current->flags &= ~PF_MCE_EARLY;
-                               else if (arg3 == PR_MCE_KILL_DEFAULT)
-                                       current->flags &=
-                                               ~(PF_MCE_EARLY|PF_MCE_PROCESS);
-                               else
-                                       return -EINVAL;
-                               break;
-                       default:
+               else
+                       current->timer_slack_ns = arg2;
+               break;
+       case PR_MCE_KILL:
+               if (arg4 | arg5)
+                       return -EINVAL;
+               switch (arg2) {
+               case PR_MCE_KILL_CLEAR:
+                       if (arg3 != 0)
                                return -EINVAL;
-                       }
+                       current->flags &= ~PF_MCE_PROCESS;
                        break;
-               case PR_MCE_KILL_GET:
-                       if (arg2 | arg3 | arg4 | arg5)
-                               return -EINVAL;
-                       if (current->flags & PF_MCE_PROCESS)
-                               error = (current->flags & PF_MCE_EARLY) ?
-                                       PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;
+               case PR_MCE_KILL_SET:
+                       current->flags |= PF_MCE_PROCESS;
+                       if (arg3 == PR_MCE_KILL_EARLY)
+                               current->flags |= PF_MCE_EARLY;
+                       else if (arg3 == PR_MCE_KILL_LATE)
+                               current->flags &= ~PF_MCE_EARLY;
+                       else if (arg3 == PR_MCE_KILL_DEFAULT)
+                               current->flags &=
+                                               ~(PF_MCE_EARLY|PF_MCE_PROCESS);
                        else
-                               error = PR_MCE_KILL_DEFAULT;
-                       break;
-               case PR_SET_MM:
-                       error = prctl_set_mm(arg2, arg3, arg4, arg5);
-                       break;
-               case PR_GET_TID_ADDRESS:
-                       error = prctl_get_tid_address(me, (int __user **)arg2);
-                       break;
-               case PR_SET_CHILD_SUBREAPER:
-                       me->signal->is_child_subreaper = !!arg2;
-                       break;
-               case PR_GET_CHILD_SUBREAPER:
-                       error = put_user(me->signal->is_child_subreaper,
-                                        (int __user *) arg2);
-                       break;
-               case PR_SET_NO_NEW_PRIVS:
-                       if (arg2 != 1 || arg3 || arg4 || arg5)
                                return -EINVAL;
-
-                       current->no_new_privs = 1;
                        break;
-               case PR_GET_NO_NEW_PRIVS:
-                       if (arg2 || arg3 || arg4 || arg5)
-                               return -EINVAL;
-                       return current->no_new_privs ? 1 : 0;
                default:
-                       error = -EINVAL;
-                       break;
+                       return -EINVAL;
+               }
+               break;
+       case PR_MCE_KILL_GET:
+               if (arg2 | arg3 | arg4 | arg5)
+                       return -EINVAL;
+               if (current->flags & PF_MCE_PROCESS)
+                       error = (current->flags & PF_MCE_EARLY) ?
+                               PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE;
+               else
+                       error = PR_MCE_KILL_DEFAULT;
+               break;
+       case PR_SET_MM:
+               error = prctl_set_mm(arg2, arg3, arg4, arg5);
+               break;
+       case PR_GET_TID_ADDRESS:
+               error = prctl_get_tid_address(me, (int __user **)arg2);
+               break;
+       case PR_SET_CHILD_SUBREAPER:
+               me->signal->is_child_subreaper = !!arg2;
+               break;
+       case PR_GET_CHILD_SUBREAPER:
+               error = put_user(me->signal->is_child_subreaper,
+                                (int __user *)arg2);
+               break;
+       case PR_SET_NO_NEW_PRIVS:
+               if (arg2 != 1 || arg3 || arg4 || arg5)
+                       return -EINVAL;
+
+               current->no_new_privs = 1;
+               break;
+       case PR_GET_NO_NEW_PRIVS:
+               if (arg2 || arg3 || arg4 || arg5)
+                       return -EINVAL;
+               return current->no_new_privs ? 1 : 0;
+       default:
+               error = -EINVAL;
+               break;
        }
        return error;
 }
@@ -2186,11 +2185,6 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
 
 char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
 
-static void argv_cleanup(struct subprocess_info *info)
-{
-       argv_free(info->argv);
-}
-
 static int __orderly_poweroff(void)
 {
        int argc;
@@ -2210,9 +2204,8 @@ static int __orderly_poweroff(void)
        }
 
        ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC,
-                                     NULL, argv_cleanup, NULL);
-       if (ret == -ENOMEM)
-               argv_free(argv);
+                                     NULL, NULL, NULL);
+       argv_free(argv);
 
        return ret;
 }