noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
					      struct clone_args __user *uargs,
					      size_t size)
{
	struct clone_args args;

	if (unlikely(size > PAGE_SIZE))
		return -E2BIG;

	if (unlikely(size < sizeof(struct clone_args)))
		return -EINVAL;

	if (unlikely(!access_ok(uargs, size)))
		return -EFAULT;

	if (size > sizeof(struct clone_args)) {
		unsigned char __user *addr;
		unsigned char __user *end;
		unsigned char val;

		addr = (void __user *)uargs + sizeof(struct clone_args);
		end = (void __user *)uargs + size;

		for (; addr < end; addr++) {
			if (get_user(val, addr))
				return -EFAULT;
			if (val)
				return -E2BIG;
		}

		size = sizeof(struct clone_args);
	}

	if (copy_from_user(&args, uargs, size))
		return -EFAULT;

	*kargs = (struct kernel_clone_args){
		.flags		= args.flags,
		.pidfd		= u64_to_user_ptr(args.pidfd),
		.child_tid	= u64_to_user_ptr(args.child_tid),
		.parent_tid	= u64_to_user_ptr(args.parent_tid),
		.exit_signal	= args.exit_signal,
		.stack		= args.stack,
		.stack_size	= args.stack_size,
		.tls		= args.tls,
	};

	return 0;
}
noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
					      struct clone_args __user *uargs,
					      size_t size)
{
	struct clone_args args;

	if (unlikely(size > PAGE_SIZE))
		return -E2BIG;

	if (unlikely(size < sizeof(struct clone_args)))
		return -EINVAL;

	if (unlikely(!access_ok(uargs, size)))
		return -EFAULT;

	if (size > sizeof(struct clone_args)) {
		unsigned char __user *addr;
		unsigned char __user *end;
		unsigned char val;

		addr = (void __user *)uargs + sizeof(struct clone_args);
		end = (void __user *)uargs + size;

		for (; addr < end; addr++) {
			if (get_user(val, addr))
				return -EFAULT;
			if (val)
				return -E2BIG;
		}

		size = sizeof(struct clone_args);
	}

	if (copy_from_user(&args, uargs, size))
		return -EFAULT;

	*kargs = (struct kernel_clone_args){
		.flags		= args.flags,
		.pidfd		= u64_to_user_ptr(args.pidfd),
		.child_tid	= u64_to_user_ptr(args.child_tid),
		.parent_tid	= u64_to_user_ptr(args.parent_tid),
		.exit_signal	= args.exit_signal,
		.stack		= args.stack,
		.stack_size	= args.stack_size,
		.tls		= args.tls,
	};

	return 0;
}