From: Sasha Levin Date: Wed, 4 Oct 2023 10:27:49 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v6.5.6~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9cff4634e0fffca28b6d1b67558757bb0b6e04b8;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- 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 index 00000000000..a86d7db8011 --- /dev/null +++ b/queue-6.1/iommu-arm-smmu-v3-fix-soft-lockup-triggered-by-arm_s.patch @@ -0,0 +1,126 @@ +From 11ca41e4f536c326c2ec7a3d493ec11a61667a60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +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 +Link: https://lore.kernel.org/r/20230920052257.8615-1-nicolinc@nvidia.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-6.1/series b/queue-6.1/series index 8bf38537812..14de272cd4b 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 00000000000..5c1d5f88fd1 --- /dev/null +++ b/queue-6.1/smack-record-transmuting-in-smk_transmuted.patch @@ -0,0 +1,126 @@ +From d00b5493a935716dfad8cfab2d97b98c8921416e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 May 2023 19:02:34 +0200 +Subject: smack: Record transmuting in smk_transmuted + +From: Roberto Sassu + +[ 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 +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d7c5cd67a09 --- /dev/null +++ b/queue-6.1/smack-retrieve-transmuting-information-in-smack_inod.patch @@ -0,0 +1,72 @@ +From 424341c7141a52285efacac280a0342d81f85b96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 May 2023 19:02:33 +0200 +Subject: smack: Retrieve transmuting information in smack_inode_getsecurity() + +From: Roberto Sassu + +[ 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 +Signed-off-by: Casey Schaufler +Signed-off-by: Sasha Levin +--- + 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 +