Bug 451626

Summary: Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s) in libbpf-tools
Product: [Developer tools] valgrind Reporter: Andreas Gerstmayr <andreas>
Component: generalAssignee: Mark Wielaard <mark>
Status: RESOLVED FIXED    
Severity: normal CC: mark
Priority: NOR    
Version First Reported In: 3.18.1   
Target Milestone: ---   
Platform: Fedora RPMs   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Andreas Gerstmayr 2022-03-17 14:55:44 UTC
SUMMARY
I'm seeing the following error for some libbpf-tools (runqlat, biolatency): Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s).
The programs are working as expected and I suspect this is a bug in valgrind.

STEPS TO REPRODUCE
dnf -y install clang valgrind
git clone --recursive https://github.com/iovisor/bcc.git
cd bcc/libbpf-tools
make runqlat biolatency
valgrind ./runqlat 1 1
valgrind ./biolatency 1 1

OBSERVED RESULT
[root@fedora libbpf-tools]# valgrind ./runqlat 1 1
==1591== Memcheck, a memory error detector
==1591== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1591== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1591== Command: ./runqlat 1 1
==1591== 
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
--1591-- WARNING: unhandled eBPF command 35
==1591== Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)
==1591==    at 0x49A06BD: syscall (syscall.S:38)
==1591==    by 0x4071E2: sys_bpf (bpf.c:74)
==1591==    by 0x4071E2: sys_bpf_fd (bpf.c:82)
==1591==    by 0x4071E2: bpf_raw_tracepoint_open (bpf.c:1130)
==1591==    by 0x40FEC6: bpf_program__attach_btf_id (libbpf.c:10491)
==1591==    by 0x41C02A: bpf_program__attach (libbpf.c:10659)
==1591==    by 0x41C02A: bpf_object__attach_skeleton (libbpf.c:11803)
==1591==    by 0x403A3A: runqlat_bpf__attach (runqlat.skel.h:114)
==1591==    by 0x403A3A: main (runqlat.c:218)
==1591==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1591== 
Tracing run queue latency... Hit Ctrl-C to end.

     usecs               : count    distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 1        |****                                    |
         4 -> 7          : 6        |************************                |
         8 -> 15         : 5        |********************                    |
        16 -> 31         : 5        |********************                    |
        32 -> 63         : 7        |****************************            |
        64 -> 127        : 1        |****                                    |
       128 -> 255        : 2        |********                                |
       256 -> 511        : 4        |****************                        |
       512 -> 1023       : 10       |****************************************|
==1591== 
==1591== HEAP SUMMARY:
==1591==     in use at exit: 0 bytes in 0 blocks
==1591==   total heap usage: 151 allocs, 151 frees, 13,605,314 bytes allocated
==1591== 
==1591== All heap blocks were freed -- no leaks are possible
==1591== 
==1591== For lists of detected and suppressed errors, rerun with: -s
==1591== ERROR SUMMARY: 3 errors from 1 contexts (suppressed: 0 from 0)

[root@fedora libbpf-tools]# valgrind ./biolatency 1 1
==1752== Memcheck, a memory error detector
==1752== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1752== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1752== Command: ./biolatency 1 1
==1752== 
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
--1752-- WARNING: unhandled eBPF command 35
==1752== Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)
==1752==    at 0x49A06BD: syscall (syscall.S:38)
==1752==    by 0x4073B2: sys_bpf (bpf.c:74)
==1752==    by 0x4073B2: sys_bpf_fd (bpf.c:82)
==1752==    by 0x4073B2: bpf_raw_tracepoint_open (bpf.c:1130)
==1752==    by 0x410096: bpf_program__attach_btf_id (libbpf.c:10491)
==1752==    by 0x403ABA: main (biolatency.c:318)
==1752==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1752== 
==1752== Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)
==1752==    at 0x49A06BD: syscall (syscall.S:38)
==1752==    by 0x4073B2: sys_bpf (bpf.c:74)
==1752==    by 0x4073B2: sys_bpf_fd (bpf.c:82)
==1752==    by 0x4073B2: bpf_raw_tracepoint_open (bpf.c:1130)
==1752==    by 0x410096: bpf_program__attach_btf_id (libbpf.c:10491)
==1752==    by 0x403AD0: main (biolatency.c:324)
==1752==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1752== 
Tracing block device I/O... Hit Ctrl-C to end.


     usecs               : count    distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 0        |                                        |
         4 -> 7          : 0        |                                        |
         8 -> 15         : 0        |                                        |
        16 -> 31         : 0        |                                        |
        32 -> 63         : 0        |                                        |
        64 -> 127        : 0        |                                        |
       128 -> 255        : 2        |****************************************|
       256 -> 511        : 1        |********************                    |
       512 -> 1023       : 1        |********************                    |
      1024 -> 2047       : 1        |********************                    |
      2048 -> 4095       : 1        |********************                    |
      4096 -> 8191       : 1        |********************                    |
==1752== 
==1752== HEAP SUMMARY:
==1752==     in use at exit: 0 bytes in 0 blocks
==1752==   total heap usage: 169 allocs, 169 frees, 13,601,324 bytes allocated
==1752== 
==1752== All heap blocks were freed -- no leaks are possible
==1752== 
==1752== For lists of detected and suppressed errors, rerun with: -s
==1752== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)


EXPECTED RESULT
No 'Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)' errors.

SOFTWARE/OS VERSIONS
Linux: Fedora 36
Valgrind: valgrind-3.18.1-9.fc36.x86_64
bcc: commit d1b1b61ceaee16e9d68e3c66e3ebddd55ba36d0f
libbpf: commit d6783c28b40e8355d2e3bd4a8141b88da7704f6d (libbpf is embedded in the bcc repository as a git submodule)

ADDITIONAL INFORMATION
The source lines in question which point to unaddressable bytes according to valgrind: https://github.com/libbpf/libbpf/blob/d6783c28b40e8355d2e3bd4a8141b88da7704f6d/src/bpf.c#L1126-L1130
Comment 1 Mark Wielaard 2022-03-17 18:16:05 UTC
So there are two issues here:

- WARNING: unhandled eBPF command 35
  This seems to be BPF_LINK_DETACH, which valgrind indeed doesn't handle.

- Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable byte(s)
  Address 0x0 is not stack'd, malloc'd or (recently) free'd
  This check is only done for BPF_RAW_TRACEPOINT_OPEN
  It isn't immediately clear to me that is is allowed to be NULL.

Do you happen to have documentation which explains what BPF_RAW_TRACEPOINT_OPEN does when the name is NULL?
Comment 2 Andreas Gerstmayr 2022-03-17 20:15:48 UTC
(In reply to Mark Wielaard from comment #1)
> So there are two issues here:
> 
> - WARNING: unhandled eBPF command 35
>   This seems to be BPF_LINK_DETACH, which valgrind indeed doesn't handle.

Yep, that's fine so far. I'm more concerned about the error below.

> - Syscall param bpf(attr->raw_tracepoint.name) points to unaddressable
> byte(s)
>   Address 0x0 is not stack'd, malloc'd or (recently) free'd
>   This check is only done for BPF_RAW_TRACEPOINT_OPEN
>   It isn't immediately clear to me that is is allowed to be NULL.
> 
> Do you happen to have documentation which explains what
> BPF_RAW_TRACEPOINT_OPEN does when the name is NULL?

Good question :)
I looked in the caller, and it's quite explicit about setting the name to NULL: https://github.com/libbpf/libbpf/blob/d6783c28b40e8355d2e3bd4a8141b88da7704f6d/src/libbpf.c#L10491

Then I looked into the syscall on the kernel side (https://github.com/torvalds/linux/blob/56e337f2cf1326323844927a04e9dbce9a244835/kernel/bpf/syscall.c#L3042-L3056) and it goes as far as erroring out if the name is set to anything other than NULL with the following comment: "The attach point for this category of programs should be specified via btf_id during program load."
A few lines later tp_name is set to prog->aux->attach_func_name.

prog->type is BPF_PROG_TYPE_TRACING in our case, I've verified that in the bpf_program__attach_btf_id function on the libbpf side.
So afaics, when using BTF, only the raw_tracepoint.prog_fd should be set.
Comment 3 Mark Wielaard 2022-03-19 00:20:43 UTC
Thanks for doing the research. The fix is simple in that case:

diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index b9d531de3..38edccc98 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -12920,8 +12920,9 @@ PRE(sys_bpf)
                break;
             }
             /* Name is limited to 128 characters in kernel/bpf/syscall.c. */
-            pre_asciiz_str(tid, attr->raw_tracepoint.name, 128,
-                           "bpf(attr->raw_tracepoint.name)");
+            if (attr->raw_tracepoint.name != NULL)
+               pre_asciiz_str(tid, attr->raw_tracepoint.name, 128,
+                              "bpf(attr->raw_tracepoint.name)");
          }
          break;
       case VKI_BPF_BTF_LOAD:

https://code.wildebeest.org/git/user/mjw/valgrind/commit/?h=bpf-raw_tracepoint-name
Comment 4 Andreas Gerstmayr 2022-03-21 11:47:36 UTC
(In reply to Mark Wielaard from comment #3)
> Thanks for doing the research. The fix is simple in that case:
> 
> diff --git a/coregrind/m_syswrap/syswrap-linux.c
> b/coregrind/m_syswrap/syswrap-linux.c
> index b9d531de3..38edccc98 100644
> --- a/coregrind/m_syswrap/syswrap-linux.c
> +++ b/coregrind/m_syswrap/syswrap-linux.c
> @@ -12920,8 +12920,9 @@ PRE(sys_bpf)
>                 break;
>              }
>              /* Name is limited to 128 characters in kernel/bpf/syscall.c. */
> -            pre_asciiz_str(tid, attr->raw_tracepoint.name, 128,
> -                           "bpf(attr->raw_tracepoint.name)");
> +            if (attr->raw_tracepoint.name != NULL)
> +               pre_asciiz_str(tid, attr->raw_tracepoint.name, 128,
> +                              "bpf(attr->raw_tracepoint.name)");
>           }
>           break;
>        case VKI_BPF_BTF_LOAD:
> 
> https://code.wildebeest.org/git/user/mjw/valgrind/commit/?h=bpf-
> raw_tracepoint-name

Thanks! I've verified that the above fix resolves this issue.
Comment 5 Mark Wielaard 2022-03-21 11:58:44 UTC
Thanks for testing. Pushed as:

commit 957339db27f7d1603a7217a0f891d91d204d64aa
Author: Mark Wielaard <mark@klomp.org>
Date:   Sat Mar 19 01:06:40 2022 +0100

    bpf attr->raw_tracepoint.name may be NULL for BPF_RAW_TRACEPOINT_OPEN.
    
    For BPF_RAW_TRACEPOINT_OPEN attr->raw_tracepoint.name may be NULL.
    Otherwise it should point to a valid (max 128 char) string. Only
    raw_tracepoint.prog_fd needs to be set.
    
    https://bugs.kde.org/show_bug.cgi?id=451626