Skip to content

Commit f14c234

Browse files
cypharChristian Brauner
authored andcommitted
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 <[email protected]> Reviewed-by: Kees Cook <[email protected]> Reviewed-by: Christian Brauner <[email protected]> [[email protected]: improve commit message] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent f5a1a53 commit f14c234

File tree

2 files changed

+9
-27
lines changed

2 files changed

+9
-27
lines changed

include/uapi/linux/sched.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ struct clone_args {
4747
__aligned_u64 tls;
4848
};
4949

50+
#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
51+
5052
/*
5153
* Scheduling policies
5254
*/

kernel/fork.c

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2525,39 +2525,19 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
25252525
#ifdef __ARCH_WANT_SYS_CLONE3
25262526
noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
25272527
struct clone_args __user *uargs,
2528-
size_t size)
2528+
size_t usize)
25292529
{
2530+
int err;
25302531
struct clone_args args;
25312532

2532-
if (unlikely(size > PAGE_SIZE))
2533+
if (unlikely(usize > PAGE_SIZE))
25332534
return -E2BIG;
2534-
2535-
if (unlikely(size < sizeof(struct clone_args)))
2535+
if (unlikely(usize < CLONE_ARGS_SIZE_VER0))
25362536
return -EINVAL;
25372537

2538-
if (unlikely(!access_ok(uargs, size)))
2539-
return -EFAULT;
2540-
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;
2538+
err = copy_struct_from_user(&args, sizeof(args), uargs, usize);
2539+
if (err)
2540+
return err;
25612541

25622542
/*
25632543
* Verify that higher 32bits of exit_signal are unset and that

0 commit comments

Comments
 (0)