The compat version of sys_kexec_load() uses compat_alloc_user_space to
convert the user-provided arguments into the native format.

Move the conversion into the regular implementation with
an in_compat_syscall() check to simplify it and avoid the
compat_alloc_user_space() call.

Signed-off-by: Arnd Bergmann <a...@arndb.de>
---
 arch/arm64/include/asm/unistd32.h         |  2 +-
 arch/mips/kernel/syscalls/syscall_n32.tbl |  2 +-
 arch/mips/kernel/syscalls/syscall_o32.tbl |  2 +-
 arch/parisc/kernel/syscalls/syscall.tbl   |  2 +-
 arch/powerpc/kernel/syscalls/syscall.tbl  |  2 +-
 arch/s390/kernel/syscalls/syscall.tbl     |  2 +-
 arch/sparc/kernel/syscalls/syscall.tbl    |  2 +-
 arch/x86/entry/syscalls/syscall_32.tbl    |  2 +-
 arch/x86/entry/syscalls/syscall_64.tbl    |  2 +-
 include/linux/compat.h                    |  6 --
 include/uapi/asm-generic/unistd.h         |  2 +-
 kernel/kexec.c                            | 75 ++++++-----------------
 12 files changed, 29 insertions(+), 72 deletions(-)

diff --git a/arch/arm64/include/asm/unistd32.h 
b/arch/arm64/include/asm/unistd32.h
index 734860ac7cf9..b6517df74037 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -705,7 +705,7 @@ __SYSCALL(__NR_getcpu, sys_getcpu)
 #define __NR_epoll_pwait 346
 __SYSCALL(__NR_epoll_pwait, compat_sys_epoll_pwait)
 #define __NR_kexec_load 347
-__SYSCALL(__NR_kexec_load, compat_sys_kexec_load)
+__SYSCALL(__NR_kexec_load, sys_kexec_load)
 #define __NR_utimensat 348
 __SYSCALL(__NR_utimensat, sys_utimensat_time32)
 #define __NR_signalfd 349
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl 
b/arch/mips/kernel/syscalls/syscall_n32.tbl
index f9df9edb67a4..ad157aab4c09 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -282,7 +282,7 @@
 271    n32     move_pages                      compat_sys_move_pages
 272    n32     set_robust_list                 compat_sys_set_robust_list
 273    n32     get_robust_list                 compat_sys_get_robust_list
-274    n32     kexec_load                      compat_sys_kexec_load
+274    n32     kexec_load                      sys_kexec_load
 275    n32     getcpu                          sys_getcpu
 276    n32     epoll_pwait                     compat_sys_epoll_pwait
 277    n32     ioprio_set                      sys_ioprio_set
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl 
b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 195b43cf27c8..57baf6c8008f 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -322,7 +322,7 @@
 308    o32     move_pages                      sys_move_pages                  
compat_sys_move_pages
 309    o32     set_robust_list                 sys_set_robust_list             
compat_sys_set_robust_list
 310    o32     get_robust_list                 sys_get_robust_list             
compat_sys_get_robust_list
-311    o32     kexec_load                      sys_kexec_load                  
compat_sys_kexec_load
+311    o32     kexec_load                      sys_kexec_load
 312    o32     getcpu                          sys_getcpu
 313    o32     epoll_pwait                     sys_epoll_pwait                 
compat_sys_epoll_pwait
 314    o32     ioprio_set                      sys_ioprio_set
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl 
b/arch/parisc/kernel/syscalls/syscall.tbl
index def64d221cd4..778bf166d7bd 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -336,7 +336,7 @@
 297    common  epoll_pwait             sys_epoll_pwait                 
compat_sys_epoll_pwait
 298    common  statfs64                sys_statfs64                    
compat_sys_statfs64
 299    common  fstatfs64               sys_fstatfs64                   
compat_sys_fstatfs64
-300    common  kexec_load              sys_kexec_load                  
compat_sys_kexec_load
+300    common  kexec_load              sys_kexec_load
 301    32      utimensat               sys_utimensat_time32
 301    64      utimensat               sys_utimensat
 302    common  signalfd                sys_signalfd                    
compat_sys_signalfd
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl 
b/arch/powerpc/kernel/syscalls/syscall.tbl
index c2d737ff2e7b..f128ba8b9a71 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -350,7 +350,7 @@
 265    64      mq_timedreceive                 sys_mq_timedreceive
 266    nospu   mq_notify                       sys_mq_notify                   
compat_sys_mq_notify
 267    nospu   mq_getsetattr                   sys_mq_getsetattr               
compat_sys_mq_getsetattr
-268    nospu   kexec_load                      sys_kexec_load                  
compat_sys_kexec_load
+268    nospu   kexec_load                      sys_kexec_load
 269    nospu   add_key                         sys_add_key
 270    nospu   request_key                     sys_request_key
 271    nospu   keyctl                          sys_keyctl                      
compat_sys_keyctl
diff --git a/arch/s390/kernel/syscalls/syscall.tbl 
b/arch/s390/kernel/syscalls/syscall.tbl
index 10456bc936fb..d45952058be2 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -283,7 +283,7 @@
 274  common    mq_timedreceive         sys_mq_timedreceive             
sys_mq_timedreceive_time32
 275  common    mq_notify               sys_mq_notify                   
compat_sys_mq_notify
 276  common    mq_getsetattr           sys_mq_getsetattr               
compat_sys_mq_getsetattr
-277  common    kexec_load              sys_kexec_load                  
compat_sys_kexec_load
+277  common    kexec_load              sys_kexec_load                  
sys_kexec_load
 278  common    add_key                 sys_add_key                     
sys_add_key
 279  common    request_key             sys_request_key                 
sys_request_key
 280  common    keyctl                  sys_keyctl                      
compat_sys_keyctl
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl 
b/arch/sparc/kernel/syscalls/syscall.tbl
index 4af114e84f20..a46edcdd950d 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -369,7 +369,7 @@
 303    common  mbind                   sys_mbind                       
compat_sys_mbind
 304    common  get_mempolicy           sys_get_mempolicy               
compat_sys_get_mempolicy
 305    common  set_mempolicy           sys_set_mempolicy               
compat_sys_set_mempolicy
-306    common  kexec_load              sys_kexec_load                  
compat_sys_kexec_load
+306    common  kexec_load              sys_kexec_load                  
sys_kexec_load
 307    common  move_pages              sys_move_pages                  
compat_sys_move_pages
 308    common  getcpu                  sys_getcpu
 309    common  epoll_pwait             sys_epoll_pwait                 
compat_sys_epoll_pwait
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl 
b/arch/x86/entry/syscalls/syscall_32.tbl
index 3db3d8823dc8..7e4140b78aad 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -294,7 +294,7 @@
 280    i386    mq_timedreceive         sys_mq_timedreceive_time32
 281    i386    mq_notify               sys_mq_notify                   
compat_sys_mq_notify
 282    i386    mq_getsetattr           sys_mq_getsetattr               
compat_sys_mq_getsetattr
-283    i386    kexec_load              sys_kexec_load                  
compat_sys_kexec_load
+283    i386    kexec_load              sys_kexec_load                  
sys_kexec_load
 284    i386    waitid                  sys_waitid                      
compat_sys_waitid
 # 285 sys_setaltroot
 286    i386    add_key                 sys_add_key
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl 
b/arch/x86/entry/syscalls/syscall_64.tbl
index f30d6ae9a688..9986f5f08278 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -384,7 +384,7 @@
 525    x32     sigaltstack             compat_sys_sigaltstack
 526    x32     timer_create            compat_sys_timer_create
 527    x32     mq_notify               compat_sys_mq_notify
-528    x32     kexec_load              compat_sys_kexec_load
+528    x32     kexec_load              sys_kexec_load
 529    x32     waitid                  compat_sys_waitid
 530    x32     set_robust_list         compat_sys_set_robust_list
 531    x32     get_robust_list         compat_sys_get_robust_list
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 3d96a841bd49..a7a5a0ff59ef 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -643,12 +643,6 @@ asmlinkage long compat_sys_setitimer(int which,
                                     struct old_itimerval32 __user *in,
                                     struct old_itimerval32 __user *out);
 
-/* kernel/kexec.c */
-asmlinkage long compat_sys_kexec_load(compat_ulong_t entry,
-                                     compat_ulong_t nr_segments,
-                                     struct compat_kexec_segment __user *,
-                                     compat_ulong_t flags);
-
 /* kernel/posix-timers.c */
 asmlinkage long compat_sys_timer_create(clockid_t which_clock,
                        struct compat_sigevent __user *timer_event_spec,
diff --git a/include/uapi/asm-generic/unistd.h 
b/include/uapi/asm-generic/unistd.h
index 995b36c2ea7d..83f1fc7fd3d7 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -342,7 +342,7 @@ __SC_COMP(__NR_setitimer, sys_setitimer, 
compat_sys_setitimer)
 
 /* kernel/kexec.c */
 #define __NR_kexec_load 104
-__SC_COMP(__NR_kexec_load, sys_kexec_load, compat_sys_kexec_load)
+__SYSCALL(__NR_kexec_load, sys_kexec_load)
 
 /* kernel/module.c */
 #define __NR_init_module 105
diff --git a/kernel/kexec.c b/kernel/kexec.c
index f977786fe498..1ef7d3dc906f 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -29,7 +29,25 @@ static int copy_user_segment_list(struct kimage *image,
        /* Read in the segments */
        image->nr_segments = nr_segments;
        segment_bytes = nr_segments * sizeof(*segments);
-       ret = copy_from_user(image->segment, segments, segment_bytes);
+       if (in_compat_syscall()) {
+               struct compat_kexec_segment __user *cs = (void __user 
*)segments;
+               struct compat_kexec_segment segment;
+               int i;
+               for (i=0; i< nr_segments; i++) {
+                       copy_from_user(&segment, &cs[i], sizeof(segment));
+                       if (ret)
+                               break;
+
+                       image->segment[i] = (struct kexec_segment) {
+                               .buf   = compat_ptr(segment.buf),
+                               .bufsz = segment.bufsz,
+                               .mem   = segment.mem,
+                               .memsz = segment.memsz,
+                       };
+               }
+       } else {
+               ret = copy_from_user(image->segment, segments, segment_bytes);
+       }
        if (ret)
                ret = -EFAULT;
 
@@ -264,58 +282,3 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned 
long, nr_segments,
 
        return result;
 }
-
-#ifdef CONFIG_COMPAT
-COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
-                      compat_ulong_t, nr_segments,
-                      struct compat_kexec_segment __user *, segments,
-                      compat_ulong_t, flags)
-{
-       struct compat_kexec_segment in;
-       struct kexec_segment out, __user *ksegments;
-       unsigned long i, result;
-
-       result = kexec_load_check(nr_segments, flags);
-       if (result)
-               return result;
-
-       /* Don't allow clients that don't understand the native
-        * architecture to do anything.
-        */
-       if ((flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_DEFAULT)
-               return -EINVAL;
-
-       ksegments = compat_alloc_user_space(nr_segments * sizeof(out));
-       for (i = 0; i < nr_segments; i++) {
-               result = copy_from_user(&in, &segments[i], sizeof(in));
-               if (result)
-                       return -EFAULT;
-
-               out.buf   = compat_ptr(in.buf);
-               out.bufsz = in.bufsz;
-               out.mem   = in.mem;
-               out.memsz = in.memsz;
-
-               result = copy_to_user(&ksegments[i], &out, sizeof(out));
-               if (result)
-                       return -EFAULT;
-       }
-
-       /* Because we write directly to the reserved memory
-        * region when loading crash kernels we need a mutex here to
-        * prevent multiple crash  kernels from attempting to load
-        * simultaneously, and to prevent a crash kernel from loading
-        * over the top of a in use crash kernel.
-        *
-        * KISS: always take the mutex.
-        */
-       if (!mutex_trylock(&kexec_mutex))
-               return -EBUSY;
-
-       result = do_kexec_load(entry, nr_segments, ksegments, flags);
-
-       mutex_unlock(&kexec_mutex);
-
-       return result;
-}
-#endif
-- 
2.27.0

Reply via email to