]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jun 2023 18:41:18 +0000 (20:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Jun 2023 18:41:18 +0000 (20:41 +0200)
added patches:
arm64-efi-use-smbios-processor-version-to-key-off-ampere-quirk.patch
tls-rx-strp-don-t-use-gfp_kernel-in-softirq-context.patch
xfs-verify-buffer-contents-when-we-skip-log-replay.patch

queue-6.1/arm64-efi-use-smbios-processor-version-to-key-off-ampere-quirk.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/tls-rx-strp-don-t-use-gfp_kernel-in-softirq-context.patch [new file with mode: 0644]
queue-6.1/xfs-verify-buffer-contents-when-we-skip-log-replay.patch [new file with mode: 0644]

diff --git a/queue-6.1/arm64-efi-use-smbios-processor-version-to-key-off-ampere-quirk.patch b/queue-6.1/arm64-efi-use-smbios-processor-version-to-key-off-ampere-quirk.patch
new file mode 100644 (file)
index 0000000..84cb83a
--- /dev/null
@@ -0,0 +1,173 @@
+From eb684408f3ea4856639675d6465f0024e498e4b1 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Tue, 28 Feb 2023 17:00:49 +0100
+Subject: arm64: efi: Use SMBIOS processor version to key off Ampere quirk
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit eb684408f3ea4856639675d6465f0024e498e4b1 upstream.
+
+Instead of using the SMBIOS type 1 record 'family' field, which is often
+modified by OEMs, use the type 4 'processor ID' and 'processor version'
+fields, which are set to a small set of probe-able values on all known
+Ampere EFI systems in the field.
+
+Fixes: 550b33cfd4452968 ("arm64: efi: Force the use of ...")
+Tested-by: Andrea Righi <andrea.righi@canonical.com>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/firmware/efi/libstub/arm64-stub.c |   39 ++++++++++++++++++++++------
+ drivers/firmware/efi/libstub/efistub.h    |   41 +++++++++++++++++++++++++++---
+ drivers/firmware/efi/libstub/smbios.c     |   13 ++++++++-
+ 3 files changed, 80 insertions(+), 13 deletions(-)
+
+--- a/drivers/firmware/efi/libstub/arm64-stub.c
++++ b/drivers/firmware/efi/libstub/arm64-stub.c
+@@ -17,20 +17,43 @@
+ static bool system_needs_vamap(void)
+ {
+-      const u8 *type1_family = efi_get_smbios_string(1, family);
++      const struct efi_smbios_type4_record *record;
++      const u32 __aligned(1) *socid;
++      const u8 *version;
+       /*
+        * Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
+-       * SetVirtualAddressMap() has not been called prior.
++       * SetVirtualAddressMap() has not been called prior. Most Altra systems
++       * can be identified by the SMCCC soc ID, which is conveniently exposed
++       * via the type 4 SMBIOS records. Otherwise, test the processor version
++       * field. eMAG systems all appear to have the processor version field
++       * set to "eMAG".
+        */
+-      if (!type1_family || (
+-          strcmp(type1_family, "eMAG") &&
+-          strcmp(type1_family, "Altra") &&
+-          strcmp(type1_family, "Altra Max")))
++      record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
++      if (!record)
+               return false;
+-      efi_warn("Working around broken SetVirtualAddressMap()\n");
+-      return true;
++      socid = (u32 *)record->processor_id;
++      switch (*socid & 0xffff000f) {
++              static char const altra[] = "Ampere(TM) Altra(TM) Processor";
++              static char const emag[] = "eMAG";
++
++      default:
++              version = efi_get_smbios_string(&record->header, 4,
++                                              processor_version);
++              if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
++                               strncmp(version, emag, sizeof(emag) - 1)))
++                      break;
++
++              fallthrough;
++
++      case 0x0a160001:        // Altra
++      case 0x0a160002:        // Altra Max
++              efi_warn("Working around broken SetVirtualAddressMap()\n");
++              return true;
++      }
++
++      return false;
+ }
+ efi_status_t check_platform_features(void)
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -983,6 +983,8 @@ struct efi_smbios_record {
+       u16     handle;
+ };
++const struct efi_smbios_record *efi_get_smbios_record(u8 type);
++
+ struct efi_smbios_type1_record {
+       struct efi_smbios_record        header;
+@@ -996,13 +998,46 @@ struct efi_smbios_type1_record {
+       u8                              family;
+ };
+-#define efi_get_smbios_string(__type, __name) ({                      \
++struct efi_smbios_type4_record {
++      struct efi_smbios_record        header;
++
++      u8                              socket;
++      u8                              processor_type;
++      u8                              processor_family;
++      u8                              processor_manufacturer;
++      u8                              processor_id[8];
++      u8                              processor_version;
++      u8                              voltage;
++      u16                             external_clock;
++      u16                             max_speed;
++      u16                             current_speed;
++      u8                              status;
++      u8                              processor_upgrade;
++      u16                             l1_cache_handle;
++      u16                             l2_cache_handle;
++      u16                             l3_cache_handle;
++      u8                              serial_number;
++      u8                              asset_tag;
++      u8                              part_number;
++      u8                              core_count;
++      u8                              enabled_core_count;
++      u8                              thread_count;
++      u16                             processor_characteristics;
++      u16                             processor_family2;
++      u16                             core_count2;
++      u16                             enabled_core_count2;
++      u16                             thread_count2;
++      u16                             thread_enabled;
++};
++
++#define efi_get_smbios_string(__record, __type, __name) ({            \
+       int size = sizeof(struct efi_smbios_type ## __type ## _record); \
+       int off = offsetof(struct efi_smbios_type ## __type ## _record, \
+                          __name);                                     \
+-      __efi_get_smbios_string(__type, off, size);                     \
++      __efi_get_smbios_string((__record), __type, off, size);         \
+ })
+-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
++const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
++                                u8 type, int offset, int recsize);
+ #endif
+--- a/drivers/firmware/efi/libstub/smbios.c
++++ b/drivers/firmware/efi/libstub/smbios.c
+@@ -22,19 +22,28 @@ struct efi_smbios_protocol {
+       u8 minor_version;
+ };
+-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize)
++const struct efi_smbios_record *efi_get_smbios_record(u8 type)
+ {
+       struct efi_smbios_record *record;
+       efi_smbios_protocol_t *smbios;
+       efi_status_t status;
+       u16 handle = 0xfffe;
+-      const u8 *strtable;
+       status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL,
+                            (void **)&smbios) ?:
+                efi_call_proto(smbios, get_next, &handle, &type, &record, NULL);
+       if (status != EFI_SUCCESS)
+               return NULL;
++      return record;
++}
++
++const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
++                                u8 type, int offset, int recsize)
++{
++      const u8 *strtable;
++
++      if (!record)
++              return NULL;
+       strtable = (u8 *)record + record->length;
+       for (int i = 1; i < ((u8 *)record)[offset]; i++) {
index e6914a0216cdcb6b0e99a8265b9494dab49fffb2..3d1d8f111d3ca9c8a58ceae91327696a74f252fc 100644 (file)
@@ -225,3 +225,6 @@ regmap-account-for-register-length-when-chunking.patch
 tpm-tpm_tis-request-threaded-interrupt-handler.patch
 iommu-amd-pgtbl_v2-fix-domain-max-address.patch
 drm-amd-display-have-payload-properly-created-after-resume.patch
+xfs-verify-buffer-contents-when-we-skip-log-replay.patch
+tls-rx-strp-don-t-use-gfp_kernel-in-softirq-context.patch
+arm64-efi-use-smbios-processor-version-to-key-off-ampere-quirk.patch
diff --git a/queue-6.1/tls-rx-strp-don-t-use-gfp_kernel-in-softirq-context.patch b/queue-6.1/tls-rx-strp-don-t-use-gfp_kernel-in-softirq-context.patch
new file mode 100644 (file)
index 0000000..21f7235
--- /dev/null
@@ -0,0 +1,45 @@
+From 74836ec828fe17b63f2006fdbf53311d691396bf Mon Sep 17 00:00:00 2001
+From: Jakub Kicinski <kuba@kernel.org>
+Date: Tue, 16 May 2023 18:50:42 -0700
+Subject: tls: rx: strp: don't use GFP_KERNEL in softirq context
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+commit 74836ec828fe17b63f2006fdbf53311d691396bf upstream.
+
+When receive buffer is small, or the TCP rx queue looks too
+complicated to bother using it directly - we allocate a new
+skb and copy data into it.
+
+We already use sk->sk_allocation... but nothing actually
+sets it to GFP_ATOMIC on the ->sk_data_ready() path.
+
+Users of HW offload are far more likely to experience problems
+due to scheduling while atomic. "Copy mode" is very rarely
+triggered with SW crypto.
+
+Fixes: 84c61fe1a75b ("tls: rx: do not use the standard strparser")
+Tested-by: Shai Amiram <samiram@nvidia.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tls/tls_sw.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -2289,8 +2289,12 @@ static void tls_data_ready(struct sock *
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+       struct sk_psock *psock;
++      gfp_t alloc_save;
++      alloc_save = sk->sk_allocation;
++      sk->sk_allocation = GFP_ATOMIC;
+       tls_strp_data_ready(&ctx->strp);
++      sk->sk_allocation = alloc_save;
+       psock = sk_psock_get(sk);
+       if (psock) {
diff --git a/queue-6.1/xfs-verify-buffer-contents-when-we-skip-log-replay.patch b/queue-6.1/xfs-verify-buffer-contents-when-we-skip-log-replay.patch
new file mode 100644 (file)
index 0000000..21b32f5
--- /dev/null
@@ -0,0 +1,113 @@
+From 22ed903eee23a5b174e240f1cdfa9acf393a5210 Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <djwong@kernel.org>
+Date: Wed, 12 Apr 2023 15:49:23 +1000
+Subject: xfs: verify buffer contents when we skip log replay
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit 22ed903eee23a5b174e240f1cdfa9acf393a5210 upstream.
+
+syzbot detected a crash during log recovery:
+
+XFS (loop0): Mounting V5 Filesystem bfdc47fc-10d8-4eed-a562-11a831b3f791
+XFS (loop0): Torn write (CRC failure) detected at log block 0x180. Truncating head block from 0x200.
+XFS (loop0): Starting recovery (logdev: internal)
+==================================================================
+BUG: KASAN: slab-out-of-bounds in xfs_btree_lookup_get_block+0x15c/0x6d0 fs/xfs/libxfs/xfs_btree.c:1813
+Read of size 8 at addr ffff88807e89f258 by task syz-executor132/5074
+
+CPU: 0 PID: 5074 Comm: syz-executor132 Not tainted 6.2.0-rc1-syzkaller #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x1b1/0x290 lib/dump_stack.c:106
+ print_address_description+0x74/0x340 mm/kasan/report.c:306
+ print_report+0x107/0x1f0 mm/kasan/report.c:417
+ kasan_report+0xcd/0x100 mm/kasan/report.c:517
+ xfs_btree_lookup_get_block+0x15c/0x6d0 fs/xfs/libxfs/xfs_btree.c:1813
+ xfs_btree_lookup+0x346/0x12c0 fs/xfs/libxfs/xfs_btree.c:1913
+ xfs_btree_simple_query_range+0xde/0x6a0 fs/xfs/libxfs/xfs_btree.c:4713
+ xfs_btree_query_range+0x2db/0x380 fs/xfs/libxfs/xfs_btree.c:4953
+ xfs_refcount_recover_cow_leftovers+0x2d1/0xa60 fs/xfs/libxfs/xfs_refcount.c:1946
+ xfs_reflink_recover_cow+0xab/0x1b0 fs/xfs/xfs_reflink.c:930
+ xlog_recover_finish+0x824/0x920 fs/xfs/xfs_log_recover.c:3493
+ xfs_log_mount_finish+0x1ec/0x3d0 fs/xfs/xfs_log.c:829
+ xfs_mountfs+0x146a/0x1ef0 fs/xfs/xfs_mount.c:933
+ xfs_fs_fill_super+0xf95/0x11f0 fs/xfs/xfs_super.c:1666
+ get_tree_bdev+0x400/0x620 fs/super.c:1282
+ vfs_get_tree+0x88/0x270 fs/super.c:1489
+ do_new_mount+0x289/0xad0 fs/namespace.c:3145
+ do_mount fs/namespace.c:3488 [inline]
+ __do_sys_mount fs/namespace.c:3697 [inline]
+ __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+RIP: 0033:0x7f89fa3f4aca
+Code: 83 c4 08 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007fffd5fb5ef8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
+RAX: ffffffffffffffda RBX: 00646975756f6e2c RCX: 00007f89fa3f4aca
+RDX: 0000000020000100 RSI: 0000000020009640 RDI: 00007fffd5fb5f10
+RBP: 00007fffd5fb5f10 R08: 00007fffd5fb5f50 R09: 000000000000970d
+R10: 0000000000200800 R11: 0000000000000206 R12: 0000000000000004
+R13: 0000555556c6b2c0 R14: 0000000000200800 R15: 00007fffd5fb5f50
+ </TASK>
+
+The fuzzed image contains an AGF with an obviously garbage
+agf_refcount_level value of 32, and a dirty log with a buffer log item
+for that AGF.  The ondisk AGF has a higher LSN than the recovered log
+item.  xlog_recover_buf_commit_pass2 reads the buffer, compares the
+LSNs, and decides to skip replay because the ondisk buffer appears to be
+newer.
+
+Unfortunately, the ondisk buffer is corrupt, but recovery just read the
+buffer with no buffer ops specified:
+
+       error = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno,
+                       buf_f->blf_len, buf_flags, &bp, NULL);
+
+Skipping the buffer leaves its contents in memory unverified.  This sets
+us up for a kernel crash because xfs_refcount_recover_cow_leftovers
+reads the buffer (which is still around in XBF_DONE state, so no read
+verification) and creates a refcountbt cursor of height 32.  This is
+impossible so we run off the end of the cursor object and crash.
+
+Fix this by invoking the verifier on all skipped buffers and aborting
+log recovery if the ondisk buffer is corrupt.  It might be smarter to
+force replay the log item atop the buffer and then see if it'll pass the
+write verifier (like ext4 does) but for now let's go with the
+conservative option where we stop immediately.
+
+Link: https://syzkaller.appspot.com/bug?extid=7e9494b8b399902e994e
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Reported-by: Danila Chernetsov <listdansp@mail.ru>
+Link: https://lore.kernel.org/linux-xfs/20230601164439.15404-1-listdansp@mail.ru
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_buf_item_recover.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/fs/xfs/xfs_buf_item_recover.c
++++ b/fs/xfs/xfs_buf_item_recover.c
+@@ -943,6 +943,16 @@ xlog_recover_buf_commit_pass2(
+       if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
+               trace_xfs_log_recover_buf_skip(log, buf_f);
+               xlog_recover_validate_buf_type(mp, bp, buf_f, NULLCOMMITLSN);
++
++              /*
++               * We're skipping replay of this buffer log item due to the log
++               * item LSN being behind the ondisk buffer.  Verify the buffer
++               * contents since we aren't going to run the write verifier.
++               */
++              if (bp->b_ops) {
++                      bp->b_ops->verify_read(bp);
++                      error = bp->b_error;
++              }
+               goto out_release;
+       }