kernel/sys.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/kernel/sys.c b/kernel/sys.c index e7006eb6c1e4..ab9f266933af 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -642,11 +642,19 @@ static int set_user(struct cred *new) * for programs doing set*uid()+execve() by harmlessly deferring the * failure to the execve() stage. */ - if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) && - new_user != INIT_USER) - current->flags |= PF_NPROC_EXCEEDED; - else - current->flags &= ~PF_NPROC_EXCEEDED; + if (new_user != INIT_USER) { + int processes = atomic_read(&new_user->processes); + + /* Hard limit: fail it */ + if (processes >= rlimit_max(RLIMIT_NPROC)) { + free_uid(new_user); + return -EAGAIN; + } + + /* Soft limit: fail the next exec */ + if (processes >= rlimit(RLIMIT_NPROC)) + current->flags |= PF_NPROC_EXCEEDED; + } free_uid(new->user); new->user = new_user;