From: Greg Kroah-Hartman Date: Thu, 12 Dec 2024 08:23:36 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v5.4.287~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=848c7a4c2f02e31e9141c229fb8cb0d3cdc70772;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: kvm-arm64-vgic-its-add-a-data-length-check-in-vgic_its_save_.patch kvm-arm64-vgic-its-clear-dte-when-mapd-unmaps-a-device.patch kvm-arm64-vgic-its-clear-ite-when-discard-frees-an-ite.patch udf-fold-udf_getblk-into-udf_bread.patch --- diff --git a/queue-6.1/kvm-arm64-vgic-its-add-a-data-length-check-in-vgic_its_save_.patch b/queue-6.1/kvm-arm64-vgic-its-add-a-data-length-check-in-vgic_its_save_.patch new file mode 100644 index 00000000000..ee3e66b243e --- /dev/null +++ b/queue-6.1/kvm-arm64-vgic-its-add-a-data-length-check-in-vgic_its_save_.patch @@ -0,0 +1,148 @@ +From stable+bounces-98556-greg=kroah.com@vger.kernel.org Wed Dec 4 21:24:07 2024 +From: Jing Zhang +Date: Wed, 4 Dec 2024 12:23:55 -0800 +Subject: KVM: arm64: vgic-its: Add a data length check in vgic_its_save_* +To: stable@vger.kernel.org +Cc: Marc Zyngier , Oliver Upton , Kunkun Jiang , Jing Zhang +Message-ID: <20241204202357.2718096-1-jingzhangos@google.com> + +From: Jing Zhang + +commit 7fe28d7e68f92cc3d0668b8f2fbdf5c303ac3022 upstream. + +In all the vgic_its_save_*() functinos, they do not check whether +the data length is 8 bytes before calling vgic_write_guest_lock. +This patch adds the check. To prevent the kernel from being blown up +when the fault occurs, KVM_BUG_ON() is used. And the other BUG_ON()s +are replaced together. + +Cc: stable@vger.kernel.org +Signed-off-by: Kunkun Jiang +[Jing: Update with the new entry read/write helpers] +Signed-off-by: Jing Zhang +Link: https://lore.kernel.org/r/20241107214137.428439-4-jingzhangos@google.com +Signed-off-by: Oliver Upton +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/vgic/vgic-its.c | 20 ++++++++------------ + arch/arm64/kvm/vgic/vgic.h | 24 ++++++++++++++++++++++++ + 2 files changed, 32 insertions(+), 12 deletions(-) + +--- a/arch/arm64/kvm/vgic/vgic-its.c ++++ b/arch/arm64/kvm/vgic/vgic-its.c +@@ -2207,7 +2207,6 @@ static int scan_its_table(struct vgic_it + static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev, + struct its_ite *ite, gpa_t gpa, int ite_esz) + { +- struct kvm *kvm = its->dev->kvm; + u32 next_offset; + u64 val; + +@@ -2216,7 +2215,8 @@ static int vgic_its_save_ite(struct vgic + ((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) | + ite->collection->collection_id; + val = cpu_to_le64(val); +- return kvm_write_guest_lock(kvm, gpa, &val, ite_esz); ++ ++ return vgic_its_write_entry_lock(its, gpa, val, ite_esz); + } + + /** +@@ -2357,7 +2357,6 @@ static int vgic_its_restore_itt(struct v + static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev, + gpa_t ptr, int dte_esz) + { +- struct kvm *kvm = its->dev->kvm; + u64 val, itt_addr_field; + u32 next_offset; + +@@ -2368,7 +2367,8 @@ static int vgic_its_save_dte(struct vgic + (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) | + (dev->num_eventid_bits - 1)); + val = cpu_to_le64(val); +- return kvm_write_guest_lock(kvm, ptr, &val, dte_esz); ++ ++ return vgic_its_write_entry_lock(its, ptr, val, dte_esz); + } + + /** +@@ -2555,7 +2555,8 @@ static int vgic_its_save_cte(struct vgic + ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) | + collection->collection_id); + val = cpu_to_le64(val); +- return kvm_write_guest_lock(its->dev->kvm, gpa, &val, esz); ++ ++ return vgic_its_write_entry_lock(its, gpa, val, esz); + } + + /* +@@ -2571,8 +2572,7 @@ static int vgic_its_restore_cte(struct v + u64 val; + int ret; + +- BUG_ON(esz > sizeof(val)); +- ret = kvm_read_guest_lock(kvm, gpa, &val, esz); ++ ret = vgic_its_read_entry_lock(its, gpa, &val, esz); + if (ret) + return ret; + val = le64_to_cpu(val); +@@ -2610,7 +2610,6 @@ static int vgic_its_save_collection_tabl + u64 baser = its->baser_coll_table; + gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser); + struct its_collection *collection; +- u64 val; + size_t max_size, filled = 0; + int ret, cte_esz = abi->cte_esz; + +@@ -2634,10 +2633,7 @@ static int vgic_its_save_collection_tabl + * table is not fully filled, add a last dummy element + * with valid bit unset + */ +- val = 0; +- BUG_ON(cte_esz > sizeof(val)); +- ret = kvm_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz); +- return ret; ++ return vgic_its_write_entry_lock(its, gpa, 0, cte_esz); + } + + /** +--- a/arch/arm64/kvm/vgic/vgic.h ++++ b/arch/arm64/kvm/vgic/vgic.h +@@ -6,6 +6,7 @@ + #define __KVM_ARM_VGIC_NEW_H__ + + #include ++#include + + #define PRODUCT_ID_KVM 0x4b /* ASCII code K */ + #define IMPLEMENTER_ARM 0x43b +@@ -131,6 +132,29 @@ static inline bool vgic_irq_is_multi_sgi + return vgic_irq_get_lr_count(irq) > 1; + } + ++static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr, ++ u64 *eval, unsigned long esize) ++{ ++ struct kvm *kvm = its->dev->kvm; ++ ++ if (KVM_BUG_ON(esize != sizeof(*eval), kvm)) ++ return -EINVAL; ++ ++ return kvm_read_guest_lock(kvm, eaddr, eval, esize); ++ ++} ++ ++static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr, ++ u64 eval, unsigned long esize) ++{ ++ struct kvm *kvm = its->dev->kvm; ++ ++ if (KVM_BUG_ON(esize != sizeof(eval), kvm)) ++ return -EINVAL; ++ ++ return kvm_write_guest_lock(kvm, eaddr, &eval, esize); ++} ++ + /* + * This struct provides an intermediate representation of the fields contained + * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC diff --git a/queue-6.1/kvm-arm64-vgic-its-clear-dte-when-mapd-unmaps-a-device.patch b/queue-6.1/kvm-arm64-vgic-its-clear-dte-when-mapd-unmaps-a-device.patch new file mode 100644 index 00000000000..80e611922b5 --- /dev/null +++ b/queue-6.1/kvm-arm64-vgic-its-clear-dte-when-mapd-unmaps-a-device.patch @@ -0,0 +1,62 @@ +From stable+bounces-98557-greg=kroah.com@vger.kernel.org Wed Dec 4 21:24:08 2024 +From: Jing Zhang +Date: Wed, 4 Dec 2024 12:23:56 -0800 +Subject: KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device +To: stable@vger.kernel.org +Cc: Marc Zyngier , Oliver Upton , Kunkun Jiang , Shusen Li , Jing Zhang +Message-ID: <20241204202357.2718096-2-jingzhangos@google.com> + +From: Kunkun Jiang + +commit e9649129d33dca561305fc590a7c4ba8c3e5675a upstream. + +vgic_its_save_device_tables will traverse its->device_list to +save DTE for each device. vgic_its_restore_device_tables will +traverse each entry of device table and check if it is valid. +Restore if valid. + +But when MAPD unmaps a device, it does not invalidate the +corresponding DTE. In the scenario of continuous saves +and restores, there may be a situation where a device's DTE +is not saved but is restored. This is unreasonable and may +cause restore to fail. This patch clears the corresponding +DTE when MAPD unmaps a device. + +Cc: stable@vger.kernel.org +Fixes: 57a9a117154c ("KVM: arm64: vgic-its: Device table save/restore") +Co-developed-by: Shusen Li +Signed-off-by: Shusen Li +Signed-off-by: Kunkun Jiang +[Jing: Update with entry write helper] +Signed-off-by: Jing Zhang +Link: https://lore.kernel.org/r/20241107214137.428439-5-jingzhangos@google.com +Signed-off-by: Oliver Upton +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/vgic/vgic-its.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/arch/arm64/kvm/vgic/vgic-its.c ++++ b/arch/arm64/kvm/vgic/vgic-its.c +@@ -1211,9 +1211,11 @@ static int vgic_its_cmd_handle_mapd(stru + bool valid = its_cmd_get_validbit(its_cmd); + u8 num_eventid_bits = its_cmd_get_size(its_cmd); + gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd); ++ int dte_esz = vgic_its_get_abi(its)->dte_esz; + struct its_device *device; ++ gpa_t gpa; + +- if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL)) ++ if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa)) + return E_ITS_MAPD_DEVICE_OOR; + + if (valid && num_eventid_bits > VITS_TYPER_IDBITS) +@@ -1234,7 +1236,7 @@ static int vgic_its_cmd_handle_mapd(stru + * is an error, so we are done in any case. + */ + if (!valid) +- return 0; ++ return vgic_its_write_entry_lock(its, gpa, 0, dte_esz); + + device = vgic_its_alloc_device(its, device_id, itt_addr, + num_eventid_bits); diff --git a/queue-6.1/kvm-arm64-vgic-its-clear-ite-when-discard-frees-an-ite.patch b/queue-6.1/kvm-arm64-vgic-its-clear-ite-when-discard-frees-an-ite.patch new file mode 100644 index 00000000000..7a6da1aea3d --- /dev/null +++ b/queue-6.1/kvm-arm64-vgic-its-clear-ite-when-discard-frees-an-ite.patch @@ -0,0 +1,53 @@ +From stable+bounces-98558-greg=kroah.com@vger.kernel.org Wed Dec 4 21:24:10 2024 +From: Jing Zhang +Date: Wed, 4 Dec 2024 12:23:57 -0800 +Subject: KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE +To: stable@vger.kernel.org +Cc: Marc Zyngier , Oliver Upton , Kunkun Jiang , Jing Zhang +Message-ID: <20241204202357.2718096-3-jingzhangos@google.com> + +From: Kunkun Jiang + +commit 7602ffd1d5e8927fadd5187cb4aed2fdc9c47143 upstream. + +When DISCARD frees an ITE, it does not invalidate the +corresponding ITE. In the scenario of continuous saves and +restores, there may be a situation where an ITE is not saved +but is restored. This is unreasonable and may cause restore +to fail. This patch clears the corresponding ITE when DISCARD +frees an ITE. + +Cc: stable@vger.kernel.org +Fixes: eff484e0298d ("KVM: arm64: vgic-its: ITT save and restore") +Signed-off-by: Kunkun Jiang +[Jing: Update with entry write helper] +Signed-off-by: Jing Zhang +Link: https://lore.kernel.org/r/20241107214137.428439-6-jingzhangos@google.com +Signed-off-by: Oliver Upton +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/vgic/vgic-its.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/arm64/kvm/vgic/vgic-its.c ++++ b/arch/arm64/kvm/vgic/vgic-its.c +@@ -855,6 +855,9 @@ static int vgic_its_cmd_handle_discard(s + + ite = find_ite(its, device_id, event_id); + if (ite && its_is_collection_mapped(ite->collection)) { ++ struct its_device *device = find_its_device(its, device_id); ++ int ite_esz = vgic_its_get_abi(its)->ite_esz; ++ gpa_t gpa = device->itt_addr + ite->event_id * ite_esz; + /* + * Though the spec talks about removing the pending state, we + * don't bother here since we clear the ITTE anyway and the +@@ -863,7 +866,8 @@ static int vgic_its_cmd_handle_discard(s + vgic_its_invalidate_cache(kvm); + + its_free_ite(kvm, ite); +- return 0; ++ ++ return vgic_its_write_entry_lock(its, gpa, 0, ite_esz); + } + + return E_ITS_DISCARD_UNMAPPED_INTERRUPT; diff --git a/queue-6.1/series b/queue-6.1/series index 67acdde650e..c0b250b2705 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -740,3 +740,7 @@ btrfs-fix-missing-snapshot-drew-unlock-when-root-is-.patch tracing-eprobe-fix-to-release-eprobe-when-failed-to-.patch revert-unicode-don-t-special-case-ignorable-code-poi.patch vfio-mlx5-align-the-page-tracking-max-message-size-w.patch +udf-fold-udf_getblk-into-udf_bread.patch +kvm-arm64-vgic-its-add-a-data-length-check-in-vgic_its_save_.patch +kvm-arm64-vgic-its-clear-dte-when-mapd-unmaps-a-device.patch +kvm-arm64-vgic-its-clear-ite-when-discard-frees-an-ite.patch diff --git a/queue-6.1/udf-fold-udf_getblk-into-udf_bread.patch b/queue-6.1/udf-fold-udf_getblk-into-udf_bread.patch new file mode 100644 index 00000000000..eea006d8e17 --- /dev/null +++ b/queue-6.1/udf-fold-udf_getblk-into-udf_bread.patch @@ -0,0 +1,90 @@ +From 32f123a3f34283f9c6446de87861696f0502b02e Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 18 Jan 2023 15:33:41 +0100 +Subject: udf: Fold udf_getblk() into udf_bread() + +From: Jan Kara + +commit 32f123a3f34283f9c6446de87861696f0502b02e upstream. + +udf_getblk() has a single call site. Fold it there. + +Signed-off-by: Jan Kara +[acsjakub: backport-adjusting changes + udf_getblk() has changed between 6.1 and the backported commit, namely + in commit 541e047b14c8 ("udf: Use udf_map_block() in udf_getblk()") + Backport using the form of udf_getblk present in 6.1., that means use + udf_get_block() instead of udf_map_block() and use dummy in buffer_new() + and buffer_mapped(). ] +Closes: https://syzkaller.appspot.com/bug?extid=a38e34ca637c224f4a79 +Signed-off-by: Jakub Acs +Signed-off-by: Greg Kroah-Hartman +--- + fs/udf/inode.c | 46 +++++++++++++++++++++------------------------- + 1 file changed, 21 insertions(+), 25 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -369,29 +369,6 @@ abort: + return err; + } + +-static struct buffer_head *udf_getblk(struct inode *inode, udf_pblk_t block, +- int create, int *err) +-{ +- struct buffer_head *bh; +- struct buffer_head dummy; +- +- dummy.b_state = 0; +- dummy.b_blocknr = -1000; +- *err = udf_get_block(inode, block, &dummy, create); +- if (!*err && buffer_mapped(&dummy)) { +- bh = sb_getblk(inode->i_sb, dummy.b_blocknr); +- if (buffer_new(&dummy)) { +- lock_buffer(bh); +- memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); +- set_buffer_uptodate(bh); +- unlock_buffer(bh); +- mark_buffer_dirty_inode(bh, inode); +- } +- return bh; +- } +- +- return NULL; +-} + + /* Extend the file with new blocks totaling 'new_block_bytes', + * return the number of extents added +@@ -1108,11 +1085,30 @@ struct buffer_head *udf_bread(struct ino + int create, int *err) + { + struct buffer_head *bh = NULL; ++ struct buffer_head dummy; ++ ++ dummy.b_state = 0; ++ dummy.b_blocknr = -1000; + +- bh = udf_getblk(inode, block, create, err); +- if (!bh) ++ *err = udf_get_block(inode, block, &dummy, create); ++ if (*err || !buffer_mapped(&dummy)) + return NULL; + ++ bh = sb_getblk(inode->i_sb, dummy.b_blocknr); ++ if (!bh) { ++ *err = -ENOMEM; ++ return NULL; ++ } ++ ++ if (buffer_new(&dummy)) { ++ lock_buffer(bh); ++ memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); ++ set_buffer_uptodate(bh); ++ unlock_buffer(bh); ++ mark_buffer_dirty_inode(bh, inode); ++ return bh; ++ } ++ + if (bh_read(bh, 0) >= 0) + return bh; +