diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 33 | 
1 files changed, 32 insertions, 1 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index bcdf53125210..55af6931c6ec 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2561,7 +2561,35 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,  	return 0;  } -static bool clone3_args_valid(const struct kernel_clone_args *kargs) +/** + * clone3_stack_valid - check and prepare stack + * @kargs: kernel clone args + * + * Verify that the stack arguments userspace gave us are sane. + * In addition, set the stack direction for userspace since it's easy for us to + * determine. + */ +static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) +{ +	if (kargs->stack == 0) { +		if (kargs->stack_size > 0) +			return false; +	} else { +		if (kargs->stack_size == 0) +			return false; + +		if (!access_ok((void __user *)kargs->stack, kargs->stack_size)) +			return false; + +#if !defined(CONFIG_STACK_GROWSUP) && !defined(CONFIG_IA64) +		kargs->stack += kargs->stack_size; +#endif +	} + +	return true; +} + +static bool clone3_args_valid(struct kernel_clone_args *kargs)  {  	/*  	 * All lower bits of the flag word are taken. @@ -2581,6 +2609,9 @@ static bool clone3_args_valid(const struct kernel_clone_args *kargs)  	    kargs->exit_signal)  		return false; +	if (!clone3_stack_valid(kargs)) +		return false; +  	return true;  }  |