diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 35 | 
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 5fd54bf0e886..495cd87d9bf4 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1442,6 +1442,8 @@ static int do_prlimit(struct task_struct *tsk, unsigned int resource,  	if (resource >= RLIM_NLIMITS)  		return -EINVAL; +	resource = array_index_nospec(resource, RLIM_NLIMITS); +  	if (new_rlim) {  		if (new_rlim->rlim_cur > new_rlim->rlim_max)  			return -EINVAL; @@ -2348,6 +2350,33 @@ static int prctl_set_vma(unsigned long opt, unsigned long start,  }  #endif /* CONFIG_ANON_VMA_NAME */ +static inline int prctl_set_mdwe(unsigned long bits, unsigned long arg3, +				 unsigned long arg4, unsigned long arg5) +{ +	if (arg3 || arg4 || arg5) +		return -EINVAL; + +	if (bits & ~(PR_MDWE_REFUSE_EXEC_GAIN)) +		return -EINVAL; + +	if (bits & PR_MDWE_REFUSE_EXEC_GAIN) +		set_bit(MMF_HAS_MDWE, ¤t->mm->flags); +	else if (test_bit(MMF_HAS_MDWE, ¤t->mm->flags)) +		return -EPERM; /* Cannot unset the flag */ + +	return 0; +} + +static inline int prctl_get_mdwe(unsigned long arg2, unsigned long arg3, +				 unsigned long arg4, unsigned long arg5) +{ +	if (arg2 || arg3 || arg4 || arg5) +		return -EINVAL; + +	return test_bit(MMF_HAS_MDWE, ¤t->mm->flags) ? +		PR_MDWE_REFUSE_EXEC_GAIN : 0; +} +  SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,  		unsigned long, arg4, unsigned long, arg5)  { @@ -2623,6 +2652,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,  		error = sched_core_share_pid(arg2, arg3, arg4, arg5);  		break;  #endif +	case PR_SET_MDWE: +		error = prctl_set_mdwe(arg2, arg3, arg4, arg5); +		break; +	case PR_GET_MDWE: +		error = prctl_get_mdwe(arg2, arg3, arg4, arg5); +		break;  	case PR_SET_VMA:  		error = prctl_set_vma(arg2, arg3, arg4, arg5);  		break;  |