Re: Errors compiling BPF programs from Linux selftests/bpf with GCC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2025-01-02 at 19:24 +0100, Jose E. Marchesi wrote:

[...]

> IMO the BPP selftest (and BPF programs in general) must not include host
> glibc headers at all, regardless of what BPF compiler is used.  The
> glibc headers installed in the host are tailored to some particular
> architecture, be it x86_64 or whatever, not necessarily compatible with
> what the compilers assume for the BPF target.
>
> This particular case shows the problem well: all the glibc headers
> included by that BPF selftest assume that `long' is 32 bits, not 64
> bits, because x86_64 is not defined.  This conflicts with both clang's
> and GCC's assumption that in BPF a `long' is 64 bits.  This may or may
> not be a problem, depending on whether the BPF program uses the stuff
> defined in the headers and how it uses it.  Had you be using an arm or
> sparc host instead of x86_64, you may be including macros and stuff that
> assume chars are unsigned.  But chars are signed in bpf.

This makes sense, but might cause some friction.
The following glibc headers are included directly from selftests:
- errno.h
- features.h
- inttypes.h
- limits.h
- netinet/in.h
- netinet/udp.h
- sched.h
- stdint.h
- stdlib.h
- string.h
- sys/socket.h
- sys/types.h
- time.h
- unistd.h

However, removing includes for these headers does not help the test in
question, because some linux UAPI headers include libc headers when exported:

    In file included from /usr/include/netinet/udp.h:51,
                     from progs/test_cls_redirect_dynptr.c:20:
    /home/eddy/work/tmp/gccbpf/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: error: conflicting types for ‘int64_t’; have ‘long int’
       43 | typedef __INT64_TYPE__ int64_t;
          |                        ^~~~~~~
    In file included from /usr/include/sys/types.h:155,
                     from /usr/include/bits/socket.h:29,
                     from /usr/include/sys/socket.h:33,
                     from /usr/include/linux/if.h:28,
                     from /usr/include/linux/icmp.h:23,
                     from progs/test_cls_redirect_dynptr.c:12:
    /usr/include/bits/stdint-intn.h:27:19: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long long int’}
       27 | typedef __int64_t int64_t;
          |                   ^~~~~~~

On my system (Fedora 41) the linux/{icmp,if}.h UAPI headers are
provided by kernel-headers package, sys/socket.h is provided by
glibc-devel package.

The UAPI headers have two modes depending whether __KERNEL__ is
defined. When used during kernel build the __KERNEL__ is defined and
there are no outside references. When exported for packages like
kernel-headers (via 'make headers' target) the __KERNEL__ is not
defined and there are some references to libc includes
(in fact, references to '#ifdef __KERNEL__' blocks are cut out during
 headers export).

E.g. here is a fragment of linux/if.h, when viewed from kernel source:

    #ifndef _LINUX_IF_H
    #define _LINUX_IF_H

    #include <linux/libc-compat.h>          /* for compatibility with glibc */
    #include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
    #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
    #include <linux/compiler.h>		/* for "__user" et al           */

    #ifndef __KERNEL__
    #include <sys/socket.h>			/* for struct sockaddr.		*/
    #endif

And here is the same fragment as part of the kernel-headers package
(/usr/include/linux/if.h):

    #ifndef _LINUX_IF_H
    #define _LINUX_IF_H

    #include <linux/libc-compat.h>          /* for compatibility with glibc */
    #include <linux/types.h>		/* for "__kernel_caddr_t" et al	*/
    #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
    		/* for "__user" et al           */

    #include <sys/socket.h>			/* for struct sockaddr.		*/

As far as I understand, the idea right now is that BPF users can
install the kernel-headers package (or its equivalent) and start
hacking. If we declare that this is no longer a blessed way, people
would need to switch to packages like kernel-devel that provide full
set of kernel headers for use with dkms etc, e.g. for my system the
if.h would be located here:
/usr/src/kernels/6.12.6-200.fc41.x86_64/include/uapi/linux/if.h .

To me this seems logical, however potentially such change might have
implications for existing BPF code-base.






[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux