[RFC,1/2] kprobes: Prohibit probing on CFI preamble symbol
Commit Message
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Do not allow to probe on "__cfi_" started symbol, because it includes
a typeid value in the code for CFI. Probing it will break the typeid
checking.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
kernel/kprobes.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
Comments
On Mon, Jul 10, 2023 at 09:14:24PM +0900, Masami Hiramatsu (Google) wrote:
> +#ifdef CONFIG_CFI_CLANG
> +static bool is_cfi_preamble_symbol(unsigned long addr)
> +{
> + char symbuf[KSYM_NAME_LEN];
> +
> + if (lookup_symbol_name(addr, symbuf))
> + return false;
> +
> + return str_has_prefix("__cfi_", symbuf)
|| str_has_prefix("__pfx_", symbol);
The __pfx_ symbols can happen when !CFI_CLANG but still having
FUNCTION_PADDING_BYTES.
> +}
> +#else
> +#define is_cfi_preamble_symbol(addr) (0)
> +#endif
As such I think we can do the above unconditionally, without either
there should not be any matching symbols.
On Mon, 10 Jul 2023 17:37:24 +0200
Peter Zijlstra <peterz@infradead.org> wrote:
> On Mon, Jul 10, 2023 at 09:14:24PM +0900, Masami Hiramatsu (Google) wrote:
>
>
> > +#ifdef CONFIG_CFI_CLANG
> > +static bool is_cfi_preamble_symbol(unsigned long addr)
> > +{
> > + char symbuf[KSYM_NAME_LEN];
> > +
> > + if (lookup_symbol_name(addr, symbuf))
> > + return false;
> > +
> > + return str_has_prefix("__cfi_", symbuf)
> || str_has_prefix("__pfx_", symbol);
>
> The __pfx_ symbols can happen when !CFI_CLANG but still having
> FUNCTION_PADDING_BYTES.
Indeed. Currently __pfx is not probed via tracefs interface because it is
notrace function but kprobe itself should also prohibit that.
>
> > +}
> > +#else
> > +#define is_cfi_preamble_symbol(addr) (0)
> > +#endif
>
> As such I think we can do the above unconditionally, without either
> there should not be any matching symbols.
OK.
Thank you!
>
@@ -1545,6 +1545,20 @@ static int check_ftrace_location(struct kprobe *p)
return 0;
}
+#ifdef CONFIG_CFI_CLANG
+static bool is_cfi_preamble_symbol(unsigned long addr)
+{
+ char symbuf[KSYM_NAME_LEN];
+
+ if (lookup_symbol_name(addr, symbuf))
+ return false;
+
+ return str_has_prefix("__cfi_", symbuf);
+}
+#else
+#define is_cfi_preamble_symbol(addr) (0)
+#endif
+
static int check_kprobe_address_safe(struct kprobe *p,
struct module **probed_mod)
{
@@ -1563,7 +1577,8 @@ static int check_kprobe_address_safe(struct kprobe *p,
within_kprobe_blacklist((unsigned long) p->addr) ||
jump_label_text_reserved(p->addr, p->addr) ||
static_call_text_reserved(p->addr, p->addr) ||
- find_bug((unsigned long)p->addr)) {
+ find_bug((unsigned long)p->addr) ||
+ is_cfi_preamble_symbol((unsigned long)p->addr)) {
ret = -EINVAL;
goto out;
}