diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 20 | 
1 files changed, 14 insertions, 6 deletions
| diff --git a/kernel/sys.c b/kernel/sys.c index ecc4cf019242..97dc9e5d6bf9 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -472,6 +472,16 @@ static int set_user(struct cred *new)  	if (!new_user)  		return -EAGAIN; +	free_uid(new->user); +	new->user = new_user; +	return 0; +} + +static void flag_nproc_exceeded(struct cred *new) +{ +	if (new->ucounts == current_ucounts()) +		return; +  	/*  	 * We don't fail in case of NPROC limit excess here because too many  	 * poorly written programs don't check set*uid() return code, assuming @@ -480,15 +490,10 @@ static int set_user(struct cred *new)  	 * failure to the execve() stage.  	 */  	if (is_ucounts_overlimit(new->ucounts, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)) && -			new_user != INIT_USER && -			!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) +			new->user != INIT_USER)  		current->flags |= PF_NPROC_EXCEEDED;  	else  		current->flags &= ~PF_NPROC_EXCEEDED; - -	free_uid(new->user); -	new->user = new_user; -	return 0;  }  /* @@ -563,6 +568,7 @@ long __sys_setreuid(uid_t ruid, uid_t euid)  	if (retval < 0)  		goto error; +	flag_nproc_exceeded(new);  	return commit_creds(new);  error: @@ -625,6 +631,7 @@ long __sys_setuid(uid_t uid)  	if (retval < 0)  		goto error; +	flag_nproc_exceeded(new);  	return commit_creds(new);  error: @@ -704,6 +711,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)  	if (retval < 0)  		goto error; +	flag_nproc_exceeded(new);  	return commit_creds(new);  error: |