From a673b755bc0745426acf40a0fbdf72ff6dec908b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 21 Feb 2022 08:04:15 +0100 Subject: [PATCH] 5.15-stable patches added patches: edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch ucounts-handle-wrapping-in-is_ucounts_overlimit.patch ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch ucounts-move-rlimit_nproc-handling-after-set_user.patch --- ...ss-and-next-offset-in-edac_align_ptr.patch | 45 +++++++ ...used-by-capability-calls-in-set_user.patch | 103 ++++++++++++++++ ...fix-pt2pt-nvme-prli-reject-logo-loop.patch | 111 ++++++++++++++++++ queue-5.15/series | 8 ++ ...red_ucounts-changes-on-the-real-user.patch | 80 +++++++++++++ ...orce-rlimit_nproc-not-rlimit_nproc-1.patch | 73 ++++++++++++ ...dle-wrapping-in-is_ucounts_overlimit.patch | 38 ++++++ ...ounts-assume-new-ucounts-is-non-null.patch | 45 +++++++ ...rlimit_nproc-handling-after-set_user.patch | 89 ++++++++++++++ 9 files changed, 592 insertions(+) create mode 100644 queue-5.15/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch create mode 100644 queue-5.15/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch create mode 100644 queue-5.15/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch create mode 100644 queue-5.15/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch create mode 100644 queue-5.15/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch create mode 100644 queue-5.15/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch create mode 100644 queue-5.15/ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch create mode 100644 queue-5.15/ucounts-move-rlimit_nproc-handling-after-set_user.patch diff --git a/queue-5.15/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch b/queue-5.15/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch new file mode 100644 index 00000000000..85ee5d4c420 --- /dev/null +++ b/queue-5.15/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch @@ -0,0 +1,45 @@ +From f8efca92ae509c25e0a4bd5d0a86decea4f0c41e Mon Sep 17 00:00:00 2001 +From: Eliav Farber +Date: Thu, 13 Jan 2022 10:06:19 +0000 +Subject: EDAC: Fix calculation of returned address and next offset in edac_align_ptr() + +From: Eliav Farber + +commit f8efca92ae509c25e0a4bd5d0a86decea4f0c41e upstream. + +Do alignment logic properly and use the "ptr" local variable for +calculating the remainder of the alignment. + +This became an issue because struct edac_mc_layer has a size that is not +zero modulo eight, and the next offset that was prepared for the private +data was unaligned, causing an alignment exception. + +The patch in Fixes: which broke this actually wanted to "what we +actually care about is the alignment of the actual pointer that's about +to be returned." But it didn't check that alignment. + +Use the correct variable "ptr" for that. + + [ bp: Massage commit message. ] + +Fixes: 8447c4d15e35 ("edac: Do alignment logic properly in edac_align_ptr()") +Signed-off-by: Eliav Farber +Signed-off-by: Borislav Petkov +Cc: +Link: https://lore.kernel.org/r/20220113100622.12783-2-farbere@amazon.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/edac/edac_mc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/edac/edac_mc.c ++++ b/drivers/edac/edac_mc.c +@@ -215,7 +215,7 @@ void *edac_align_ptr(void **p, unsigned + else + return (char *)ptr; + +- r = (unsigned long)p % align; ++ r = (unsigned long)ptr % align; + + if (r == 0) + return (char *)ptr; diff --git a/queue-5.15/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch b/queue-5.15/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch new file mode 100644 index 00000000000..b2cf0c349ca --- /dev/null +++ b/queue-5.15/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch @@ -0,0 +1,103 @@ +From c16bdeb5a39ffa3f32b32f812831a2092d2a3061 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Fri, 11 Feb 2022 13:57:44 -0600 +Subject: rlimit: Fix RLIMIT_NPROC enforcement failure caused by capability calls in set_user + +From: Eric W. Biederman + +commit c16bdeb5a39ffa3f32b32f812831a2092d2a3061 upstream. + +Solar Designer wrote: +> I'm not aware of anyone actually running into this issue and reporting +> it. The systems that I personally know use suexec along with rlimits +> still run older/distro kernels, so would not yet be affected. +> +> So my mention was based on my understanding of how suexec works, and +> code review. Specifically, Apache httpd has the setting RLimitNPROC, +> which makes it set RLIMIT_NPROC: +> +> https://httpd.apache.org/docs/2.4/mod/core.html#rlimitnproc +> +> The above documentation for it includes: +> +> "This applies to processes forked from Apache httpd children servicing +> requests, not the Apache httpd children themselves. This includes CGI +> scripts and SSI exec commands, but not any processes forked from the +> Apache httpd parent, such as piped logs." +> +> In code, there are: +> +> ./modules/generators/mod_cgid.c: ( (cgid_req.limits.limit_nproc_set) && ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, +> ./modules/generators/mod_cgi.c: ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, +> ./modules/filters/mod_ext_filter.c: rv = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, conf->limit_nproc); +> +> For example, in mod_cgi.c this is in run_cgi_child(). +> +> I think this means an httpd child sets RLIMIT_NPROC shortly before it +> execs suexec, which is a SUID root program. suexec then switches to the +> target user and execs the CGI script. +> +> Before 2863643fb8b9, the setuid() in suexec would set the flag, and the +> target user's process count would be checked against RLIMIT_NPROC on +> execve(). After 2863643fb8b9, the setuid() in suexec wouldn't set the +> flag because setuid() is (naturally) called when the process is still +> running as root (thus, has those limits bypass capabilities), and +> accordingly execve() would not check the target user's process count +> against RLIMIT_NPROC. + +In commit 2863643fb8b9 ("set_user: add capability check when +rlimit(RLIMIT_NPROC) exceeds") capable calls were added to set_user to +make it more consistent with fork. Unfortunately because of call site +differences those capable calls were checking the credentials of the +user before set*id() instead of after set*id(). + +This breaks enforcement of RLIMIT_NPROC for applications that set the +rlimit and then call set*id() while holding a full set of +capabilities. The capabilities are only changed in the new credential +in security_task_fix_setuid(). + +The code in apache suexec appears to follow this pattern. + +Commit 909cc4ae86f3 ("[PATCH] Fix two bugs with process limits +(RLIMIT_NPROC)") where this check was added describes the targes of this +capability check as: + + 2/ When a root-owned process (e.g. cgiwrap) sets up process limits and then + calls setuid, the setuid should fail if the user would then be running + more than rlim_cur[RLIMIT_NPROC] processes, but it doesn't. This patch + adds an appropriate test. With this patch, and per-user process limit + imposed in cgiwrap really works. + +So the original use case of this check also appears to match the broken +pattern. + +Restore the enforcement of RLIMIT_NPROC by removing the bad capable +checks added in set_user. This unfortunately restores the +inconsistent state the code has been in for the last 11 years, but +dealing with the inconsistencies looks like a larger problem. + +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/20210907213042.GA22626@openwall.com/ +Link: https://lkml.kernel.org/r/20220212221412.GA29214@openwall.com +Link: https://lkml.kernel.org/r/20220216155832.680775-1-ebiederm@xmission.com +Fixes: 2863643fb8b9 ("set_user: add capability check when rlimit(RLIMIT_NPROC) exceeds") +History-Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git +Reviewed-by: Solar Designer +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + kernel/sys.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -480,8 +480,7 @@ 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 && +- !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) ++ new_user != INIT_USER) + current->flags |= PF_NPROC_EXCEEDED; + else + current->flags &= ~PF_NPROC_EXCEEDED; diff --git a/queue-5.15/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch b/queue-5.15/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch new file mode 100644 index 00000000000..6c3f04c23f9 --- /dev/null +++ b/queue-5.15/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch @@ -0,0 +1,111 @@ +From 7f4c5a26f735dea4bbc0eb8eb9da99cda95a8563 Mon Sep 17 00:00:00 2001 +From: James Smart +Date: Sat, 12 Feb 2022 08:31:20 -0800 +Subject: scsi: lpfc: Fix pt2pt NVMe PRLI reject LOGO loop + +From: James Smart + +commit 7f4c5a26f735dea4bbc0eb8eb9da99cda95a8563 upstream. + +When connected point to point, the driver does not know the FC4's supported +by the other end. In Fabrics, it can query the nameserver. Thus the driver +must send PRLIs for the FC4s it supports and enable support based on the +acc(ept) or rej(ect) of the respective FC4 PRLI. Currently the driver +supports SCSI and NVMe PRLIs. + +Unfortunately, although the behavior is per standard, many devices have +come to expect only SCSI PRLIs. In this particular example, the NVMe PRLI +is properly RJT'd but the target decided that it must LOGO after seeing the +unexpected NVMe PRLI. The LOGO causes the sequence to restart and login is +now in an infinite failure loop. + +Fix the problem by having the driver, on a pt2pt link, remember NVMe PRLI +accept or reject status across logout as long as the link stays "up". When +retrying login, if the prior NVMe PRLI was rejected, it will not be sent on +the next login. + +Link: https://lore.kernel.org/r/20220212163120.15385-1-jsmart2021@gmail.com +Cc: # v5.4+ +Reviewed-by: Ewan D. Milne +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/lpfc/lpfc.h | 1 + + drivers/scsi/lpfc/lpfc_attr.c | 3 +++ + drivers/scsi/lpfc/lpfc_els.c | 20 +++++++++++++++++++- + drivers/scsi/lpfc/lpfc_nportdisc.c | 5 +++-- + 4 files changed, 26 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/lpfc/lpfc.h ++++ b/drivers/scsi/lpfc/lpfc.h +@@ -593,6 +593,7 @@ struct lpfc_vport { + #define FC_VPORT_LOGO_RCVD 0x200 /* LOGO received on vport */ + #define FC_RSCN_DISCOVERY 0x400 /* Auth all devices after RSCN */ + #define FC_LOGO_RCVD_DID_CHNG 0x800 /* FDISC on phys port detect DID chng*/ ++#define FC_PT2PT_NO_NVME 0x1000 /* Don't send NVME PRLI */ + #define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */ + #define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */ + #define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */ +--- a/drivers/scsi/lpfc/lpfc_attr.c ++++ b/drivers/scsi/lpfc/lpfc_attr.c +@@ -1315,6 +1315,9 @@ lpfc_issue_lip(struct Scsi_Host *shost) + pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK; + pmboxq->u.mb.mbxOwner = OWN_HOST; + ++ if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME)) ++ vport->fc_flag &= ~FC_PT2PT_NO_NVME; ++ + mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2); + + if ((mbxstatus == MBX_SUCCESS) && +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -1072,7 +1072,8 @@ stop_rr_fcf_flogi: + + /* FLOGI failed, so there is no fabric */ + spin_lock_irq(shost->host_lock); +- vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); ++ vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP | ++ FC_PT2PT_NO_NVME); + spin_unlock_irq(shost->host_lock); + + /* If private loop, then allow max outstanding els to be +@@ -4587,6 +4588,23 @@ lpfc_els_retry(struct lpfc_hba *phba, st + /* Added for Vendor specifc support + * Just keep retrying for these Rsn / Exp codes + */ ++ if ((vport->fc_flag & FC_PT2PT) && ++ cmd == ELS_CMD_NVMEPRLI) { ++ switch (stat.un.b.lsRjtRsnCode) { ++ case LSRJT_UNABLE_TPC: ++ case LSRJT_INVALID_CMD: ++ case LSRJT_LOGICAL_ERR: ++ case LSRJT_CMD_UNSUPPORTED: ++ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, ++ "0168 NVME PRLI LS_RJT " ++ "reason %x port doesn't " ++ "support NVME, disabling NVME\n", ++ stat.un.b.lsRjtRsnCode); ++ retry = 0; ++ vport->fc_flag |= FC_PT2PT_NO_NVME; ++ goto out_retry; ++ } ++ } + switch (stat.un.b.lsRjtRsnCode) { + case LSRJT_UNABLE_TPC: + /* The driver has a VALID PLOGI but the rport has +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -1961,8 +1961,9 @@ lpfc_cmpl_reglogin_reglogin_issue(struct + * is configured try it. + */ + ndlp->nlp_fc4_type |= NLP_FC4_FCP; +- if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || +- (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { ++ if ((!(vport->fc_flag & FC_PT2PT_NO_NVME)) && ++ (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH || ++ vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { + ndlp->nlp_fc4_type |= NLP_FC4_NVME; + /* We need to update the localport also */ + lpfc_nvme_update_localport(vport); diff --git a/queue-5.15/series b/queue-5.15/series index ef286313307..e534e6f2b41 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -173,3 +173,11 @@ drm-amd-display-fix-yellow-carp-wm-clamping.patch net-usb-qmi_wwan-add-support-for-dell-dw5829e.patch net-macb-align-the-dma-and-coherent-dma-masks.patch kconfig-fix-failing-to-generate-auto.conf.patch +scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch +edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch +ucounts-handle-wrapping-in-is_ucounts_overlimit.patch +ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch +ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch +ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch +rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch +ucounts-move-rlimit_nproc-handling-after-set_user.patch diff --git a/queue-5.15/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch b/queue-5.15/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch new file mode 100644 index 00000000000..737a1878e63 --- /dev/null +++ b/queue-5.15/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch @@ -0,0 +1,80 @@ +From a55d07294f1e9b576093bdfa95422f8119941e83 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 9 Feb 2022 16:22:20 -0600 +Subject: ucounts: Base set_cred_ucounts changes on the real user +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric W. Biederman + +commit a55d07294f1e9b576093bdfa95422f8119941e83 upstream. + +Michal Koutný wrote: +> Tasks are associated to multiple users at once. Historically and as per +> setrlimit(2) RLIMIT_NPROC is enforce based on real user ID. +> +> The commit 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") +> made the accounting structure "indexed" by euid and hence potentially +> account tasks differently. +> +> The effective user ID may be different e.g. for setuid programs but +> those are exec'd into already existing task (i.e. below limit), so +> different accounting is moot. +> +> Some special setresuid(2) users may notice the difference, justifying +> this fix. + +I looked at cred->ucount and it is only used for rlimit operations +that were previously stored in cred->user. Making the fact +cred->ucount can refer to a different user from cred->user a bug, +affecting all uses of cred->ulimit not just RLIMIT_NPROC. + +Fix set_cred_ucounts to always use the real uid not the effective uid. + +Further simplify set_cred_ucounts by noticing that set_cred_ucounts +somehow retained a draft version of the check to see if alloc_ucounts +was needed that checks the new->user and new->user_ns against the +current_real_cred(). Remove that draft version of the check. + +All that matters for setting the cred->ucounts are the user_ns and uid +fields in the cred. + +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/20220207121800.5079-4-mkoutny@suse.com +Link: https://lkml.kernel.org/r/20220216155832.680775-3-ebiederm@xmission.com +Reported-by: Michal Koutný +Reviewed-by: Michal Koutný +Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + kernel/cred.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -665,21 +665,16 @@ EXPORT_SYMBOL(cred_fscmp); + + int set_cred_ucounts(struct cred *new) + { +- struct task_struct *task = current; +- const struct cred *old = task->real_cred; + struct ucounts *new_ucounts, *old_ucounts = new->ucounts; + +- if (new->user == old->user && new->user_ns == old->user_ns) +- return 0; +- + /* + * This optimization is needed because alloc_ucounts() uses locks + * for table lookups. + */ +- if (old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid)) ++ if (old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->uid)) + return 0; + +- if (!(new_ucounts = alloc_ucounts(new->user_ns, new->euid))) ++ if (!(new_ucounts = alloc_ucounts(new->user_ns, new->uid))) + return -EAGAIN; + + new->ucounts = new_ucounts; diff --git a/queue-5.15/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch b/queue-5.15/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch new file mode 100644 index 00000000000..f1836ef7ad1 --- /dev/null +++ b/queue-5.15/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch @@ -0,0 +1,73 @@ +From 8f2f9c4d82f24f172ae439e5035fc1e0e4c229dd Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 9 Feb 2022 20:03:19 -0600 +Subject: ucounts: Enforce RLIMIT_NPROC not RLIMIT_NPROC+1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Eric W. Biederman + +commit 8f2f9c4d82f24f172ae439e5035fc1e0e4c229dd upstream. + +Michal Koutný 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 21d1c5e386bc ("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ý +Reviewed-by: Michal Koutný +Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + kernel/fork.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2055,18 +2055,18 @@ static __latent_entropy struct task_stru + #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 diff --git a/queue-5.15/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch b/queue-5.15/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch new file mode 100644 index 00000000000..99a635794bd --- /dev/null +++ b/queue-5.15/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch @@ -0,0 +1,38 @@ +From 0cbae9e24fa7d6c6e9f828562f084da82217a0c5 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 9 Feb 2022 18:09:41 -0600 +Subject: ucounts: Handle wrapping in is_ucounts_overlimit + +From: Eric W. Biederman + +commit 0cbae9e24fa7d6c6e9f828562f084da82217a0c5 upstream. + +While examining is_ucounts_overlimit and reading the various messages +I realized that is_ucounts_overlimit fails to deal with counts that +may have wrapped. + +Being wrapped should be a transitory state for counts and they should +never be wrapped for long, but it can happen so handle it. + +Cc: stable@vger.kernel.org +Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") +Link: https://lkml.kernel.org/r/20220216155832.680775-5-ebiederm@xmission.com +Reviewed-by: Shuah Khan +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + kernel/ucount.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/ucount.c ++++ b/kernel/ucount.c +@@ -344,7 +344,8 @@ bool is_ucounts_overlimit(struct ucounts + if (rlimit > LONG_MAX) + max = LONG_MAX; + for (iter = ucounts; iter; iter = iter->ns->ucounts) { +- if (get_ucounts_value(iter, type) > max) ++ long val = get_ucounts_value(iter, type); ++ if (val < 0 || val > max) + return true; + max = READ_ONCE(iter->ns->ucount_max[type]); + } diff --git a/queue-5.15/ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch b/queue-5.15/ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch new file mode 100644 index 00000000000..71bc9423d16 --- /dev/null +++ b/queue-5.15/ucounts-in-set_cred_ucounts-assume-new-ucounts-is-non-null.patch @@ -0,0 +1,45 @@ +From 99c31f9feda41d0f10d030dc04ba106c93295aa2 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Sat, 16 Oct 2021 12:51:58 -0500 +Subject: ucounts: In set_cred_ucounts assume new->ucounts is non-NULL + +From: Eric W. Biederman + +commit 99c31f9feda41d0f10d030dc04ba106c93295aa2 upstream. + +Any cred that is destined for use by commit_creds must have a non-NULL +cred->ucounts field. Only curing credential construction is a NULL +cred->ucounts valid. Only abort_creds, put_cred, and put_cred_rcu +needs to deal with a cred with a NULL ucount. As set_cred_ucounts is +non of those case don't confuse people by handling something that can +not happen. + +Link: https://lkml.kernel.org/r/871r4irzds.fsf_-_@disp2133 +Tested-by: Yu Zhao +Reviewed-by: Alexey Gladkov +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + kernel/cred.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/kernel/cred.c ++++ b/kernel/cred.c +@@ -676,15 +676,14 @@ int set_cred_ucounts(struct cred *new) + * This optimization is needed because alloc_ucounts() uses locks + * for table lookups. + */ +- if (old_ucounts && old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid)) ++ if (old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid)) + return 0; + + if (!(new_ucounts = alloc_ucounts(new->user_ns, new->euid))) + return -EAGAIN; + + new->ucounts = new_ucounts; +- if (old_ucounts) +- put_ucounts(old_ucounts); ++ put_ucounts(old_ucounts); + + return 0; + } diff --git a/queue-5.15/ucounts-move-rlimit_nproc-handling-after-set_user.patch b/queue-5.15/ucounts-move-rlimit_nproc-handling-after-set_user.patch new file mode 100644 index 00000000000..3089999d22a --- /dev/null +++ b/queue-5.15/ucounts-move-rlimit_nproc-handling-after-set_user.patch @@ -0,0 +1,89 @@ +From c923a8e7edb010da67424077cbf1a6f1396ebd2e Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Mon, 14 Feb 2022 09:40:25 -0600 +Subject: ucounts: Move RLIMIT_NPROC handling after set_user + +From: Eric W. Biederman + +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@vger.kernel.org +Link: https://lkml.kernel.org/r/20220216155832.680775-4-ebiederm@xmission.com +Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts") +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman +--- + 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: -- 2.47.3