Once we make it to accept struct prctl_mm_map as an argument it will
be possible to reuse this functionallity for the rest of PR_SET_MM_x
operations. Here we simply allocate struct prctl_mm_map in a caller
and provide it downstairs.

CC: Jonathan de Boyne Pollard <[email protected]>
CC: Andrey Vagin <[email protected]>
CC: Andrew Morton <[email protected]>
CC: Michael Kerrisk <[email protected]>
CC: Yang Shi <[email protected]>
CC: Michal Hocko <[email protected]>
Signed-off-by: Cyrill Gorcunov <[email protected]>
---
 kernel/sys.c |   59 +++++++++++++++++++++++++++++++----------------------------
 1 file changed, 31 insertions(+), 28 deletions(-)

Index: linux-ml.git/kernel/sys.c
===================================================================
--- linux-ml.git.orig/kernel/sys.c
+++ linux-ml.git/kernel/sys.c
@@ -1969,9 +1969,8 @@ exit_err:
        goto exit;
 }
 
-static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long 
data_size)
+static int prctl_set_mm_map(struct prctl_mm_map *prctl_map)
 {
-       struct prctl_mm_map prctl_map = { .exe_fd = (u32)-1, };
        unsigned long user_auxv[AT_VECTOR_SIZE];
        struct mm_struct *mm = current->mm;
        int error;
@@ -1979,21 +1978,15 @@ static int prctl_set_mm_map(int opt, con
        BUILD_BUG_ON(sizeof(user_auxv) != sizeof(mm->saved_auxv));
        BUILD_BUG_ON(sizeof(struct prctl_mm_map) > 256);
 
-       if (data_size != sizeof(prctl_map))
-               return -EINVAL;
-
-       if (copy_from_user(&prctl_map, addr, sizeof(prctl_map)))
-               return -EFAULT;
-
-       error = validate_prctl_map(&prctl_map);
+       error = validate_prctl_map(prctl_map);
        if (error)
                return error;
 
-       if (prctl_map.auxv_size) {
+       if (prctl_map->auxv_size) {
                memset(user_auxv, 0, sizeof(user_auxv));
                if (copy_from_user(user_auxv,
-                                  (const void __user *)prctl_map.auxv,
-                                  prctl_map.auxv_size))
+                                  (const void __user *)prctl_map->auxv,
+                                  prctl_map->auxv_size))
                        return -EFAULT;
 
                /* Last entry must be AT_NULL as specification requires */
@@ -2001,8 +1994,8 @@ static int prctl_set_mm_map(int opt, con
                user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL;
        }
 
-       if (prctl_map.exe_fd != (u32)-1) {
-               error = prctl_set_mm_exe_file(mm, prctl_map.exe_fd);
+       if (prctl_map->exe_fd != (u32)-1) {
+               error = prctl_set_mm_exe_file(mm, prctl_map->exe_fd);
                if (error)
                        return error;
        }
@@ -2026,17 +2019,17 @@ static int prctl_set_mm_map(int opt, con
         */
 
        spin_lock(&mm->arg_lock);
-       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;
+       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;
        spin_unlock(&mm->arg_lock);
 
        /*
@@ -2047,7 +2040,7 @@ static int prctl_set_mm_map(int opt, con
         * not introduce additional locks here making the kernel
         * more complex.
         */
-       if (prctl_map.auxv_size)
+       if (prctl_map->auxv_size)
                memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv));
 
        up_read(&mm->mmap_sem);
@@ -2063,8 +2056,18 @@ static int prctl_set_mm(int opt, unsigne
                return put_user((unsigned int)sizeof(struct prctl_mm_map),
                                (unsigned int __user *)addr);
 
-       if (opt == PR_SET_MM_MAP)
-               return prctl_set_mm_map(opt, (const void __user *)addr, arg4);
+       if (opt == PR_SET_MM_MAP) {
+               struct prctl_mm_map prctl_map = { .exe_fd = (u32)-1, };
+
+               if (arg4 != sizeof(prctl_map))
+                       return -EINVAL;
+
+               if (copy_from_user(&prctl_map, (const void __user *)addr,
+                                  sizeof(prctl_map)))
+                       return -EFAULT;
+
+               return prctl_set_mm_map(&prctl_map);
+       }
 #endif
 
        pr_warn_once("PR_SET_MM_* has been removed. Use PR_SET_MM_MAP 
instead\n");

Reply via email to