These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / kernel / sys.c
index a4e372b..78947de 100644 (file)
 # define SET_TSC_CTL(a)                (-EINVAL)
 #endif
 #ifndef MPX_ENABLE_MANAGEMENT
-# define MPX_ENABLE_MANAGEMENT(a)      (-EINVAL)
+# define MPX_ENABLE_MANAGEMENT(      (-EINVAL)
 #endif
 #ifndef MPX_DISABLE_MANAGEMENT
-# define MPX_DISABLE_MANAGEMENT(a)     (-EINVAL)
+# define MPX_DISABLE_MANAGEMENT(     (-EINVAL)
 #endif
 #ifndef GET_FP_MODE
 # define GET_FP_MODE(a)                (-EINVAL)
@@ -222,7 +222,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
                                goto out_unlock;        /* No processes for this user */
                }
                do_each_thread(g, p) {
-                       if (uid_eq(task_uid(p), uid))
+                       if (uid_eq(task_uid(p), uid) && task_pid_vnr(p))
                                error = set_one_prio(p, niceval, error);
                } while_each_thread(g, p);
                if (!uid_eq(uid, cred->uid))
@@ -290,7 +290,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
                                goto out_unlock;        /* No processes for this user */
                }
                do_each_thread(g, p) {
-                       if (uid_eq(task_uid(p), uid)) {
+                       if (uid_eq(task_uid(p), uid) && task_pid_vnr(p)) {
                                niceval = nice_to_rlimit(task_nice(p));
                                if (niceval > retval)
                                        retval = niceval;
@@ -1668,8 +1668,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd)
         * overall picture.
         */
        err = -EACCES;
-       if (!S_ISREG(inode->i_mode)     ||
-           exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC)
+       if (!S_ISREG(inode->i_mode) || path_noexec(&exe.file->f_path))
                goto exit;
 
        err = inode_permission(inode, MAY_EXEC);
@@ -1722,7 +1721,6 @@ exit_err:
        goto exit;
 }
 
-#ifdef CONFIG_CHECKPOINT_RESTORE
 /*
  * WARNING: we don't require any capability here so be very careful
  * in what is allowed for modification from userspace.
@@ -1818,6 +1816,7 @@ out:
        return error;
 }
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data_size)
 {
        struct prctl_mm_map prctl_map = { .exe_fd = (u32)-1, };
@@ -1854,11 +1853,13 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
                user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL;
        }
 
-       if (prctl_map.exe_fd != (u32)-1)
+       if (prctl_map.exe_fd != (u32)-1) {
                error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd);
-       down_read(&mm->mmap_sem);
-       if (error)
-               goto out;
+               if (error)
+                       return error;
+       }
+
+       down_write(&mm->mmap_sem);
 
        /*
         * We don't validate if these members are pointing to
@@ -1895,17 +1896,46 @@ static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data
        if (prctl_map.auxv_size)
                memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
 
-       error = 0;
-out:
-       up_read(&mm->mmap_sem);
-       return error;
+       up_write(&mm->mmap_sem);
+       return 0;
 }
 #endif /* CONFIG_CHECKPOINT_RESTORE */
 
+static int prctl_set_auxv(struct mm_struct *mm, unsigned long addr,
+                         unsigned long len)
+{
+       /*
+        * This doesn't move the auxiliary vector itself since it's pinned to
+        * mm_struct, but it permits filling the vector with new values.  It's
+        * up to the caller to provide sane values here, otherwise userspace
+        * tools which use this vector might be unhappy.
+        */
+       unsigned long user_auxv[AT_VECTOR_SIZE];
+
+       if (len > sizeof(user_auxv))
+               return -EINVAL;
+
+       if (copy_from_user(user_auxv, (const void __user *)addr, len))
+               return -EFAULT;
+
+       /* Make sure the last entry is always AT_NULL */
+       user_auxv[AT_VECTOR_SIZE - 2] = 0;
+       user_auxv[AT_VECTOR_SIZE - 1] = 0;
+
+       BUILD_BUG_ON(sizeof(user_auxv) != sizeof(mm->saved_auxv));
+
+       task_lock(current);
+       memcpy(mm->saved_auxv, user_auxv, len);
+       task_unlock(current);
+
+       return 0;
+}
+
 static int prctl_set_mm(int opt, unsigned long addr,
                        unsigned long arg4, unsigned long arg5)
 {
        struct mm_struct *mm = current->mm;
+       struct prctl_mm_map prctl_map;
        struct vm_area_struct *vma;
        int error;
 
@@ -1925,50 +1955,75 @@ static int prctl_set_mm(int opt, unsigned long addr,
        if (opt == PR_SET_MM_EXE_FILE)
                return prctl_set_mm_exe_file(mm, (unsigned int)addr);
 
+       if (opt == PR_SET_MM_AUXV)
+               return prctl_set_auxv(mm, addr, arg4);
+
        if (addr >= TASK_SIZE || addr < mmap_min_addr)
                return -EINVAL;
 
        error = -EINVAL;
 
-       down_read(&mm->mmap_sem);
+       down_write(&mm->mmap_sem);
        vma = find_vma(mm, addr);
 
+       prctl_map.start_code    = mm->start_code;
+       prctl_map.end_code      = mm->end_code;
+       prctl_map.start_data    = mm->start_data;
+       prctl_map.end_data      = mm->end_data;
+       prctl_map.start_brk     = mm->start_brk;
+       prctl_map.brk           = mm->brk;
+       prctl_map.start_stack   = mm->start_stack;
+       prctl_map.arg_start     = mm->arg_start;
+       prctl_map.arg_end       = mm->arg_end;
+       prctl_map.env_start     = mm->env_start;
+       prctl_map.env_end       = mm->env_end;
+       prctl_map.auxv          = NULL;
+       prctl_map.auxv_size     = 0;
+       prctl_map.exe_fd        = -1;
+
        switch (opt) {
        case PR_SET_MM_START_CODE:
-               mm->start_code = addr;
+               prctl_map.start_code = addr;
                break;
        case PR_SET_MM_END_CODE:
-               mm->end_code = addr;
+               prctl_map.end_code = addr;
                break;
        case PR_SET_MM_START_DATA:
-               mm->start_data = addr;
+               prctl_map.start_data = addr;
                break;
        case PR_SET_MM_END_DATA:
-               mm->end_data = addr;
+               prctl_map.end_data = addr;
+               break;
+       case PR_SET_MM_START_STACK:
+               prctl_map.start_stack = addr;
                break;
-
        case PR_SET_MM_START_BRK:
-               if (addr <= mm->end_data)
-                       goto out;
-
-               if (check_data_rlimit(rlimit(RLIMIT_DATA), mm->brk, addr,
-                                     mm->end_data, mm->start_data))
-                       goto out;
-
-               mm->start_brk = addr;
+               prctl_map.start_brk = addr;
                break;
-
        case PR_SET_MM_BRK:
-               if (addr <= mm->end_data)
-                       goto out;
-
-               if (check_data_rlimit(rlimit(RLIMIT_DATA), addr, mm->start_brk,
-                                     mm->end_data, mm->start_data))
-                       goto out;
-
-               mm->brk = addr;
+               prctl_map.brk = addr;
                break;
+       case PR_SET_MM_ARG_START:
+               prctl_map.arg_start = addr;
+               break;
+       case PR_SET_MM_ARG_END:
+               prctl_map.arg_end = addr;
+               break;
+       case PR_SET_MM_ENV_START:
+               prctl_map.env_start = addr;
+               break;
+       case PR_SET_MM_ENV_END:
+               prctl_map.env_end = addr;
+               break;
+       default:
+               goto out;
+       }
+
+       error = validate_prctl_map(&prctl_map);
+       if (error)
+               goto out;
 
+       switch (opt) {
        /*
         * If command line arguments and environment
         * are placed somewhere else on stack, we can
@@ -1985,55 +2040,23 @@ static int prctl_set_mm(int opt, unsigned long addr,
                        error = -EFAULT;
                        goto out;
                }
-               if (opt == PR_SET_MM_START_STACK)
-                       mm->start_stack = addr;
-               else if (opt == PR_SET_MM_ARG_START)
-                       mm->arg_start = addr;
-               else if (opt == PR_SET_MM_ARG_END)
-                       mm->arg_end = addr;
-               else if (opt == PR_SET_MM_ENV_START)
-                       mm->env_start = addr;
-               else if (opt == PR_SET_MM_ENV_END)
-                       mm->env_end = addr;
-               break;
-
-       /*
-        * This doesn't move auxiliary vector itself
-        * since it's pinned to mm_struct, but allow
-        * to fill vector with new values. It's up
-        * to a caller to provide sane values here
-        * otherwise user space tools which use this
-        * vector might be unhappy.
-        */
-       case PR_SET_MM_AUXV: {
-               unsigned long user_auxv[AT_VECTOR_SIZE];
-
-               if (arg4 > sizeof(user_auxv))
-                       goto out;
-               up_read(&mm->mmap_sem);
-
-               if (copy_from_user(user_auxv, (const void __user *)addr, arg4))
-                       return -EFAULT;
-
-               /* Make sure the last entry is always AT_NULL */
-               user_auxv[AT_VECTOR_SIZE - 2] = 0;
-               user_auxv[AT_VECTOR_SIZE - 1] = 0;
-
-               BUILD_BUG_ON(sizeof(user_auxv) != sizeof(mm->saved_auxv));
-
-               task_lock(current);
-               memcpy(mm->saved_auxv, user_auxv, arg4);
-               task_unlock(current);
-
-               return 0;
-       }
-       default:
-               goto out;
        }
 
+       mm->start_code  = prctl_map.start_code;
+       mm->end_code    = prctl_map.end_code;
+       mm->start_data  = prctl_map.start_data;
+       mm->end_data    = prctl_map.end_data;
+       mm->start_brk   = prctl_map.start_brk;
+       mm->brk         = prctl_map.brk;
+       mm->start_stack = prctl_map.start_stack;
+       mm->arg_start   = prctl_map.arg_start;
+       mm->arg_end     = prctl_map.arg_end;
+       mm->env_start   = prctl_map.env_start;
+       mm->env_end     = prctl_map.env_end;
+
        error = 0;
 out:
-       up_read(&mm->mmap_sem);
+       up_write(&mm->mmap_sem);
        return error;
 }
 
@@ -2230,12 +2253,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
        case PR_MPX_ENABLE_MANAGEMENT:
                if (arg2 || arg3 || arg4 || arg5)
                        return -EINVAL;
-               error = MPX_ENABLE_MANAGEMENT(me);
+               error = MPX_ENABLE_MANAGEMENT();
                break;
        case PR_MPX_DISABLE_MANAGEMENT:
                if (arg2 || arg3 || arg4 || arg5)
                        return -EINVAL;
-               error = MPX_DISABLE_MANAGEMENT(me);
+               error = MPX_DISABLE_MANAGEMENT();
                break;
        case PR_SET_FP_MODE:
                error = SET_FP_MODE(me, arg2);