--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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);
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
--- /dev/null
+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;
--- /dev/null
+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
--- /dev/null
+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]);
+ }
--- /dev/null
+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:
--- /dev/null
+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
+ },