From: Greg Kroah-Hartman Date: Fri, 18 Oct 2024 08:28:21 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.10.228~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2937068ee09c126d2c44529ef44292668af22c78;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: arm64-probes-fix-simulate_ldr-_literal.patch arm64-probes-remove-broken-ldr-literal-uprobe-support.patch fat-fix-uninitialized-variable.patch mm-swapfile-skip-hugetlb-pages-for-unuse_vma.patch pci-add-function-0-dma-alias-quirk-for-glenfly-arise-chip.patch posix-clock-fix-missing-timespec64-check-in-pc_clock_settime.patch tracing-kprobes-fix-symbol-counting-logic-by-looking-at-modules-as-well.patch tracing-kprobes-return-eaddrnotavail-when-func-matches-several-symbols.patch --- diff --git a/queue-5.4/arm64-probes-fix-simulate_ldr-_literal.patch b/queue-5.4/arm64-probes-fix-simulate_ldr-_literal.patch new file mode 100644 index 00000000000..bb6fc8bbb68 --- /dev/null +++ b/queue-5.4/arm64-probes-fix-simulate_ldr-_literal.patch @@ -0,0 +1,79 @@ +From 50f813e57601c22b6f26ced3193b9b94d70a2640 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Tue, 8 Oct 2024 16:58:47 +0100 +Subject: arm64: probes: Fix simulate_ldr*_literal() + +From: Mark Rutland + +commit 50f813e57601c22b6f26ced3193b9b94d70a2640 upstream. + +The simulate_ldr_literal() code always loads a 64-bit quantity, and when +simulating a 32-bit load into a 'W' register, it discards the most +significant 32 bits. For big-endian kernels this means that the relevant +bits are discarded, and the value returned is the the subsequent 32 bits +in memory (i.e. the value at addr + 4). + +Additionally, simulate_ldr_literal() and simulate_ldrsw_literal() use a +plain C load, which the compiler may tear or elide (e.g. if the target +is the zero register). Today this doesn't happen to matter, but it may +matter in future if trampoline code uses a LDR (literal) or LDRSW +(literal). + +Update simulate_ldr_literal() and simulate_ldrsw_literal() to use an +appropriately-sized READ_ONCE() to perform the access, which avoids +these problems. + +Fixes: 39a67d49ba35 ("arm64: kprobes instruction simulation support") +Cc: stable@vger.kernel.org +Signed-off-by: Mark Rutland +Cc: Catalin Marinas +Cc: Will Deacon +Link: https://lore.kernel.org/r/20241008155851.801546-3-mark.rutland@arm.com +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/probes/simulate-insn.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +--- a/arch/arm64/kernel/probes/simulate-insn.c ++++ b/arch/arm64/kernel/probes/simulate-insn.c +@@ -170,17 +170,15 @@ simulate_tbz_tbnz(u32 opcode, long addr, + void __kprobes + simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) + { +- u64 *load_addr; ++ unsigned long load_addr; + int xn = opcode & 0x1f; +- int disp; + +- disp = ldr_displacement(opcode); +- load_addr = (u64 *) (addr + disp); ++ load_addr = addr + ldr_displacement(opcode); + + if (opcode & (1 << 30)) /* x0-x30 */ +- set_x_reg(regs, xn, *load_addr); ++ set_x_reg(regs, xn, READ_ONCE(*(u64 *)load_addr)); + else /* w0-w30 */ +- set_w_reg(regs, xn, *load_addr); ++ set_w_reg(regs, xn, READ_ONCE(*(u32 *)load_addr)); + + instruction_pointer_set(regs, instruction_pointer(regs) + 4); + } +@@ -188,14 +186,12 @@ simulate_ldr_literal(u32 opcode, long ad + void __kprobes + simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs) + { +- s32 *load_addr; ++ unsigned long load_addr; + int xn = opcode & 0x1f; +- int disp; + +- disp = ldr_displacement(opcode); +- load_addr = (s32 *) (addr + disp); ++ load_addr = addr + ldr_displacement(opcode); + +- set_x_reg(regs, xn, *load_addr); ++ set_x_reg(regs, xn, READ_ONCE(*(s32 *)load_addr)); + + instruction_pointer_set(regs, instruction_pointer(regs) + 4); + } diff --git a/queue-5.4/arm64-probes-remove-broken-ldr-literal-uprobe-support.patch b/queue-5.4/arm64-probes-remove-broken-ldr-literal-uprobe-support.patch new file mode 100644 index 00000000000..e59f1d25c4f --- /dev/null +++ b/queue-5.4/arm64-probes-remove-broken-ldr-literal-uprobe-support.patch @@ -0,0 +1,121 @@ +From acc450aa07099d071b18174c22a1119c57da8227 Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Tue, 8 Oct 2024 16:58:46 +0100 +Subject: arm64: probes: Remove broken LDR (literal) uprobe support + +From: Mark Rutland + +commit acc450aa07099d071b18174c22a1119c57da8227 upstream. + +The simulate_ldr_literal() and simulate_ldrsw_literal() functions are +unsafe to use for uprobes. Both functions were originally written for +use with kprobes, and access memory with plain C accesses. When uprobes +was added, these were reused unmodified even though they cannot safely +access user memory. + +There are three key problems: + +1) The plain C accesses do not have corresponding extable entries, and + thus if they encounter a fault the kernel will treat these as + unintentional accesses to user memory, resulting in a BUG() which + will kill the kernel thread, and likely lead to further issues (e.g. + lockup or panic()). + +2) The plain C accesses are subject to HW PAN and SW PAN, and so when + either is in use, any attempt to simulate an access to user memory + will fault. Thus neither simulate_ldr_literal() nor + simulate_ldrsw_literal() can do anything useful when simulating a + user instruction on any system with HW PAN or SW PAN. + +3) The plain C accesses are privileged, as they run in kernel context, + and in practice can access a small range of kernel virtual addresses. + The instructions they simulate have a range of +/-1MiB, and since the + simulated instructions must itself be a user instructions in the + TTBR0 address range, these can address the final 1MiB of the TTBR1 + acddress range by wrapping downwards from an address in the first + 1MiB of the TTBR0 address range. + + In contemporary kernels the last 8MiB of TTBR1 address range is + reserved, and accesses to this will always fault, meaning this is no + worse than (1). + + Historically, it was theoretically possible for the linear map or + vmemmap to spill into the final 8MiB of the TTBR1 address range, but + in practice this is extremely unlikely to occur as this would + require either: + + * Having enough physical memory to fill the entire linear map all the + way to the final 1MiB of the TTBR1 address range. + + * Getting unlucky with KASLR randomization of the linear map such + that the populated region happens to overlap with the last 1MiB of + the TTBR address range. + + ... and in either case if we were to spill into the final page there + would be larger problems as the final page would alias with error + pointers. + +Practically speaking, (1) and (2) are the big issues. Given there have +been no reports of problems since the broken code was introduced, it +appears that no-one is relying on probing these instructions with +uprobes. + +Avoid these issues by not allowing uprobes on LDR (literal) and LDRSW +(literal), limiting the use of simulate_ldr_literal() and +simulate_ldrsw_literal() to kprobes. Attempts to place uprobes on LDR +(literal) and LDRSW (literal) will be rejected as +arm_probe_decode_insn() will return INSN_REJECTED. In future we can +consider introducing working uprobes support for these instructions, but +this will require more significant work. + +Fixes: 9842ceae9fa8 ("arm64: Add uprobe support") +Cc: stable@vger.kernel.org +Signed-off-by: Mark Rutland +Cc: Catalin Marinas +Cc: Will Deacon +Link: https://lore.kernel.org/r/20241008155851.801546-2-mark.rutland@arm.com +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kernel/probes/decode-insn.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/arch/arm64/kernel/probes/decode-insn.c ++++ b/arch/arm64/kernel/probes/decode-insn.c +@@ -96,10 +96,6 @@ arm_probe_decode_insn(probe_opcode_t ins + aarch64_insn_is_blr(insn) || + aarch64_insn_is_ret(insn)) { + api->handler = simulate_br_blr_ret; +- } else if (aarch64_insn_is_ldr_lit(insn)) { +- api->handler = simulate_ldr_literal; +- } else if (aarch64_insn_is_ldrsw_lit(insn)) { +- api->handler = simulate_ldrsw_literal; + } else { + /* + * Instruction cannot be stepped out-of-line and we don't +@@ -137,6 +133,17 @@ arm_kprobe_decode_insn(kprobe_opcode_t * + probe_opcode_t insn = le32_to_cpu(*addr); + probe_opcode_t *scan_end = NULL; + unsigned long size = 0, offset = 0; ++ struct arch_probe_insn *api = &asi->api; ++ ++ if (aarch64_insn_is_ldr_lit(insn)) { ++ api->handler = simulate_ldr_literal; ++ decoded = INSN_GOOD_NO_SLOT; ++ } else if (aarch64_insn_is_ldrsw_lit(insn)) { ++ api->handler = simulate_ldrsw_literal; ++ decoded = INSN_GOOD_NO_SLOT; ++ } else { ++ decoded = arm_probe_decode_insn(insn, &asi->api); ++ } + + /* + * If there's a symbol defined in front of and near enough to +@@ -154,7 +161,6 @@ arm_kprobe_decode_insn(kprobe_opcode_t * + else + scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; + } +- decoded = arm_probe_decode_insn(insn, &asi->api); + + if (decoded != INSN_REJECTED && scan_end) + if (is_probed_address_atomic(addr - 1, scan_end)) diff --git a/queue-5.4/fat-fix-uninitialized-variable.patch b/queue-5.4/fat-fix-uninitialized-variable.patch new file mode 100644 index 00000000000..a6fb448b2c4 --- /dev/null +++ b/queue-5.4/fat-fix-uninitialized-variable.patch @@ -0,0 +1,36 @@ +From 963a7f4d3b90ee195b895ca06b95757fcba02d1a Mon Sep 17 00:00:00 2001 +From: OGAWA Hirofumi +Date: Fri, 4 Oct 2024 15:03:49 +0900 +Subject: fat: fix uninitialized variable + +From: OGAWA Hirofumi + +commit 963a7f4d3b90ee195b895ca06b95757fcba02d1a upstream. + +syszbot produced this with a corrupted fs image. In theory, however an IO +error would trigger this also. + +This affects just an error report, so should not be a serious error. + +Link: https://lkml.kernel.org/r/87r08wjsnh.fsf@mail.parknet.co.jp +Link: https://lkml.kernel.org/r/66ff2c95.050a0220.49194.03e9.GAE@google.com +Signed-off-by: OGAWA Hirofumi +Reported-by: syzbot+ef0d7bc412553291aa86@syzkaller.appspotmail.com +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/fat/namei_vfat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fat/namei_vfat.c ++++ b/fs/fat/namei_vfat.c +@@ -1019,7 +1019,7 @@ error_inode: + if (corrupt < 0) { + fat_fs_error(new_dir->i_sb, + "%s: Filesystem corrupted (i_pos %lld)", +- __func__, sinfo.i_pos); ++ __func__, new_i_pos); + } + goto out; + } diff --git a/queue-5.4/mm-swapfile-skip-hugetlb-pages-for-unuse_vma.patch b/queue-5.4/mm-swapfile-skip-hugetlb-pages-for-unuse_vma.patch new file mode 100644 index 00000000000..0702c9c55c2 --- /dev/null +++ b/queue-5.4/mm-swapfile-skip-hugetlb-pages-for-unuse_vma.patch @@ -0,0 +1,46 @@ +From 7528c4fb1237512ee18049f852f014eba80bbe8d Mon Sep 17 00:00:00 2001 +From: Liu Shixin +Date: Tue, 15 Oct 2024 09:45:21 +0800 +Subject: mm/swapfile: skip HugeTLB pages for unuse_vma + +From: Liu Shixin + +commit 7528c4fb1237512ee18049f852f014eba80bbe8d upstream. + +I got a bad pud error and lost a 1GB HugeTLB when calling swapoff. The +problem can be reproduced by the following steps: + + 1. Allocate an anonymous 1GB HugeTLB and some other anonymous memory. + 2. Swapout the above anonymous memory. + 3. run swapoff and we will get a bad pud error in kernel message: + + mm/pgtable-generic.c:42: bad pud 00000000743d215d(84000001400000e7) + +We can tell that pud_clear_bad is called by pud_none_or_clear_bad in +unuse_pud_range() by ftrace. And therefore the HugeTLB pages will never +be freed because we lost it from page table. We can skip HugeTLB pages +for unuse_vma to fix it. + +Link: https://lkml.kernel.org/r/20241015014521.570237-1-liushixin2@huawei.com +Fixes: 0fe6e20b9c4c ("hugetlb, rmap: add reverse mapping for hugepage") +Signed-off-by: Liu Shixin +Acked-by: Muchun Song +Cc: Naoya Horiguchi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/swapfile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/swapfile.c ++++ b/mm/swapfile.c +@@ -2091,7 +2091,7 @@ static int unuse_mm(struct mm_struct *mm + + down_read(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { +- if (vma->anon_vma) { ++ if (vma->anon_vma && !is_vm_hugetlb_page(vma)) { + ret = unuse_vma(vma, type, frontswap, + fs_pages_to_unuse); + if (ret) diff --git a/queue-5.4/pci-add-function-0-dma-alias-quirk-for-glenfly-arise-chip.patch b/queue-5.4/pci-add-function-0-dma-alias-quirk-for-glenfly-arise-chip.patch new file mode 100644 index 00000000000..7c746a4301a --- /dev/null +++ b/queue-5.4/pci-add-function-0-dma-alias-quirk-for-glenfly-arise-chip.patch @@ -0,0 +1,48 @@ +From 9246b487ab3c3b5993aae7552b7a4c541cc14a49 Mon Sep 17 00:00:00 2001 +From: WangYuli +Date: Fri, 23 Aug 2024 17:57:08 +0800 +Subject: PCI: Add function 0 DMA alias quirk for Glenfly Arise chip + +From: WangYuli + +commit 9246b487ab3c3b5993aae7552b7a4c541cc14a49 upstream. + +Add DMA support for audio function of Glenfly Arise chip, which uses +Requester ID of function 0. + +Link: https://lore.kernel.org/r/CA2BBD087345B6D1+20240823095708.3237375-1-wangyuli@uniontech.com +Signed-off-by: SiyuLi +Signed-off-by: WangYuli +[bhelgaas: lower-case hex to match local code, drop unused Device IDs] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/quirks.c | 4 ++++ + include/linux/pci_ids.h | 2 ++ + 2 files changed, 6 insertions(+) + +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -4138,6 +4138,10 @@ static void quirk_dma_func0_alias(struct + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe832, quirk_dma_func0_alias); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias); + ++/* Some Glenfly chips use function 0 as the PCIe Requester ID for DMA */ ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d40, quirk_dma_func0_alias); ++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d41, quirk_dma_func0_alias); ++ + static void quirk_dma_func1_alias(struct pci_dev *dev) + { + if (PCI_FUNC(dev->devfn) != 1) +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -2654,6 +2654,8 @@ + #define PCI_DEVICE_ID_DCI_PCCOM8 0x0002 + #define PCI_DEVICE_ID_DCI_PCCOM2 0x0004 + ++#define PCI_VENDOR_ID_GLENFLY 0x6766 ++ + #define PCI_VENDOR_ID_INTEL 0x8086 + #define PCI_DEVICE_ID_INTEL_EESSC 0x0008 + #define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 diff --git a/queue-5.4/posix-clock-fix-missing-timespec64-check-in-pc_clock_settime.patch b/queue-5.4/posix-clock-fix-missing-timespec64-check-in-pc_clock_settime.patch new file mode 100644 index 00000000000..b39e716da04 --- /dev/null +++ b/queue-5.4/posix-clock-fix-missing-timespec64-check-in-pc_clock_settime.patch @@ -0,0 +1,52 @@ +From d8794ac20a299b647ba9958f6d657051fc51a540 Mon Sep 17 00:00:00 2001 +From: Jinjie Ruan +Date: Wed, 9 Oct 2024 15:23:01 +0800 +Subject: posix-clock: Fix missing timespec64 check in pc_clock_settime() + +From: Jinjie Ruan + +commit d8794ac20a299b647ba9958f6d657051fc51a540 upstream. + +As Andrew pointed out, it will make sense that the PTP core +checked timespec64 struct's tv_sec and tv_nsec range before calling +ptp->info->settime64(). + +As the man manual of clock_settime() said, if tp.tv_sec is negative or +tp.tv_nsec is outside the range [0..999,999,999], it should return EINVAL, +which include dynamic clocks which handles PTP clock, and the condition is +consistent with timespec64_valid(). As Thomas suggested, timespec64_valid() +only check the timespec is valid, but not ensure that the time is +in a valid range, so check it ahead using timespec64_valid_strict() +in pc_clock_settime() and return -EINVAL if not valid. + +There are some drivers that use tp->tv_sec and tp->tv_nsec directly to +write registers without validity checks and assume that the higher layer +has checked it, which is dangerous and will benefit from this, such as +hclge_ptp_settime(), igb_ptp_settime_i210(), _rcar_gen4_ptp_settime(), +and some drivers can remove the checks of itself. + +Cc: stable@vger.kernel.org +Fixes: 0606f422b453 ("posix clocks: Introduce dynamic clocks") +Acked-by: Richard Cochran +Suggested-by: Andrew Lunn +Suggested-by: Thomas Gleixner +Signed-off-by: Jinjie Ruan +Link: https://patch.msgid.link/20241009072302.1754567-2-ruanjinjie@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/posix-clock.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/kernel/time/posix-clock.c ++++ b/kernel/time/posix-clock.c +@@ -299,6 +299,9 @@ static int pc_clock_settime(clockid_t id + goto out; + } + ++ if (!timespec64_valid_strict(ts)) ++ return -EINVAL; ++ + if (cd.clk->ops.clock_settime) + err = cd.clk->ops.clock_settime(cd.clk, ts); + else diff --git a/queue-5.4/series b/queue-5.4/series index 890d4862d06..456c37abf93 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -349,3 +349,11 @@ usb-storage-ignore-bogus-device-raised-by-jieli-br21-usb-sound-chip.patch hid-intel-ish-hid-fix-uninitialized-variable-rv-in-ish_fw_xfer_direct_dma.patch net-fix-an-unsafe-loop-on-the-list.patch nouveau-dmem-fix-vulnerability-in-migrate_to_ram-upon-copy-error.patch +posix-clock-fix-missing-timespec64-check-in-pc_clock_settime.patch +arm64-probes-remove-broken-ldr-literal-uprobe-support.patch +arm64-probes-fix-simulate_ldr-_literal.patch +tracing-kprobes-return-eaddrnotavail-when-func-matches-several-symbols.patch +tracing-kprobes-fix-symbol-counting-logic-by-looking-at-modules-as-well.patch +pci-add-function-0-dma-alias-quirk-for-glenfly-arise-chip.patch +fat-fix-uninitialized-variable.patch +mm-swapfile-skip-hugetlb-pages-for-unuse_vma.patch diff --git a/queue-5.4/tracing-kprobes-fix-symbol-counting-logic-by-looking-at-modules-as-well.patch b/queue-5.4/tracing-kprobes-fix-symbol-counting-logic-by-looking-at-modules-as-well.patch new file mode 100644 index 00000000000..89404651f9a --- /dev/null +++ b/queue-5.4/tracing-kprobes-fix-symbol-counting-logic-by-looking-at-modules-as-well.patch @@ -0,0 +1,44 @@ +From 926fe783c8a64b33997fec405cf1af3e61aed441 Mon Sep 17 00:00:00 2001 +From: Andrii Nakryiko +Date: Fri, 27 Oct 2023 16:31:26 -0700 +Subject: tracing/kprobes: Fix symbol counting logic by looking at modules as well + +From: Andrii Nakryiko + +commit 926fe783c8a64b33997fec405cf1af3e61aed441 upstream. + +Recent changes to count number of matching symbols when creating +a kprobe event failed to take into account kernel modules. As such, it +breaks kprobes on kernel module symbols, by assuming there is no match. + +Fix this my calling module_kallsyms_on_each_symbol() in addition to +kallsyms_on_each_match_symbol() to perform a proper counting. + +Link: https://lore.kernel.org/all/20231027233126.2073148-1-andrii@kernel.org/ + +Cc: Francis Laniel +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Steven Rostedt +Fixes: b022f0c7e404 ("tracing/kprobes: Return EADDRNOTAVAIL when func matches several symbols") +Signed-off-by: Andrii Nakryiko +Acked-by: Song Liu +Signed-off-by: Masami Hiramatsu (Google) +[ Sherry: It's a fix for previous backport, thus backport together to 5.4.y ] +Signed-off-by: Sherry Yang +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_kprobe.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -741,6 +741,8 @@ static unsigned int number_of_same_symbo + + kallsyms_on_each_symbol(count_symbols, &args); + ++ module_kallsyms_on_each_symbol(count_symbols, &args); ++ + return args.count; + } + diff --git a/queue-5.4/tracing-kprobes-return-eaddrnotavail-when-func-matches-several-symbols.patch b/queue-5.4/tracing-kprobes-return-eaddrnotavail-when-func-matches-several-symbols.patch new file mode 100644 index 00000000000..c094accc6f6 --- /dev/null +++ b/queue-5.4/tracing-kprobes-return-eaddrnotavail-when-func-matches-several-symbols.patch @@ -0,0 +1,153 @@ +From b022f0c7e404887a7c5229788fc99eff9f9a80d5 Mon Sep 17 00:00:00 2001 +From: Francis Laniel +Date: Fri, 20 Oct 2023 13:42:49 +0300 +Subject: tracing/kprobes: Return EADDRNOTAVAIL when func matches several symbols + +From: Francis Laniel + +commit b022f0c7e404887a7c5229788fc99eff9f9a80d5 upstream. + +When a kprobe is attached to a function that's name is not unique (is +static and shares the name with other functions in the kernel), the +kprobe is attached to the first function it finds. This is a bug as the +function that it is attaching to is not necessarily the one that the +user wants to attach to. + +Instead of blindly picking a function to attach to what is ambiguous, +error with EADDRNOTAVAIL to let the user know that this function is not +unique, and that the user must use another unique function with an +address offset to get to the function they want to attach to. + +Link: https://lore.kernel.org/all/20231020104250.9537-2-flaniel@linux.microsoft.com/ + +Cc: stable@vger.kernel.org +Fixes: 413d37d1eb69 ("tracing: Add kprobe-based event tracer") +Suggested-by: Masami Hiramatsu +Signed-off-by: Francis Laniel +Link: https://lore.kernel.org/lkml/20230819101105.b0c104ae4494a7d1f2eea742@kernel.org/ +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Masami Hiramatsu (Google) +[ Sherry: kselftest kprobe_non_uniq_symbol.tc failed on 5.4.y, because of missing + this commit, backport it to 5.4.y. Minor conflicts due to context change, ignore + context change ] +Signed-off-by: Sherry Yang +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace_kprobe.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ + kernel/trace/trace_probe.h | 1 + 2 files changed, 75 insertions(+) + +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -714,6 +714,36 @@ static inline void sanitize_event_name(c + *name = '_'; + } + ++struct count_symbols_struct { ++ const char *func_name; ++ unsigned int count; ++}; ++ ++static int count_symbols(void *data, const char *name, struct module *unused0, ++ unsigned long unused1) ++{ ++ struct count_symbols_struct *args = data; ++ ++ if (strcmp(args->func_name, name)) ++ return 0; ++ ++ args->count++; ++ ++ return 0; ++} ++ ++static unsigned int number_of_same_symbols(char *func_name) ++{ ++ struct count_symbols_struct args = { ++ .func_name = func_name, ++ .count = 0, ++ }; ++ ++ kallsyms_on_each_symbol(count_symbols, &args); ++ ++ return args.count; ++} ++ + static int trace_kprobe_create(int argc, const char *argv[]) + { + /* +@@ -825,6 +855,31 @@ static int trace_kprobe_create(int argc, + } + } + ++ if (symbol && !strchr(symbol, ':')) { ++ unsigned int count; ++ ++ count = number_of_same_symbols(symbol); ++ if (count > 1) { ++ /* ++ * Users should use ADDR to remove the ambiguity of ++ * using KSYM only. ++ */ ++ trace_probe_log_err(0, NON_UNIQ_SYMBOL); ++ ret = -EADDRNOTAVAIL; ++ ++ goto error; ++ } else if (count == 0) { ++ /* ++ * We can return ENOENT earlier than when register the ++ * kprobe. ++ */ ++ trace_probe_log_err(0, BAD_PROBE_ADDR); ++ ret = -ENOENT; ++ ++ goto error; ++ } ++ } ++ + trace_probe_log_set_index(0); + if (event) { + ret = traceprobe_parse_event_name(&event, &group, buf, +@@ -1596,6 +1651,7 @@ static int unregister_kprobe_event(struc + } + + #ifdef CONFIG_PERF_EVENTS ++ + /* create a trace_kprobe, but don't add it to global lists */ + struct trace_event_call * + create_local_trace_kprobe(char *func, void *addr, unsigned long offs, +@@ -1605,6 +1661,24 @@ create_local_trace_kprobe(char *func, vo + int ret; + char *event; + ++ if (func) { ++ unsigned int count; ++ ++ count = number_of_same_symbols(func); ++ if (count > 1) ++ /* ++ * Users should use addr to remove the ambiguity of ++ * using func only. ++ */ ++ return ERR_PTR(-EADDRNOTAVAIL); ++ else if (count == 0) ++ /* ++ * We can return ENOENT earlier than when register the ++ * kprobe. ++ */ ++ return ERR_PTR(-ENOENT); ++ } ++ + /* + * local trace_kprobes are not added to dyn_event, so they are never + * searched in find_trace_kprobe(). Therefore, there is no concern of +--- a/kernel/trace/trace_probe.h ++++ b/kernel/trace/trace_probe.h +@@ -403,6 +403,7 @@ extern int traceprobe_define_arg_fields( + C(BAD_MAXACT, "Invalid maxactive number"), \ + C(MAXACT_TOO_BIG, "Maxactive is too big"), \ + C(BAD_PROBE_ADDR, "Invalid probed address or symbol"), \ ++ C(NON_UNIQ_SYMBOL, "The symbol is not unique"), \ + C(BAD_RETPROBE, "Retprobe address must be an function entry"), \ + C(NO_GROUP_NAME, "Group name is not specified"), \ + C(GROUP_TOO_LONG, "Group name is too long"), \