]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 21 Feb 2022 07:04:31 +0000 (08:04 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 21 Feb 2022 07:04:31 +0000 (08:04 +0100)
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-move-rlimit_nproc-handling-after-set_user.patch
x86-ptrace-fix-xfpregs_set-s-incorrect-xmm-clearing.patch

queue-5.16/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch [new file with mode: 0644]
queue-5.16/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch [new file with mode: 0644]
queue-5.16/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch [new file with mode: 0644]
queue-5.16/series
queue-5.16/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch [new file with mode: 0644]
queue-5.16/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch [new file with mode: 0644]
queue-5.16/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch [new file with mode: 0644]
queue-5.16/ucounts-move-rlimit_nproc-handling-after-set_user.patch [new file with mode: 0644]
queue-5.16/x86-ptrace-fix-xfpregs_set-s-incorrect-xmm-clearing.patch [new file with mode: 0644]

diff --git a/queue-5.16/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch b/queue-5.16/edac-fix-calculation-of-returned-address-and-next-offset-in-edac_align_ptr.patch
new file mode 100644 (file)
index 0000000..3073bdb
--- /dev/null
@@ -0,0 +1,45 @@
+From f8efca92ae509c25e0a4bd5d0a86decea4f0c41e Mon Sep 17 00:00:00 2001
+From: Eliav Farber <farbere@amazon.com>
+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 <farbere@amazon.com>
+
+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 <farbere@amazon.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20220113100622.12783-2-farbere@amazon.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -213,7 +213,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.16/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch b/queue-5.16/rlimit-fix-rlimit_nproc-enforcement-failure-caused-by-capability-calls-in-set_user.patch
new file mode 100644 (file)
index 0000000..b2cf0c3
--- /dev/null
@@ -0,0 +1,103 @@
+From c16bdeb5a39ffa3f32b32f812831a2092d2a3061 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+commit c16bdeb5a39ffa3f32b32f812831a2092d2a3061 upstream.
+
+Solar Designer <solar@openwall.com> 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 <solar@openwall.com>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.16/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch b/queue-5.16/scsi-lpfc-fix-pt2pt-nvme-prli-reject-logo-loop.patch
new file mode 100644 (file)
index 0000000..0d72719
--- /dev/null
@@ -0,0 +1,111 @@
+From 7f4c5a26f735dea4bbc0eb8eb9da99cda95a8563 Mon Sep 17 00:00:00 2001
+From: James Smart <jsmart2021@gmail.com>
+Date: Sat, 12 Feb 2022 08:31:20 -0800
+Subject: scsi: lpfc: Fix pt2pt NVMe PRLI reject LOGO loop
+
+From: James Smart <jsmart2021@gmail.com>
+
+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: <stable@vger.kernel.org> # v5.4+
+Reviewed-by: Ewan D. Milne <emilne@redhat.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -594,6 +594,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
+@@ -4607,6 +4608,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);
index 210f4e1ee0306b533feef8fc7b7f6888be86f56a..d4d28f65dc625346a38603b365ce7f97bb5f9aa8 100644 (file)
@@ -167,6 +167,14 @@ mtd-parsers-qcom-fix-kernel-panic-on-skipped-partition.patch
 mtd-parsers-qcom-fix-missing-free-for-pparts-in-cleanup.patch
 mtd-phram-prevent-divide-by-zero-bug-in-phram_setup.patch
 mtd-rawnand-brcmnand-fixed-incorrect-sub-page-ecc-status.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
+x86-ptrace-fix-xfpregs_set-s-incorrect-xmm-clearing.patch
+ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch
+ucounts-handle-wrapping-in-is_ucounts_overlimit.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
 hid-elo-fix-memory-leak-in-elo_probe.patch
 mtd-rawnand-ingenic-fix-missing-put_device-in-ingeni.patch
 drivers-hv-vmbus-fix-memory-leak-in-vmbus_add_channe.patch
diff --git a/queue-5.16/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch b/queue-5.16/ucounts-base-set_cred_ucounts-changes-on-the-real-user.patch
new file mode 100644 (file)
index 0000000..737a187
--- /dev/null
@@ -0,0 +1,80 @@
+From a55d07294f1e9b576093bdfa95422f8119941e83 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+commit a55d07294f1e9b576093bdfa95422f8119941e83 upstream.
+
+Michal Koutný <mkoutny@suse.com> 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ý <mkoutny@suse.com>
+Reviewed-by: Michal Koutný <mkoutny@suse.com>
+Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts")
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.16/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch b/queue-5.16/ucounts-enforce-rlimit_nproc-not-rlimit_nproc-1.patch
new file mode 100644 (file)
index 0000000..853fb84
--- /dev/null
@@ -0,0 +1,73 @@
+From 8f2f9c4d82f24f172ae439e5035fc1e0e4c229dd Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+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 <ebiederm@xmission.com>
+
+commit 8f2f9c4d82f24f172ae439e5035fc1e0e4c229dd upstream.
+
+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 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ý <mkoutny@suse.com>
+Reviewed-by: Michal Koutný <mkoutny@suse.com>
+Fixes: 21d1c5e386bc ("Reimplement RLIMIT_NPROC on top of ucounts")
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/fork.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2052,18 +2052,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.16/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch b/queue-5.16/ucounts-handle-wrapping-in-is_ucounts_overlimit.patch
new file mode 100644 (file)
index 0000000..628dbf7
--- /dev/null
@@ -0,0 +1,38 @@
+From 0cbae9e24fa7d6c6e9f828562f084da82217a0c5 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 9 Feb 2022 18:09:41 -0600
+Subject: ucounts: Handle wrapping in is_ucounts_overlimit
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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 <skhan@linuxfoundation.org>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/ucount.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/ucount.c
++++ b/kernel/ucount.c
+@@ -350,7 +350,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.16/ucounts-move-rlimit_nproc-handling-after-set_user.patch b/queue-5.16/ucounts-move-rlimit_nproc-handling-after-set_user.patch
new file mode 100644 (file)
index 0000000..3089999
--- /dev/null
@@ -0,0 +1,89 @@
+From c923a8e7edb010da67424077cbf1a6f1396ebd2e Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Mon, 14 Feb 2022 09:40:25 -0600
+Subject: ucounts: Move RLIMIT_NPROC handling after set_user
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+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" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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:
diff --git a/queue-5.16/x86-ptrace-fix-xfpregs_set-s-incorrect-xmm-clearing.patch b/queue-5.16/x86-ptrace-fix-xfpregs_set-s-incorrect-xmm-clearing.patch
new file mode 100644 (file)
index 0000000..ec4f3c2
--- /dev/null
@@ -0,0 +1,87 @@
+From 44cad52cc14ae10062f142ec16ede489bccf4469 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Mon, 14 Feb 2022 13:05:49 +0100
+Subject: x86/ptrace: Fix xfpregs_set()'s incorrect xmm clearing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Andy Lutomirski <luto@kernel.org>
+
+commit 44cad52cc14ae10062f142ec16ede489bccf4469 upstream.
+
+xfpregs_set() handles 32-bit REGSET_XFP and 64-bit REGSET_FP. The actual
+code treats these regsets as modern FX state (i.e. the beginning part of
+XSTATE). The declarations of the regsets thought they were the legacy
+i387 format. The code thought they were the 32-bit (no xmm8..15) variant
+of XSTATE and, for good measure, made the high bits disappear by zeroing
+the wrong part of the buffer. The latter broke ptrace, and everything
+else confused anyone trying to understand the code. In particular, the
+nonsense definitions of the regsets confused me when I wrote this code.
+
+Clean this all up. Change the declarations to match reality (which
+shouldn't change the generated code, let alone the ABI) and fix
+xfpregs_set() to clear the correct bits and to only do so for 32-bit
+callers.
+
+Fixes: 6164331d15f7 ("x86/fpu: Rewrite xfpregs_set()")
+Reported-by: Luís Ferreira <contact@lsferreira.net>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Cc: <stable@vger.kernel.org>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=215524
+Link: https://lore.kernel.org/r/YgpFnZpF01WwR8wU@zn.tnic
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/fpu/regset.c |    9 ++++-----
+ arch/x86/kernel/ptrace.c     |    4 ++--
+ 2 files changed, 6 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/kernel/fpu/regset.c
++++ b/arch/x86/kernel/fpu/regset.c
+@@ -91,11 +91,9 @@ int xfpregs_set(struct task_struct *targ
+               const void *kbuf, const void __user *ubuf)
+ {
+       struct fpu *fpu = &target->thread.fpu;
+-      struct user32_fxsr_struct newstate;
++      struct fxregs_state newstate;
+       int ret;
+-      BUILD_BUG_ON(sizeof(newstate) != sizeof(struct fxregs_state));
+-
+       if (!cpu_feature_enabled(X86_FEATURE_FXSR))
+               return -ENODEV;
+@@ -116,9 +114,10 @@ int xfpregs_set(struct task_struct *targ
+       /* Copy the state  */
+       memcpy(&fpu->fpstate->regs.fxsave, &newstate, sizeof(newstate));
+-      /* Clear xmm8..15 */
++      /* Clear xmm8..15 for 32-bit callers */
+       BUILD_BUG_ON(sizeof(fpu->__fpstate.regs.fxsave.xmm_space) != 16 * 16);
+-      memset(&fpu->fpstate->regs.fxsave.xmm_space[8], 0, 8 * 16);
++      if (in_ia32_syscall())
++              memset(&fpu->fpstate->regs.fxsave.xmm_space[8*4], 0, 8 * 16);
+       /* Mark FP and SSE as in use when XSAVE is enabled */
+       if (use_xsave())
+--- a/arch/x86/kernel/ptrace.c
++++ b/arch/x86/kernel/ptrace.c
+@@ -1224,7 +1224,7 @@ static struct user_regset x86_64_regsets
+       },
+       [REGSET_FP] = {
+               .core_note_type = NT_PRFPREG,
+-              .n = sizeof(struct user_i387_struct) / sizeof(long),
++              .n = sizeof(struct fxregs_state) / sizeof(long),
+               .size = sizeof(long), .align = sizeof(long),
+               .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
+       },
+@@ -1271,7 +1271,7 @@ static struct user_regset x86_32_regsets
+       },
+       [REGSET_XFP] = {
+               .core_note_type = NT_PRXFPREG,
+-              .n = sizeof(struct user32_fxsr_struct) / sizeof(u32),
++              .n = sizeof(struct fxregs_state) / sizeof(u32),
+               .size = sizeof(u32), .align = sizeof(u32),
+               .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
+       },