From: Greg Kroah-Hartman Date: Tue, 20 Jan 2026 11:08:08 +0000 (+0100) Subject: 6.18-stable patches X-Git-Tag: v6.12.67~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1cbb618fda2053a09f6815b49c171cdd3833d77e;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch --- 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 index 0000000000..9668ea493c --- /dev/null +++ b/queue-6.18/hid-usbhid-paper-over-wrong-bnumdescriptor-field.patch @@ -0,0 +1,55 @@ +From f28beb69c51517aec7067dfb2074e7c751542384 Mon Sep 17 00:00:00 2001 +From: Benjamin Tissoires +Date: Mon, 15 Dec 2025 12:57:21 +0100 +Subject: HID: usbhid: paper over wrong bNumDescriptor field + +From: Benjamin Tissoires + +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 +Cc: Salvatore Bonaccorso +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..5473b24e6d --- /dev/null +++ b/queue-6.18/selftests-bpf-fix-selftest-verif_scale_strobemeta-failure-with-llvm22.patch @@ -0,0 +1,175 @@ +From 4f8543b5f20f851cedbb23f8eade159871d84e2a Mon Sep 17 00:00:00 2001 +From: Yonghong Song +Date: Mon, 13 Oct 2025 22:16:39 -0700 +Subject: selftests/bpf: Fix selftest verif_scale_strobemeta failure with llvm22 + +From: Yonghong Song + +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 +Link: https://lore.kernel.org/r/20251014051639.1996331-1-yonghong.song@linux.dev +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-6.18/series b/queue-6.18/series index 2f0c0dac40..f8c035dfa1 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -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