mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
ucounts: Enforce RLIMIT_NPROC not RLIMIT_NPROC+1
Michal Koutný <mkoutny@suse.com> wrote: > It was reported that v5.14 behaves differently when enforcing > RLIMIT_NPROC limit, namely, it allows one more task than previously. > This is consequence of the commit21d1c5e386
("Reimplement > RLIMIT_NPROC on top of ucounts") that missed the sharpness of > equality in the forking path. This can be fixed either by fixing the test or by moving the increment to be before the test. Fix it my moving copy_creds which contains the increment before is_ucounts_overlimit. In the case of CLONE_NEWUSER the ucounts in the task_cred changes. The function is_ucounts_overlimit needs to use the final version of the ucounts for the new process. Which means moving the is_ucounts_overlimit test after copy_creds is necessary. Both the test in fork and the test in set_user were semantically changed when the code moved to ucounts. The change of the test in fork was bad because it was before the increment. The test in set_user was wrong and the change to ucounts fixed it. So this fix only restores the old behavior in one lcation not two. Link: https://lkml.kernel.org/r/20220204181144.24462-1-mkoutny@suse.com Link: https://lkml.kernel.org/r/20220216155832.680775-2-ebiederm@xmission.com Cc: stable@vger.kernel.org Reported-by: Michal Koutný <mkoutny@suse.com> Reviewed-by: Michal Koutný <mkoutny@suse.com> Fixes:21d1c5e386
("Reimplement RLIMIT_NPROC on top of ucounts") Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
parent
c16bdeb5a3
commit
8f2f9c4d82
@ -2021,18 +2021,18 @@ static __latent_entropy struct task_struct *copy_process(
|
|||||||
#ifdef CONFIG_PROVE_LOCKING
|
#ifdef CONFIG_PROVE_LOCKING
|
||||||
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
|
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
|
||||||
#endif
|
#endif
|
||||||
|
retval = copy_creds(p, clone_flags);
|
||||||
|
if (retval < 0)
|
||||||
|
goto bad_fork_free;
|
||||||
|
|
||||||
retval = -EAGAIN;
|
retval = -EAGAIN;
|
||||||
if (is_ucounts_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
|
if (is_ucounts_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
|
||||||
if (p->real_cred->user != INIT_USER &&
|
if (p->real_cred->user != INIT_USER &&
|
||||||
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
|
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
|
||||||
goto bad_fork_free;
|
goto bad_fork_cleanup_count;
|
||||||
}
|
}
|
||||||
current->flags &= ~PF_NPROC_EXCEEDED;
|
current->flags &= ~PF_NPROC_EXCEEDED;
|
||||||
|
|
||||||
retval = copy_creds(p, clone_flags);
|
|
||||||
if (retval < 0)
|
|
||||||
goto bad_fork_free;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If multiple threads are within copy_process(), then this check
|
* If multiple threads are within copy_process(), then this check
|
||||||
* triggers too late. This doesn't hurt, the check is only there
|
* triggers too late. This doesn't hurt, the check is only there
|
||||||
|
Loading…
Reference in New Issue
Block a user