]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Jan 2026 11:08:08 +0000 (12:08 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Jan 2026 11:08:08 +0000 (12:08 +0100)
added patches:
hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch
selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch

queue-6.18/hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch [new file with mode: 0644]
queue-6.18/selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch [new file with mode: 0644]
queue-6.18/series

diff --git a/queue-6.18/hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch b/queue-6.18/hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch
new file mode 100644 (file)
index 0000000..9668ea4
--- /dev/null
@@ -0,0 +1,55 @@
+From f28beb69c51517aec7067dfb2074e7c751542384 Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <bentiss@kernel.org>
+Date: Mon, 15 Dec 2025 12:57:21 +0100
+Subject: HID: usbhid: paper over wrong bNumDescriptor field
+
+From: Benjamin Tissoires <bentiss@kernel.org>
+
+commit f28beb69c51517aec7067dfb2074e7c751542384 upstream.
+
+Some faulty devices (ZWO EFWmini) have a wrong optional HID class
+descriptor count compared to the provided length.
+
+Given that we plainly ignore those optional descriptor, we can attempt
+to fix the provided number so we do not lock out those devices.
+
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/usbhid/hid-core.c |   17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -985,6 +985,7 @@ static int usbhid_parse(struct hid_devic
+       struct usb_device *dev = interface_to_usbdev (intf);
+       struct hid_descriptor *hdesc;
+       struct hid_class_descriptor *hcdesc;
++      __u8 fixed_opt_descriptors_size;
+       u32 quirks = 0;
+       unsigned int rsize = 0;
+       char *rdesc;
+@@ -1015,7 +1016,21 @@ static int usbhid_parse(struct hid_devic
+                             (hdesc->bNumDescriptors - 1) * sizeof(*hcdesc)) {
+               dbg_hid("hid descriptor invalid, bLen=%hhu bNum=%hhu\n",
+                       hdesc->bLength, hdesc->bNumDescriptors);
+-              return -EINVAL;
++
++              /*
++               * Some devices may expose a wrong number of descriptors compared
++               * to the provided length.
++               * However, we ignore the optional hid class descriptors entirely
++               * so we can safely recompute the proper field.
++               */
++              if (hdesc->bLength >= sizeof(*hdesc)) {
++                      fixed_opt_descriptors_size = hdesc->bLength - sizeof(*hdesc);
++
++                      hid_warn(intf, "fixing wrong optional hid class descriptors count\n");
++                      hdesc->bNumDescriptors = fixed_opt_descriptors_size / sizeof(*hcdesc) + 1;
++              } else {
++                      return -EINVAL;
++              }
+       }
+       hid->version = le16_to_cpu(hdesc->bcdHID);
diff --git a/queue-6.18/selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch b/queue-6.18/selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch
new file mode 100644 (file)
index 0000000..5473b24
--- /dev/null
@@ -0,0 +1,175 @@
+From 4f8543b5f20f851cedbb23f8eade159871d84e2a Mon Sep 17 00:00:00 2001
+From: Yonghong Song <yonghong.song@linux.dev>
+Date: Mon, 13 Oct 2025 22:16:39 -0700
+Subject: selftests/bpf: Fix selftest verif_scale_strobemeta failure with llvm22
+
+From: Yonghong Song <yonghong.song@linux.dev>
+
+commit 4f8543b5f20f851cedbb23f8eade159871d84e2a upstream.
+
+With latest llvm22, I hit the verif_scale_strobemeta selftest failure
+below:
+  $ ./test_progs -n 618
+  libbpf: prog 'on_event': BPF program load failed: -E2BIG
+  libbpf: prog 'on_event': -- BEGIN PROG LOAD LOG --
+  BPF program is too large. Processed 1000001 insn
+  verification time 7019091 usec
+  stack depth 488
+  processed 1000001 insns (limit 1000000) max_states_per_insn 28 total_states 33927 peak_states 12813 mark_read 0
+  -- END PROG LOAD LOG --
+  libbpf: prog 'on_event': failed to load: -E2BIG
+  libbpf: failed to load object 'strobemeta.bpf.o'
+  scale_test:FAIL:expect_success unexpected error: -7 (errno 7)
+  #618     verif_scale_strobemeta:FAIL
+
+But if I increase the verificaiton insn limit from 1M to 10M, the above
+test_progs run actually will succeed. The below is the result from veristat:
+  $ ./veristat strobemeta.bpf.o
+  Processing 'strobemeta.bpf.o'...
+  File              Program   Verdict  Duration (us)    Insns  States  Program size  Jited size
+  ----------------  --------  -------  -------------  -------  ------  ------------  ----------
+  strobemeta.bpf.o  on_event  success       90250893  9777685  358230         15954       80794
+  ----------------  --------  -------  -------------  -------  ------  ------------  ----------
+  Done. Processed 1 files, 0 programs. Skipped 1 files, 0 programs.
+
+Further debugging shows the llvm commit [1] is responsible for the verificaiton
+failure as it tries to convert certain switch statement to if-condition. Such
+change may cause different transformation compared to original switch statement.
+
+In bpf program strobemeta.c case, the initial llvm ir for read_int_var() function is
+  define internal void @read_int_var(ptr noundef %0, i64 noundef %1, ptr noundef %2,
+      ptr noundef %3, ptr noundef %4) #2 !dbg !535 {
+    %6 = alloca ptr, align 8
+    %7 = alloca i64, align 8
+    %8 = alloca ptr, align 8
+    %9 = alloca ptr, align 8
+    %10 = alloca ptr, align 8
+    %11 = alloca ptr, align 8
+    %12 = alloca i32, align 4
+    ...
+    %20 = icmp ne ptr %19, null, !dbg !561
+    br i1 %20, label %22, label %21, !dbg !562
+
+  21:                                               ; preds = %5
+    store i32 1, ptr %12, align 4
+    br label %48, !dbg !563
+
+  22:
+    %23 = load ptr, ptr %9, align 8, !dbg !564
+    ...
+
+  47:                                               ; preds = %38, %22
+    store i32 0, ptr %12, align 4, !dbg !588
+    br label %48, !dbg !588
+
+  48:                                               ; preds = %47, %21
+    call void @llvm.lifetime.end.p0(ptr %11) #4, !dbg !588
+    %49 = load i32, ptr %12, align 4
+    switch i32 %49, label %51 [
+      i32 0, label %50
+      i32 1, label %50
+    ]
+
+  50:                                               ; preds = %48, %48
+    ret void, !dbg !589
+
+  51:                                               ; preds = %48
+    unreachable
+  }
+
+Note that the above 'switch' statement is added by clang frontend.
+Without [1], the switch statement will survive until SelectionDag,
+so the switch statement acts like a 'barrier' and prevents some
+transformation involved with both 'before' and 'after' the switch statement.
+
+But with [1], the switch statement will be removed during middle end
+optimization and later middle end passes (esp. after inlining) have more
+freedom to reorder the code.
+
+The following is the related source code:
+
+  static void *calc_location(struct strobe_value_loc *loc, void *tls_base):
+        bpf_probe_read_user(&tls_ptr, sizeof(void *), dtv);
+        /* if pointer has (void *)-1 value, then TLS wasn't initialized yet */
+        return tls_ptr && tls_ptr != (void *)-1
+                ? tls_ptr + tls_index.offset
+                : NULL;
+
+  In read_int_var() func, we have:
+        void *location = calc_location(&cfg->int_locs[idx], tls_base);
+        if (!location)
+                return;
+
+        bpf_probe_read_user(value, sizeof(struct strobe_value_generic), location);
+        ...
+
+The static func calc_location() is called inside read_int_var(). The asm code
+without [1]:
+     77: .123....89 (85) call bpf_probe_read_user#112
+     78: ........89 (79) r1 = *(u64 *)(r10 -368)
+     79: .1......89 (79) r2 = *(u64 *)(r10 -8)
+     80: .12.....89 (bf) r3 = r2
+     81: .123....89 (0f) r3 += r1
+     82: ..23....89 (07) r2 += 1
+     83: ..23....89 (79) r4 = *(u64 *)(r10 -464)
+     84: ..234...89 (a5) if r2 < 0x2 goto pc+13
+     85: ...34...89 (15) if r3 == 0x0 goto pc+12
+     86: ...3....89 (bf) r1 = r10
+     87: .1.3....89 (07) r1 += -400
+     88: .1.3....89 (b4) w2 = 16
+In this case, 'r2 < 0x2' and 'r3 == 0x0' go to null 'locaiton' place,
+so the verifier actually prefers to do verification first at 'r1 = r10' etc.
+
+The asm code with [1]:
+    119: .123....89 (85) call bpf_probe_read_user#112
+    120: ........89 (79) r1 = *(u64 *)(r10 -368)
+    121: .1......89 (79) r2 = *(u64 *)(r10 -8)
+    122: .12.....89 (bf) r3 = r2
+    123: .123....89 (0f) r3 += r1
+    124: ..23....89 (07) r2 += -1
+    125: ..23....89 (a5) if r2 < 0xfffffffe goto pc+6
+    126: ........89 (05) goto pc+17
+    ...
+    144: ........89 (b4) w1 = 0
+    145: .1......89 (6b) *(u16 *)(r8 +80) = r1
+In this case, if 'r2 < 0xfffffffe' is true, the control will go to
+non-null 'location' branch, so 'goto pc+17' will actually go to
+null 'location' branch. This seems causing tremendous amount of
+verificaiton state.
+
+To fix the issue, rewrite the following code
+  return tls_ptr && tls_ptr != (void *)-1
+                ? tls_ptr + tls_index.offset
+                : NULL;
+to if/then statement and hopefully these explicit if/then statements
+are sticky during middle-end optimizations.
+
+Test with llvm20 and llvm21 as well and all strobemeta related selftests
+are passed.
+
+  [1] https://github.com/llvm/llvm-project/pull/161000
+
+Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
+Link: https://lore.kernel.org/r/20251014051639.1996331-1-yonghong.song@linux.dev
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/bpf/progs/strobemeta.h |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/tools/testing/selftests/bpf/progs/strobemeta.h
++++ b/tools/testing/selftests/bpf/progs/strobemeta.h
+@@ -330,9 +330,9 @@ static void *calc_location(struct strobe
+       }
+       bpf_probe_read_user(&tls_ptr, sizeof(void *), dtv);
+       /* if pointer has (void *)-1 value, then TLS wasn't initialized yet */
+-      return tls_ptr && tls_ptr != (void *)-1
+-              ? tls_ptr + tls_index.offset
+-              : NULL;
++      if (!tls_ptr || tls_ptr == (void *)-1)
++              return NULL;
++      return tls_ptr + tls_index.offset;
+ }
+ #ifdef SUBPROGS
index 2f0c0dac40c0943d3080100743fff1d96d9216fa..f8c035dfa10df7926769fec4fb225c481ffbcf58 100644 (file)
@@ -86,3 +86,5 @@ i2c-qcom-geni-make-sure-i2c-hub-controllers-can-t-us.patch
 i2c-imx-lpi2c-change-to-pio-mode-in-system-wide-susp.patch
 sched-deadline-avoid-double-update_rq_clock.patch
 sched-deadline-has-dynamic-priority.patch
+hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch
+selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch