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 <arnd@xxxxxxxx> --- 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