aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAleksa Sarai <cyphar@cyphar.com>2019-09-30 21:10:53 -0400
committerChristian Brauner <christian.brauner@ubuntu.com>2019-10-01 09:45:10 -0400
commitf14c234b4bc5184fd40d9a47830e5b32c3b36d49 (patch)
tree03dd3b1cb5035fa6cec8389cf10ea30ddd1ec3e3 /kernel
parentf5a1a536fa14895ccff4e94e6a5af90901ce86aa (diff)
clone3: switch to copy_struct_from_user()
Switch clone3() syscall from it's own copying struct clone_args from userspace to the new dedicated copy_struct_from_user() helper. The change is very straightforward, and helps unify the syscall interface for struct-from-userspace syscalls. Additionally, explicitly define CLONE_ARGS_SIZE_VER0 to match the other users of the struct-extension pattern. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Reviewed-by: Kees Cook <keescook@chromium.org> Reviewed-by: Christian Brauner <christian.brauner@ubuntu.com> [christian.brauner@ubuntu.com: improve commit message] Link: https://lore.kernel.org/r/20191001011055.19283-3-cyphar@cyphar.com Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fork.c34
1 files changed, 7 insertions, 27 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index f9572f416126..2ef529869c64 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2525,39 +2525,19 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
2525#ifdef __ARCH_WANT_SYS_CLONE3 2525#ifdef __ARCH_WANT_SYS_CLONE3
2526noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, 2526noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
2527 struct clone_args __user *uargs, 2527 struct clone_args __user *uargs,
2528 size_t size) 2528 size_t usize)
2529{ 2529{
2530 int err;
2530 struct clone_args args; 2531 struct clone_args args;
2531 2532
2532 if (unlikely(size > PAGE_SIZE)) 2533 if (unlikely(usize > PAGE_SIZE))
2533 return -E2BIG; 2534 return -E2BIG;
2534 2535 if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
2535 if (unlikely(size < sizeof(struct clone_args)))
2536 return -EINVAL; 2536 return -EINVAL;
2537 2537
2538 if (unlikely(!access_ok(uargs, size))) 2538 err = copy_struct_from_user(&args, sizeof(args), uargs, usize);
2539 return -EFAULT; 2539 if (err)
2540 2540 return err;
2541 if (size > sizeof(struct clone_args)) {
2542 unsigned char __user *addr;
2543 unsigned char __user *end;
2544 unsigned char val;
2545
2546 addr = (void __user *)uargs + sizeof(struct clone_args);
2547 end = (void __user *)uargs + size;
2548
2549 for (; addr < end; addr++) {
2550 if (get_user(val, addr))
2551 return -EFAULT;
2552 if (val)
2553 return -E2BIG;
2554 }
2555
2556 size = sizeof(struct clone_args);
2557 }
2558
2559 if (copy_from_user(&args, uargs, size))
2560 return -EFAULT;
2561 2541
2562 /* 2542 /*
2563 * Verify that higher 32bits of exit_signal are unset and that 2543 * Verify that higher 32bits of exit_signal are unset and that