Skip to content

Commit

Permalink
ucounts: Enforce RLIMIT_NPROC not RLIMIT_NPROC+1
Browse files Browse the repository at this point in the history
Michal Koutný <[email protected]> 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 commit 21d1c5e ("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/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Cc: [email protected]
Reported-by: Michal Koutný <[email protected]>
Reviewed-by: Michal Koutný <[email protected]>
Fixes: 21d1c5e ("Reimplement RLIMIT_NPROC on top of ucounts")
Signed-off-by: "Eric W. Biederman" <[email protected]>
  • Loading branch information
ebiederm committed Feb 17, 2022
1 parent c16bdeb commit 8f2f9c4
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -2021,18 +2021,18 @@ static __latent_entropy struct task_struct *copy_process(
#ifdef CONFIG_PROVE_LOCKING
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
retval = copy_creds(p, clone_flags);
if (retval < 0)
goto bad_fork_free;

retval = -EAGAIN;
if (is_ucounts_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
if (p->real_cred->user != INIT_USER &&
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
goto bad_fork_free;
goto bad_fork_cleanup_count;
}
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
* triggers too late. This doesn't hurt, the check is only there
Expand Down

0 comments on commit 8f2f9c4

Please sign in to comment.