]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Wed, 4 Oct 2023 10:27:49 +0000 (06:27 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 4 Oct 2023 10:27:49 +0000 (06:27 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/iommu-arm-smmu-v3-fix-soft-lockup-triggered-by-arm_s.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/smack-record-transmuting-in-smk_transmuted.patch [new file with mode: 0644]
queue-6.1/smack-retrieve-transmuting-information-in-smack_inod.patch [new file with mode: 0644]

diff --git a/queue-6.1/iommu-arm-smmu-v3-fix-soft-lockup-triggered-by-arm_s.patch b/queue-6.1/iommu-arm-smmu-v3-fix-soft-lockup-triggered-by-arm_s.patch
new file mode 100644 (file)
index 0000000..a86d7db
--- /dev/null
@@ -0,0 +1,126 @@
+From 11ca41e4f536c326c2ec7a3d493ec11a61667a60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 16:35:49 -0700
+Subject: iommu/arm-smmu-v3: Fix soft lockup triggered by
+ arm_smmu_mm_invalidate_range
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit d5afb4b47e13161b3f33904d45110f9e6463bad6 upstream.
+
+When running an SVA case, the following soft lockup is triggered:
+--------------------------------------------------------------------
+watchdog: BUG: soft lockup - CPU#244 stuck for 26s!
+pstate: 83400009 (Nzcv daif +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
+pc : arm_smmu_cmdq_issue_cmdlist+0x178/0xa50
+lr : arm_smmu_cmdq_issue_cmdlist+0x150/0xa50
+sp : ffff8000d83ef290
+x29: ffff8000d83ef290 x28: 000000003b9aca00 x27: 0000000000000000
+x26: ffff8000d83ef3c0 x25: da86c0812194a0e8 x24: 0000000000000000
+x23: 0000000000000040 x22: ffff8000d83ef340 x21: ffff0000c63980c0
+x20: 0000000000000001 x19: ffff0000c6398080 x18: 0000000000000000
+x17: 0000000000000000 x16: 0000000000000000 x15: ffff3000b4a3bbb0
+x14: ffff3000b4a30888 x13: ffff3000b4a3cf60 x12: 0000000000000000
+x11: 0000000000000000 x10: 0000000000000000 x9 : ffffc08120e4d6bc
+x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000048cfa
+x5 : 0000000000000000 x4 : 0000000000000001 x3 : 000000000000000a
+x2 : 0000000080000000 x1 : 0000000000000000 x0 : 0000000000000001
+Call trace:
+ arm_smmu_cmdq_issue_cmdlist+0x178/0xa50
+ __arm_smmu_tlb_inv_range+0x118/0x254
+ arm_smmu_tlb_inv_range_asid+0x6c/0x130
+ arm_smmu_mm_invalidate_range+0xa0/0xa4
+ __mmu_notifier_invalidate_range_end+0x88/0x120
+ unmap_vmas+0x194/0x1e0
+ unmap_region+0xb4/0x144
+ do_mas_align_munmap+0x290/0x490
+ do_mas_munmap+0xbc/0x124
+ __vm_munmap+0xa8/0x19c
+ __arm64_sys_munmap+0x28/0x50
+ invoke_syscall+0x78/0x11c
+ el0_svc_common.constprop.0+0x58/0x1c0
+ do_el0_svc+0x34/0x60
+ el0_svc+0x2c/0xd4
+ el0t_64_sync_handler+0x114/0x140
+ el0t_64_sync+0x1a4/0x1a8
+--------------------------------------------------------------------
+
+The commit 06ff87bae8d3 ("arm64: mm: remove unused functions and variable
+protoypes") fixed a similar lockup on the CPU MMU side. Yet, it can occur
+to SMMU too since arm_smmu_mm_invalidate_range() is typically called next
+to MMU tlb flush function, e.g.
+       tlb_flush_mmu_tlbonly {
+               tlb_flush {
+                       __flush_tlb_range {
+                               // check MAX_TLBI_OPS
+                       }
+               }
+               mmu_notifier_invalidate_range {
+                       arm_smmu_mm_invalidate_range {
+                               // does not check MAX_TLBI_OPS
+                       }
+               }
+       }
+
+Clone a CMDQ_MAX_TLBI_OPS from the MAX_TLBI_OPS in tlbflush.h, since in an
+SVA case SMMU uses the CPU page table, so it makes sense to align with the
+tlbflush code. Then, replace per-page TLBI commands with a single per-asid
+TLBI command, if the request size hits this threshold.
+
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Link: https://lore.kernel.org/r/20230920052257.8615-1-nicolinc@nvidia.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 27 ++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+index 5968a568aae2a..ffba8ce93ff88 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+@@ -186,6 +186,15 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd)
+       }
+ }
++/*
++ * Cloned from the MAX_TLBI_OPS in arch/arm64/include/asm/tlbflush.h, this
++ * is used as a threshold to replace per-page TLBI commands to issue in the
++ * command queue with an address-space TLBI command, when SMMU w/o a range
++ * invalidation feature handles too many per-page TLBI commands, which will
++ * otherwise result in a soft lockup.
++ */
++#define CMDQ_MAX_TLBI_OPS             (1 << (PAGE_SHIFT - 3))
++
+ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
+                                        struct mm_struct *mm,
+                                        unsigned long start, unsigned long end)
+@@ -200,10 +209,22 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
+        * range. So do a simple translation here by calculating size correctly.
+        */
+       size = end - start;
++      if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) {
++              if (size >= CMDQ_MAX_TLBI_OPS * PAGE_SIZE)
++                      size = 0;
++      }
++
++      if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) {
++              if (!size)
++                      arm_smmu_tlb_inv_asid(smmu_domain->smmu,
++                                            smmu_mn->cd->asid);
++              else
++                      arm_smmu_tlb_inv_range_asid(start, size,
++                                                  smmu_mn->cd->asid,
++                                                  PAGE_SIZE, false,
++                                                  smmu_domain);
++      }
+-      if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM))
+-              arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,
+-                                          PAGE_SIZE, false, smmu_domain);
+       arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size);
+ }
+-- 
+2.40.1
+
index 8bf385378125b601b07659163253fc2f3e39cab4..14de272cd4bacaf8a85095ed01f16f6c2fdbd748 100644 (file)
@@ -203,3 +203,6 @@ nvme-pci-do-not-set-the-numa-node-of-device-if-it-ha.patch
 wifi-ath11k-don-t-drop-tx_status-when-peer-cannot-be.patch
 scsi-qla2xxx-fix-null-pointer-dereference-in-target-.patch
 nvme-pci-always-return-an-err_ptr-from-nvme_pci_allo.patch
+smack-record-transmuting-in-smk_transmuted.patch
+smack-retrieve-transmuting-information-in-smack_inod.patch
+iommu-arm-smmu-v3-fix-soft-lockup-triggered-by-arm_s.patch
diff --git a/queue-6.1/smack-record-transmuting-in-smk_transmuted.patch b/queue-6.1/smack-record-transmuting-in-smk_transmuted.patch
new file mode 100644 (file)
index 0000000..5c1d5f8
--- /dev/null
@@ -0,0 +1,126 @@
+From d00b5493a935716dfad8cfab2d97b98c8921416e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 May 2023 19:02:34 +0200
+Subject: smack: Record transmuting in smk_transmuted
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+[ Upstream commit 2c085f3a8f23c9b444e8b99d93c15d7ce870fc4e ]
+
+smack_dentry_create_files_as() determines whether transmuting should occur
+based on the label of the parent directory the new inode will be added to,
+and not the label of the directory where it is created.
+
+This helps for example to do transmuting on overlayfs, since the latter
+first creates the inode in the working directory, and then moves it to the
+correct destination.
+
+However, despite smack_dentry_create_files_as() provides the correct label,
+smack_inode_init_security() does not know from passed information whether
+or not transmuting occurred. Without this information,
+smack_inode_init_security() cannot set SMK_INODE_CHANGED in smk_flags,
+which will result in the SMACK64TRANSMUTE xattr not being set in
+smack_d_instantiate().
+
+Thus, add the smk_transmuted field to the task_smack structure, and set it
+in smack_dentry_create_files_as() to smk_task if transmuting occurred. If
+smk_task is equal to smk_transmuted in smack_inode_init_security(), act as
+if transmuting was successful but without taking the label from the parent
+directory (the inode label was already set correctly from the current
+credentials in smack_inode_alloc_security()).
+
+Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/smack/smack.h     |  1 +
+ security/smack/smack_lsm.c | 41 +++++++++++++++++++++++++++-----------
+ 2 files changed, 30 insertions(+), 12 deletions(-)
+
+diff --git a/security/smack/smack.h b/security/smack/smack.h
+index e2239be7bd60a..aa15ff56ed6e7 100644
+--- a/security/smack/smack.h
++++ b/security/smack/smack.h
+@@ -120,6 +120,7 @@ struct inode_smack {
+ struct task_smack {
+       struct smack_known      *smk_task;      /* label for access control */
+       struct smack_known      *smk_forked;    /* label when forked */
++      struct smack_known      *smk_transmuted;/* label when transmuted */
+       struct list_head        smk_rules;      /* per task access rules */
+       struct mutex            smk_rules_lock; /* lock for the rules */
+       struct list_head        smk_relabel;    /* transit allowed labels */
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 67dcd31cd3f3d..1232c1d71d9f8 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -999,8 +999,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
+                                    const struct qstr *qstr, const char **name,
+                                    void **value, size_t *len)
+ {
++      struct task_smack *tsp = smack_cred(current_cred());
+       struct inode_smack *issp = smack_inode(inode);
+-      struct smack_known *skp = smk_of_current();
++      struct smack_known *skp = smk_of_task(tsp);
+       struct smack_known *isp = smk_of_inode(inode);
+       struct smack_known *dsp = smk_of_inode(dir);
+       int may;
+@@ -1009,20 +1010,34 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
+               *name = XATTR_SMACK_SUFFIX;
+       if (value && len) {
+-              rcu_read_lock();
+-              may = smk_access_entry(skp->smk_known, dsp->smk_known,
+-                                     &skp->smk_rules);
+-              rcu_read_unlock();
++              /*
++               * If equal, transmuting already occurred in
++               * smack_dentry_create_files_as(). No need to check again.
++               */
++              if (tsp->smk_task != tsp->smk_transmuted) {
++                      rcu_read_lock();
++                      may = smk_access_entry(skp->smk_known, dsp->smk_known,
++                                             &skp->smk_rules);
++                      rcu_read_unlock();
++              }
+               /*
+-               * If the access rule allows transmutation and
+-               * the directory requests transmutation then
+-               * by all means transmute.
++               * In addition to having smk_task equal to smk_transmuted,
++               * if the access rule allows transmutation and the directory
++               * requests transmutation then by all means transmute.
+                * Mark the inode as changed.
+                */
+-              if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
+-                  smk_inode_transmutable(dir)) {
+-                      isp = dsp;
++              if ((tsp->smk_task == tsp->smk_transmuted) ||
++                  (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
++                   smk_inode_transmutable(dir))) {
++                      /*
++                       * The caller of smack_dentry_create_files_as()
++                       * should have overridden the current cred, so the
++                       * inode label was already set correctly in
++                       * smack_inode_alloc_security().
++                       */
++                      if (tsp->smk_task != tsp->smk_transmuted)
++                              isp = dsp;
+                       issp->smk_flags |= SMK_INODE_CHANGED;
+               }
+@@ -4750,8 +4765,10 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
+                * providing access is transmuting use the containing
+                * directory label instead of the process label.
+                */
+-              if (may > 0 && (may & MAY_TRANSMUTE))
++              if (may > 0 && (may & MAY_TRANSMUTE)) {
+                       ntsp->smk_task = isp->smk_inode;
++                      ntsp->smk_transmuted = ntsp->smk_task;
++              }
+       }
+       return 0;
+ }
+-- 
+2.40.1
+
diff --git a/queue-6.1/smack-retrieve-transmuting-information-in-smack_inod.patch b/queue-6.1/smack-retrieve-transmuting-information-in-smack_inod.patch
new file mode 100644 (file)
index 0000000..d7c5cd6
--- /dev/null
@@ -0,0 +1,72 @@
+From 424341c7141a52285efacac280a0342d81f85b96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 May 2023 19:02:33 +0200
+Subject: smack: Retrieve transmuting information in smack_inode_getsecurity()
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+[ Upstream commit 3a3d8fce31a49363cc31880dce5e3b0617c9c38b ]
+
+Enhance smack_inode_getsecurity() to retrieve the value for
+SMACK64TRANSMUTE from the inode security blob, similarly to SMACK64.
+
+This helps to display accurate values in the situation where the security
+labels come from mount options and not from xattrs.
+
+Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
+Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ security/smack/smack_lsm.c | 22 ++++++++++++++++++----
+ 1 file changed, 18 insertions(+), 4 deletions(-)
+
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 1232c1d71d9f8..cd6a03e945eb7 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -1476,10 +1476,19 @@ static int smack_inode_getsecurity(struct user_namespace *mnt_userns,
+       struct super_block *sbp;
+       struct inode *ip = (struct inode *)inode;
+       struct smack_known *isp;
++      struct inode_smack *ispp;
++      size_t label_len;
++      char *label = NULL;
+-      if (strcmp(name, XATTR_SMACK_SUFFIX) == 0)
++      if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
+               isp = smk_of_inode(inode);
+-      else {
++      } else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
++              ispp = smack_inode(inode);
++              if (ispp->smk_flags & SMK_INODE_TRANSMUTE)
++                      label = TRANS_TRUE;
++              else
++                      label = "";
++      } else {
+               /*
+                * The rest of the Smack xattrs are only on sockets.
+                */
+@@ -1501,13 +1510,18 @@ static int smack_inode_getsecurity(struct user_namespace *mnt_userns,
+                       return -EOPNOTSUPP;
+       }
++      if (!label)
++              label = isp->smk_known;
++
++      label_len = strlen(label);
++
+       if (alloc) {
+-              *buffer = kstrdup(isp->smk_known, GFP_KERNEL);
++              *buffer = kstrdup(label, GFP_KERNEL);
+               if (*buffer == NULL)
+                       return -ENOMEM;
+       }
+-      return strlen(isp->smk_known);
++      return label_len;
+ }
+-- 
+2.40.1
+