ucounts: Move RLIMIT_NPROC handling after set_user

Bugzilla: https://bugzilla.redhat.com/2061724
Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

commit c923a8e7edb010da67424077cbf1a6f1396ebd2e
Author: Eric W. Biederman <ebiederm@xmission.com>
Date:   Mon Feb 14 09:40:25 2022 -0600

    ucounts: Move RLIMIT_NPROC handling after set_user

    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@vger.kernel.org
    Link: https://lkml.kernel.org/r/20220216155832.680775-4-ebiederm@xmission.com
    Fixes: 21d1c5e386 ("Reimplement RLIMIT_NPROC on top of ucounts")
    Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

Signed-off-by: Alexey Gladkov <agladkov@redhat.com>
This commit is contained in:
Alexey Gladkov 2022-03-08 13:25:22 +01:00
parent bedcb96dd6
commit 7aadcd187c
1 changed files with 14 additions and 5 deletions

View File

@ -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 euid)
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 euid, uid_t suid)
if (retval < 0)
goto error;
flag_nproc_exceeded(new);
return commit_creds(new);
error: