From: Jianpeng Chang <jianpeng.chang.cn@windriver.com>
To: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
Cc: naveen@kernel.org, davem@davemloft.net, catalin.marinas@arm.com,
mark.rutland@arm.com, linux-kernel@vger.kernel.org,
linux-trace-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] kprobes: skip non-symbol addresses in kprobe_add_ksym_blacklist()
Date: Wed, 29 Apr 2026 16:16:44 +0800 [thread overview]
Message-ID: <a298419e-c581-41c9-b6d5-9319c24b7995@windriver.com> (raw)
In-Reply-To: <20260428184321.309a48036892b8d23a08b566@kernel.org>
在 2026/4/28 下午5:43, Masami Hiramatsu (Google) 写道:
> CAUTION: This email comes from a non Wind River email account! Do
> not click links or open attachments unless you recognize the sender
> and know the content is safe.
>
> Hi,
>
> On Mon, 27 Apr 2026 15:35:44 +0800 Jianpeng Chang
> <jianpeng.chang.cn@windriver.com> wrote:
>
>> When kprobe_add_area_blacklist() iterates through a section like
>> .kprobes.text, the start address may not correspond to a named
>> symbol. On ARM64 with CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y
>> (introduced by commit baaf553d3bc3 ("arm64: Implement
>> HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS")), the compiler flag -
>> fpatchable-function-entry=4,2 inserts 2 NOPs before each function
>> entry point for ftrace call_ops. These pre-function NOPs sit at
>> the section base address, before the first named function symbol.
>> The compiler emits a $x mapping symbol at offset 0x00 to mark the
>> start of code, but find_kallsyms_symbol() ignores mapping symbols.
>>
>> Without CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS (e.g. defconfig), no
>> pre-function NOPs are inserted, the first function starts at
>> offset 0x00, and the bug does not trigger.
>>
>> This only affects modules that have a .kprobes.text section (i.e.
>> those using the __kprobes annotation). Modules using
>> NOKPROBE_SYMBOL() instead (like kretprobe_example.ko) blacklist
>> exact function addresses via the _kprobe_blacklist section and are
>> not affected.
>>
>> For kprobe_example.ko on ARM64 with -fpatchable-function-
>> entry=4,2, the .kprobes.text section layout is:
>>
>> offset 0x00: $x + 2 NOPs (mapping symbol + ftrace preamble)
>> offset 0x08: handler_post (64 bytes) offset 0x50: handler_pre
>> (68 bytes)
>
> Ah, OK. It is for __kprobes attribute. I recommend user to use
> NOKPROBE_SYMBOL() but I understand the situation.
>
>>
>> kprobe_add_area_blacklist() starts iterating from the section base
>> address (offset 0x00), which only has the $x mapping symbol.
>> kprobe_add_ksym_blacklist() then calls
>> kallsyms_lookup_size_offset() for this address, which goes
>> through:
>>
>> kallsyms_lookup_size_offset() -> module_address_lookup() ->
>> find_kallsyms_symbol()
>>
>> find_kallsyms_symbol() scans all module symbols to find the
>> closest preceding symbol.
>>
>> Since no named text symbol exists at offset 0x00,
>> find_kallsyms_symbol() picks __UNIQUE_ID_vermagic (a .modinfo
>> symbol whose address is in the temporary image) as the "best"
>> match. The computed "size" = next_text_symbol - modinfo_symbol
>> spans across these two unrelated memory regions, creating a
>> blacklist entry with a bogus range of tens of terabytes.
>>
>> Whether this causes a visible failure depends on address
>> randomization, here is what happens on Raspberry Pi 4/5:
>>
>> - On RPi5, the bogus size was ~35 TB. start + size stayed within
>> 64-bit range, so the blacklist entry covered the entire kernel
>> text. register_kprobe() in the module's own init function failed
>> with -EINVAL.
>>
>> - On RPi4, the bogus size was ~75 TB. start + size overflowed 64
>> bits and wrapped to a small address near zero. The range check
>> (addr >= start && addr < end) then failed because end wrapped
>> around, so the bogus entry was accidentally harmless and kprobes
>> worked by luck.
>>
>> The same bug exists on both machines, but randomization determines
>> whether the integer overflow masks it or not.
>>
>> Fix this by checking the offset returned by
>> kallsyms_lookup_size_offset(). A non-zero offset means the address
>> is not at a symbol boundary, so skip forward to the next symbol
>> instead of creating a blacklist entry with a wrong size.
>>
>> Fixes: baaf553d3bc3 ("arm64: Implement
>> HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS") Signed-off-by: Jianpeng Chang
>> <jianpeng.chang.cn@windriver.com> --- Hi,
>>
>> This patch skips non-symbol addresses, fixes the bogus blacklist
>> entry, but leaves the NOP gap at the start of .kprobes.text
>> unblacklisted.
>
> That is OK because those NOPs are not executed in kprobe handler.
>
>>
>> We can continue alloc the ent without return to add the gap to
>> blacklist, or do some more works to add the gap to the first
>> symbol in blacklist. I'm not sure if is this necessary, or is
>> there a better way?
>
> Are there any compiler option or attribute to avoid inserting these
> NOPs to the specific section? (like notrace?)
>
> Also, as you can see there is an alias symbol whose size is 0. and
> in that case, we move the entry + 1 and call
> kprobe_add_ksym_blacklist() again. Thus, the offset becomes 1.
> Please make sure it is correctly handled.
>
Regarding the alias symbol concern: kallsyms_lookup_size_offset()
computes size as the distance to the next different-address symbol, not
from ELF st_size. I tested with a module containing alias symbols in
.kprobes.text (created via __attribute__((alias))), and the lookup
returned a correct size with offset=0 — the if (ret == 0) ret = 1 path
was never triggered.
That said, #define __kprobes notrace __section(".kprobes.text") is a
cleaner fix. The NOPs in .kprobes.text are unnecessary since these
functions should never be traced by ftrace. I've tested this on RPi5 —
the bug is resolved and all .kprobes.text functions are correctly
blacklisted. I'll send the notrace approach in v2.
Thanks,
Jianpeng> Thanks,
>
>>
>> Thanks, Jianpeng
>>
>> kernel/kprobes.c | 4 ++++ 1 file changed, 4 insertions(+)
>>
>> diff --git a/kernel/kprobes.c b/kernel/kprobes.c index
>> bfc89083daa9..be700fb03198 100644 --- a/kernel/kprobes.c> +++ b/
>> kernel/kprobes.c @@ -2503,6 +2503,10 @@ int
>> kprobe_add_ksym_blacklist(unsigned long entry) !
>> kallsyms_lookup_size_offset(entry, &size, &offset)) return -
>> EINVAL;
>>
>> + /* Not on a symbol boundary -- skip to the next symbol */
>> + if (offset) + return (int)(size - offset); + ent
>> = kmalloc_obj(*ent); if (!ent) return -ENOMEM; -- 2.54.0
>>
>
>
> -- Masami Hiramatsu (Google) <mhiramat@kernel.org>
next prev parent reply other threads:[~2026-04-29 8:17 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 7:35 [PATCH] kprobes: skip non-symbol addresses in kprobe_add_ksym_blacklist() Jianpeng Chang
2026-04-28 9:43 ` Masami Hiramatsu
2026-04-29 8:16 ` Jianpeng Chang [this message]
2026-04-29 8:30 ` Masami Hiramatsu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a298419e-c581-41c9-b6d5-9319c24b7995@windriver.com \
--to=jianpeng.chang.cn@windriver.com \
--cc=catalin.marinas@arm.com \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mhiramat@kernel.org \
--cc=naveen@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox