Re: [PATCH bpf] bpf/btf: Accept function names that contain dots

From: Andrii Nakryiko
Date: Fri Jun 16 2023 - 13:00:43 EST


On Thu, Jun 15, 2023 at 7:56 AM Florent Revest <revest@xxxxxxxxxxxx> wrote:
>
> When building a kernel with LLVM=1, LLVM_IAS=0 and CONFIG_KASAN=y, LLVM
> leaves DWARF tags for the "asan.module_ctor" & co symbols. In turn,
> pahole creates BTF_KIND_FUNC entries for these and this makes the BTF
> metadata validation fail because they contain a dot.
>
> In a dramatic turn of event, this BTF verification failure can cause
> the netfilter_bpf initialization to fail, causing netfilter_core to
> free the netfilter_helper hashmap and netfilter_ftp to trigger a
> use-after-free. The risk of u-a-f in netfilter will be addressed
> separately but the existence of "asan.module_ctor" debug info under some
> build conditions sounds like a good enough reason to accept functions
> that contain dots in BTF.

I don't see much harm in allowing dots. There are also all those .isra
and other modifications to functions that we currently don't have in
BTF, but with the discussions about recording function addrs we might
eventually have those as well. So:

Acked-by: Andrii Nakryiko <andrii@xxxxxxxxxx>

>
> Cc: stable@xxxxxxxxxxxxxxx
> Fixes: 1dc92851849c ("bpf: kernel side support for BTF Var and DataSec")
> Signed-off-by: Florent Revest <revest@xxxxxxxxxxxx>
> ---
> kernel/bpf/btf.c | 20 ++++++++------------
> 1 file changed, 8 insertions(+), 12 deletions(-)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 6b682b8e4b50..72b32b7cd9cd 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -744,13 +744,12 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
> return offset < btf->hdr.str_len;
> }
>
> -static bool __btf_name_char_ok(char c, bool first, bool dot_ok)
> +static bool __btf_name_char_ok(char c, bool first)
> {
> if ((first ? !isalpha(c) :
> !isalnum(c)) &&
> c != '_' &&
> - ((c == '.' && !dot_ok) ||
> - c != '.'))
> + c != '.')
> return false;
> return true;
> }
> @@ -767,20 +766,20 @@ static const char *btf_str_by_offset(const struct btf *btf, u32 offset)
> return NULL;
> }
>
> -static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
> +static bool __btf_name_valid(const struct btf *btf, u32 offset)
> {
> /* offset must be valid */
> const char *src = btf_str_by_offset(btf, offset);
> const char *src_limit;
>
> - if (!__btf_name_char_ok(*src, true, dot_ok))
> + if (!__btf_name_char_ok(*src, true))
> return false;
>
> /* set a limit on identifier length */
> src_limit = src + KSYM_NAME_LEN;
> src++;
> while (*src && src < src_limit) {
> - if (!__btf_name_char_ok(*src, false, dot_ok))
> + if (!__btf_name_char_ok(*src, false))
> return false;
> src++;
> }
> @@ -788,17 +787,14 @@ static bool __btf_name_valid(const struct btf *btf, u32 offset, bool dot_ok)
> return !*src;
> }
>
> -/* Only C-style identifier is permitted. This can be relaxed if
> - * necessary.
> - */
> static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)
> {
> - return __btf_name_valid(btf, offset, false);
> + return __btf_name_valid(btf, offset);
> }
>
> static bool btf_name_valid_section(const struct btf *btf, u32 offset)
> {
> - return __btf_name_valid(btf, offset, true);
> + return __btf_name_valid(btf, offset);
> }
>
> static const char *__btf_name_by_offset(const struct btf *btf, u32 offset)
> @@ -4422,7 +4418,7 @@ static s32 btf_var_check_meta(struct btf_verifier_env *env,
> }
>
> if (!t->name_off ||
> - !__btf_name_valid(env->btf, t->name_off, true)) {
> + !__btf_name_valid(env->btf, t->name_off)) {
> btf_verifier_log_type(env, t, "Invalid name");
> return -EINVAL;
> }
> --
> 2.41.0.162.gfafddb0af9-goog
>