[PATCH 5.15 183/196] ucounts: Move RLIMIT_NPROC handling after set_user

From: Greg Kroah-Hartman
Date: Mon Feb 21 2022 - 04:43:37 EST


From: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>

commit c923a8e7edb010da67424077cbf1a6f1396ebd2e upstream.

During set*id() which cred->ucounts to charge the the current process
to is not known until after set_cred_ucounts. So move the
RLIMIT_NPROC checking into a new helper flag_nproc_exceeded and call
flag_nproc_exceeded after set_cred_ucounts.

This is very much an arbitrary subset of the places where we currently
change the RLIMIT_NPROC accounting, designed to preserve the existing
logic.

Fixing the existing logic will be the subject of another series of
changes.

Cc: stable@xxxxxxxxxxxxxxx
Link: https://lkml.kernel.org/r/20220216155832.680775-4-ebiederm@xxxxxxxxxxxx
Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts")
Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
kernel/sys.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)

--- 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,14 +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)
+ 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;
}

/*
@@ -562,6 +568,7 @@ long __sys_setreuid(uid_t ruid, uid_t eu
if (retval < 0)
goto error;

+ flag_nproc_exceeded(new);
return commit_creds(new);

error:
@@ -624,6 +631,7 @@ long __sys_setuid(uid_t uid)
if (retval < 0)
goto error;

+ flag_nproc_exceeded(new);
return commit_creds(new);

error:
@@ -703,6 +711,7 @@ long __sys_setresuid(uid_t ruid, uid_t e
if (retval < 0)
goto error;

+ flag_nproc_exceeded(new);
return commit_creds(new);

error: