bpf: move all programs into src/bpf/ and consolidate meson logic

The six .bpf.c files and their shared .bpf.h headers now live directly
under src/bpf/, rather than scattered across src/core/bpf/<prog>/,
src/network/bpf/<prog>/ and src/nsresourced/bpf/<prog>/.

All BPF compilation logic — the BPF_FRAMEWORK determination (clang/gcc/
bpftool/llvm-strip lookups), flag and command construction, vmlinux.h
handling, the bpf_programs list and the loop that builds the unstripped
object, the stripped object and the skeleton header for each program —
moves into src/bpf/meson.build. The top-level meson.build only keeps
option handling and the libbpf dependency. subdir('src/bpf') is pulled
up before config.h generation so that BPF_FRAMEWORK, HAVE_VMLINUX_H and
ENABLE_SYSCTL_BPF land in conf in time.

Skeleton wrapper headers (<prog>-skel.h) are now emitted by a
configure_file() template (src/bpf/bpf-skel-wrapper.h.in) at meson
setup, replacing the previously checked-in shims of the same name.

Consumer #include paths are flattened:
"bpf/<prog>/<prog>-skel.h" becomes "<prog>-skel.h",
"bpf/<prog>/<prog>-api.bpf.h" becomes "<prog>-api.bpf.h". src/bpf is
added to includes so the shared BPF headers resolve.

sysctl-write-event.h, now shared between userspace (networkd-sysctl.c)
and BPF (sysctl-monitor.bpf.c) from a single location, gains guarded
includes so pid_t and uint64_t resolve on both sides: vmlinux.h in the
BPF case (selected via __bpf__), stdint.h + sys/types.h otherwise.
This commit is contained in:
Daan De Meyer
2026-04-22 16:49:36 +02:00
committed by Daan De Meyer
parent 85b5acde86
commit e6fc73350f
33 changed files with 433 additions and 580 deletions
+18 -319
View File
@@ -1067,86 +1067,6 @@ libbpf = dependency('libbpf',
libbpf_cflags = libbpf.partial_dependency(includes: true, compile_args: true)
conf.set10('HAVE_LIBBPF', libbpf.found())
if not libbpf.found()
conf.set10('BPF_FRAMEWORK', false)
else
clang_found = false
clang_supports_bpf = false
bpf_gcc_found = false
bpftool_strip = false
deps_found = false
if bpf_compiler == 'clang'
# Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
# (like clang-10/llvm-strip-10)
if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
r = find_program('clang',
required : bpf_framework,
version : '>= 10.0.0')
clang_found = r.found()
if clang_found
clang = r.full_path()
endif
else
clang_found = true
clang = cc.cmd_array()
endif
if clang_found
# Check if 'clang -target bpf' is supported.
clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
endif
if bpf_framework.enabled() and not clang_supports_bpf
error('bpf-framework was enabled but clang does not support bpf')
endif
elif bpf_compiler == 'gcc'
bpf_gcc = find_program('bpf-gcc',
'bpf-none-gcc',
'bpf-unknown-none-gcc',
required : true,
version : '>= 13.1.0')
bpf_gcc_found = bpf_gcc.found()
endif
if clang_supports_bpf or bpf_gcc_found
# Debian installs this in /usr/sbin/ which is not in $PATH.
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
# We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework.enabled() and bpf_compiler == 'gcc',
version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
if bpftool.found()
bpftool_strip = true
deps_found = true
elif bpf_compiler == 'clang'
# We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework,
version : '>= 5.6.0')
endif
# We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
if not bpftool_strip and bpftool.found() and clang_supports_bpf
if not meson.is_cross_build()
llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
check : true).stdout().strip()
else
llvm_strip_bin = 'llvm-strip'
endif
llvm_strip = find_program(llvm_strip_bin,
required : bpf_framework,
version : '>= 10.0.0')
deps_found = llvm_strip.found()
endif
endif
# Can build BPF program from source code in restricted C
conf.set10('BPF_FRAMEWORK', deps_found)
endif
libmount = dependency('mount',
version : fuzzer_build ? '>= 0' : '>= 2.30',
required : get_option('libmount'))
@@ -1730,171 +1650,6 @@ endif
#####################################################################
if conf.get('BPF_FRAMEWORK') == 1
bpf_clang_flags = [
'-std=gnu17',
'-Wno-compare-distinct-pointer-types',
'-Wno-microsoft-anon-tag',
'-fms-extensions',
'-fno-stack-protector',
'-O2',
'-target',
'bpf',
'-g',
'-c',
]
bpf_gcc_flags = [
'-std=gnu17',
'-fms-extensions',
'-fno-stack-protector',
'-fno-ssa-phiopt',
'-O2',
'-mcpu=v3',
'-mco-re',
'-gbtf',
'-c',
]
# If c_args contains these flags copy them along with the values, in order to avoid breaking
# reproducible builds and other functionality
propagate_cflags = [
'-ffile-prefix-map=',
'-fdebug-prefix-map=',
'-fmacro-prefix-map=',
'--sysroot=',
]
foreach opt : c_args
foreach flag : propagate_cflags
if opt.startswith(flag)
bpf_clang_flags += [opt]
bpf_gcc_flags += [opt]
break
endif
endforeach
endforeach
# Generate defines that are appropriate to tell the compiler what architecture
# we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
# This dictionary contains the exceptions where this doesn't work.
#
# C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
# and src/basic/missing_syscall_def.h.
# Start with older ABI. When define is missing, we're likely targeting that.
ppc64_elf_version = '1'
if host_machine.cpu_family() == 'ppc64'
# cc doesn't have to be bpf_compiler, but they should be targeting the same ABI
call_elf_value = cc.get_define('_CALL_ELF')
if call_elf_value != ''
ppc64_elf_version = call_elf_value
endif
endif
cpu_arch_defines = {
'ppc' : ['-D__powerpc__', '-D__TARGET_ARCH_powerpc'],
'ppc64' : ['-D__powerpc64__', '-D__TARGET_ARCH_powerpc', '-D_CALL_ELF=' + ppc64_elf_version],
'riscv32' : ['-D__riscv', '-D__riscv_xlen=32', '-D__TARGET_ARCH_riscv'],
'riscv64' : ['-D__riscv', '-D__riscv_xlen=64', '-D__TARGET_ARCH_riscv'],
'x86' : ['-D__i386__', '-D__TARGET_ARCH_x86'],
's390x' : ['-D__s390__', '-D__s390x__', '-D__TARGET_ARCH_s390'],
# For arm, assume hardware fp is available.
'arm' : ['-D__arm__', '-D__ARM_PCS_VFP', '-D__TARGET_ARCH_arm'],
'loongarch64' : ['-D__loongarch__', '-D__loongarch_grlen=64', '-D__TARGET_ARCH_loongarch']
}
bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
['-D__@0@__'.format(host_machine.cpu_family())])
if bpf_compiler == 'gcc'
bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
endif
libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
bpf_o_unstripped_cmd = []
if bpf_compiler == 'clang'
bpf_o_unstripped_cmd += [
clang,
bpf_clang_flags,
bpf_arch_flags,
]
elif bpf_compiler == 'gcc'
bpf_o_unstripped_cmd += [
bpf_gcc,
bpf_gcc_flags,
bpf_arch_flags,
]
endif
bpf_o_unstripped_cmd += ['-I.', '-include', 'config.h']
if cc.get_id() == 'gcc' or meson.is_cross_build()
if cc.get_id() != 'gcc'
warning('Cross compiler is not gcc. Guessing the target triplet for bpf likely fails.')
endif
target_triplet_cmd = run_command(cc.cmd_array(), '-print-multiarch', check: false)
else
# clang does not support -print-multiarch (D133170) and its -dump-machine
# does not match multiarch. Query gcc instead.
target_triplet_cmd = run_command('gcc', '-print-multiarch', check: false)
endif
if target_triplet_cmd.returncode() == 0
sysroot = meson.get_external_property('sys_root', '/')
target_triplet = target_triplet_cmd.stdout().strip()
target_include_dir = sysroot / 'usr' / 'include'
target_triple_include_dir = target_include_dir / target_triplet
isystem_dir = ''
if fs.is_dir(target_triple_include_dir)
isystem_dir = target_triple_include_dir
elif fs.is_dir(target_include_dir)
isystem_dir = target_include_dir
endif
if isystem_dir != ''
bpf_o_unstripped_cmd += [
'-isystem', isystem_dir
]
endif
endif
bpf_o_unstripped_cmd += [
'-idirafter',
libbpf_include_dir,
'@INPUT@',
'-o',
'@OUTPUT@'
]
if bpftool_strip
bpf_o_cmd = [
bpftool,
'gen',
'object',
'@OUTPUT@',
'@INPUT@'
]
elif bpf_compiler == 'clang'
bpf_o_cmd = [
llvm_strip,
'-g',
'@INPUT@',
'-o',
'@OUTPUT@'
]
endif
skel_h_cmd = [
bpftool,
'gen',
'skeleton',
'@INPUT@'
]
endif
#####################################################################
efi_arch = {
'aarch64' : 'aa64',
'arm' : 'arm',
@@ -1932,77 +1687,6 @@ conf.set10('ENABLE_UKIFY', want_ukify)
#####################################################################
use_provided_vmlinux_h = false
use_generated_vmlinux_h = false
provided_vmlinux_h_path = get_option('vmlinux-h-path')
# For the more complex BPF programs we really want a vmlinux.h (which is arch
# specific, but only somewhat bound to kernel version). Ideally the kernel
# development headers would ship that, but right now they don't. Hence address
# this in two ways:
#
# 1. Provide a vmlinux.h at build time
# 2. Generate the file on the fly where possible (which requires /sys/ to be mounted)
#
# We generally prefer the former (to support reproducible builds), but will
# fallback to the latter.
if conf.get('BPF_FRAMEWORK') == 1
enable_vmlinux_h = get_option('vmlinux-h')
if enable_vmlinux_h == 'auto'
if provided_vmlinux_h_path != ''
use_provided_vmlinux_h = true
elif fs.exists('/sys/kernel/btf/vmlinux') and \
bpftool.found() and \
(host_machine.cpu_family() == build_machine.cpu_family()) and \
host_machine.cpu_family() in ['x86_64', 'aarch64']
# We will only generate a vmlinux.h from the running
# kernel if the host and build machine are of the same
# family. Also for now we focus on x86_64 and aarch64,
# since other archs don't seem to be ready yet.
use_generated_vmlinux_h = true
endif
elif enable_vmlinux_h == 'provided'
use_provided_vmlinux_h = true
elif enable_vmlinux_h == 'generated'
if not fs.exists('/sys/kernel/btf/vmlinux')
error('BTF data from kernel not available (/sys/kernel/btf/vmlinux missing), cannot generate vmlinux.h, but was asked to.')
endif
if not bpftool.found()
error('bpftool not available, cannot generate vmlinux.h, but was asked to.')
endif
use_generated_vmlinux_h = true
endif
endif
vmlinux_h_dependency = []
if use_provided_vmlinux_h
if not fs.exists(provided_vmlinux_h_path)
error('Path to provided vmlinux.h does not exist.')
endif
bpf_o_unstripped_cmd += ['-I' + fs.parent(provided_vmlinux_h_path)]
message(f'Using provided @provided_vmlinux_h_path@')
elif use_generated_vmlinux_h
vmlinux_h_dependency = custom_target(
output: 'vmlinux.h',
command : [ bpftool, 'btf', 'dump', 'file', '/sys/kernel/btf/vmlinux', 'format', 'c' ],
capture : true)
bpf_o_unstripped_cmd += ['-I' + fs.parent(vmlinux_h_dependency.full_path())]
message('Using generated @0@'.format(vmlinux_h_dependency.full_path()))
else
message('Using neither provided nor generated vmlinux.h, some features will not be available.')
endif
conf.set10('HAVE_VMLINUX_H', use_provided_vmlinux_h or use_generated_vmlinux_h)
conf.set10('ENABLE_SYSCTL_BPF', conf.get('HAVE_VMLINUX_H') == 1 and libbpf.version().version_compare('>= 0.7'))
#####################################################################
version_tag = get_option('version-tag')
if version_tag == ''
version_tag = meson.project_version()
@@ -2010,8 +1694,11 @@ endif
conf.set_quoted('VERSION_TAG', version_tag)
generated_sources = []
subdir('tools')
subdir('src/version')
subdir('src/bpf')
shared_lib_tag = get_option('shared-lib-tag')
if shared_lib_tag == ''
@@ -2051,7 +1738,6 @@ executables = []
executables_by_name = {}
objects_by_name = {}
fuzzer_exes = []
generated_sources = [version_h, vmlinux_h_dependency]
sources = []
# binaries that have --help and are intended for use by humans,
@@ -2118,7 +1804,13 @@ libsystemd_includes = [basic_includes, include_directories(
'src/libsystemd/sd-resolve',
'src/libsystemd/sd-varlink')]
includes = [libsystemd_includes, include_directories('src/shared')]
includes = [
libsystemd_includes,
include_directories(
'src/shared',
'src/bpf',
),
]
subdir('po')
subdir('catalog')
@@ -2519,11 +2211,18 @@ foreach dict : executables
exe_sources = dict.get('sources', []) + dict.get('extract', [])
foreach bpf_name : dict.get('bpf_programs', [])
if bpf_name in bpf_programs_by_name
exe_sources += bpf_programs_by_name[bpf_name]
endif
endforeach
kwargs = {}
foreach key, val : dict
if key in ['name', 'dbus', 'public', 'conditions', 'type', 'suite',
'timeout', 'parallel', 'objects', 'sources', 'extract',
'include_directories', 'build_by_default', 'install']
'include_directories', 'build_by_default', 'install',
'bpf_programs']
continue
endif
@@ -7,12 +7,13 @@
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__attach_skeleton sym_bpf_object__attach_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#define bpf_object__detach_skeleton sym_bpf_object__detach_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#include "bpf/userns-restrict/userns-restrict.skel.h" /* IWYU pragma: export */
#include "@NAME@.bpf.skel.h" /* IWYU pragma: export */
+385
View File
@@ -0,0 +1,385 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if not libbpf.found()
conf.set10('BPF_FRAMEWORK', false)
else
clang_found = false
clang_supports_bpf = false
bpf_gcc_found = false
bpftool_strip = false
deps_found = false
if bpf_compiler == 'clang'
# Support 'versioned' clang/llvm-strip binaries, as seen on Debian/Ubuntu
# (like clang-10/llvm-strip-10)
if meson.is_cross_build() or cc.get_id() != 'clang' or cc.cmd_array()[0].contains('afl-clang') or cc.cmd_array()[0].contains('hfuzz-clang')
r = find_program('clang',
required : bpf_framework,
version : '>= 10.0.0')
clang_found = r.found()
if clang_found
clang = r.full_path()
endif
else
clang_found = true
clang = cc.cmd_array()
endif
if clang_found
# Check if 'clang -target bpf' is supported.
clang_supports_bpf = run_command(clang, '-target', 'bpf', '--print-supported-cpus', check : false).returncode() == 0
endif
if bpf_framework.enabled() and not clang_supports_bpf
error('bpf-framework was enabled but clang does not support bpf')
endif
elif bpf_compiler == 'gcc'
bpf_gcc = find_program('bpf-gcc',
'bpf-none-gcc',
'bpf-unknown-none-gcc',
required : true,
version : '>= 13.1.0')
bpf_gcc_found = bpf_gcc.found()
endif
if clang_supports_bpf or bpf_gcc_found
# Debian installs this in /usr/sbin/ which is not in $PATH.
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
# We use 'bpftool gen object' subcommand for bpftool strip, it was added by d80b2fcbe0a023619e0fc73112f2a02c2662f6ab (v5.13).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework.enabled() and bpf_compiler == 'gcc',
version : bpf_compiler == 'gcc' ? '>= 7.0.0' : '>= 5.13.0')
if bpftool.found()
bpftool_strip = true
deps_found = true
elif bpf_compiler == 'clang'
# We require the 'bpftool gen skeleton' subcommand, it was added by 985ead416df39d6fe8e89580cc1db6aa273e0175 (v5.6).
bpftool = find_program('bpftool',
'/usr/sbin/bpftool',
required : bpf_framework,
version : '>= 5.6.0')
endif
# We use `llvm-strip` as a fallback if `bpftool gen object` strip support is not available.
if not bpftool_strip and bpftool.found() and clang_supports_bpf
if not meson.is_cross_build()
llvm_strip_bin = run_command(clang, '--print-prog-name', 'llvm-strip',
check : true).stdout().strip()
else
llvm_strip_bin = 'llvm-strip'
endif
llvm_strip = find_program(llvm_strip_bin,
required : bpf_framework,
version : '>= 10.0.0')
deps_found = llvm_strip.found()
endif
endif
# Can build BPF program from source code in restricted C
conf.set10('BPF_FRAMEWORK', deps_found)
endif
if conf.get('BPF_FRAMEWORK') == 1
bpf_clang_flags = [
'-std=gnu17',
'-Wno-compare-distinct-pointer-types',
'-Wno-microsoft-anon-tag',
'-fms-extensions',
'-fno-stack-protector',
'-O2',
'-target',
'bpf',
'-g',
'-c',
]
bpf_gcc_flags = [
'-std=gnu17',
'-fms-extensions',
'-fno-stack-protector',
'-fno-ssa-phiopt',
'-O2',
'-mcpu=v3',
'-mco-re',
'-gbtf',
'-c',
]
# If c_args contains these flags copy them along with the values, in order to avoid breaking
# reproducible builds and other functionality
propagate_cflags = [
'-ffile-prefix-map=',
'-fdebug-prefix-map=',
'-fmacro-prefix-map=',
'--sysroot=',
]
foreach opt : c_args
foreach flag : propagate_cflags
if opt.startswith(flag)
bpf_clang_flags += [opt]
bpf_gcc_flags += [opt]
break
endif
endforeach
endforeach
# Generate defines that are appropriate to tell the compiler what architecture
# we're compiling for. By default we just map meson's cpu_family to __<cpu_family>__.
# This dictionary contains the exceptions where this doesn't work.
#
# C.f. https://mesonbuild.com/Reference-tables.html#cpu-families
# and src/basic/missing_syscall_def.h.
# Start with older ABI. When define is missing, we're likely targeting that.
ppc64_elf_version = '1'
if host_machine.cpu_family() == 'ppc64'
# cc doesn't have to be bpf_compiler, but they should be targeting the same ABI
call_elf_value = cc.get_define('_CALL_ELF')
if call_elf_value != ''
ppc64_elf_version = call_elf_value
endif
endif
cpu_arch_defines = {
'ppc' : ['-D__powerpc__', '-D__TARGET_ARCH_powerpc'],
'ppc64' : ['-D__powerpc64__', '-D__TARGET_ARCH_powerpc', '-D_CALL_ELF=' + ppc64_elf_version],
'riscv32' : ['-D__riscv', '-D__riscv_xlen=32', '-D__TARGET_ARCH_riscv'],
'riscv64' : ['-D__riscv', '-D__riscv_xlen=64', '-D__TARGET_ARCH_riscv'],
'x86' : ['-D__i386__', '-D__TARGET_ARCH_x86'],
's390x' : ['-D__s390__', '-D__s390x__', '-D__TARGET_ARCH_s390'],
# For arm, assume hardware fp is available.
'arm' : ['-D__arm__', '-D__ARM_PCS_VFP', '-D__TARGET_ARCH_arm'],
'loongarch64' : ['-D__loongarch__', '-D__loongarch_grlen=64', '-D__TARGET_ARCH_loongarch']
}
bpf_arch_flags = cpu_arch_defines.get(host_machine.cpu_family(),
['-D__@0@__'.format(host_machine.cpu_family())])
if bpf_compiler == 'gcc'
bpf_arch_flags += ['-m' + host_machine.endian() + '-endian']
endif
libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
bpf_o_unstripped_cmd = []
if bpf_compiler == 'clang'
bpf_o_unstripped_cmd += [
clang,
bpf_clang_flags,
bpf_arch_flags,
]
elif bpf_compiler == 'gcc'
bpf_o_unstripped_cmd += [
bpf_gcc,
bpf_gcc_flags,
bpf_arch_flags,
]
endif
bpf_o_unstripped_cmd += ['-I.', '-include', 'config.h']
if cc.get_id() == 'gcc' or meson.is_cross_build()
if cc.get_id() != 'gcc'
warning('Cross compiler is not gcc. Guessing the target triplet for bpf likely fails.')
endif
target_triplet_cmd = run_command(cc.cmd_array(), '-print-multiarch', check: false)
else
# clang does not support -print-multiarch (D133170) and its -dump-machine
# does not match multiarch. Query gcc instead.
target_triplet_cmd = run_command('gcc', '-print-multiarch', check: false)
endif
if target_triplet_cmd.returncode() == 0
sysroot = meson.get_external_property('sys_root', '/')
target_triplet = target_triplet_cmd.stdout().strip()
target_include_dir = sysroot / 'usr' / 'include'
target_triple_include_dir = target_include_dir / target_triplet
isystem_dir = ''
if fs.is_dir(target_triple_include_dir)
isystem_dir = target_triple_include_dir
elif fs.is_dir(target_include_dir)
isystem_dir = target_include_dir
endif
if isystem_dir != ''
bpf_o_unstripped_cmd += [
'-isystem', isystem_dir
]
endif
endif
bpf_o_unstripped_cmd += [
'-idirafter',
libbpf_include_dir,
'@INPUT@',
'-o',
'@OUTPUT@'
]
if bpftool_strip
bpf_o_cmd = [
bpftool,
'gen',
'object',
'@OUTPUT@',
'@INPUT@'
]
elif bpf_compiler == 'clang'
bpf_o_cmd = [
llvm_strip,
'-g',
'@INPUT@',
'-o',
'@OUTPUT@'
]
endif
skel_h_cmd = [
bpftool,
'gen',
'skeleton',
'@INPUT@'
]
endif
use_provided_vmlinux_h = false
use_generated_vmlinux_h = false
provided_vmlinux_h_path = get_option('vmlinux-h-path')
# For the more complex BPF programs we really want a vmlinux.h (which is arch
# specific, but only somewhat bound to kernel version). Ideally the kernel
# development headers would ship that, but right now they don't. Hence address
# this in two ways:
#
# 1. Provide a vmlinux.h at build time
# 2. Generate the file on the fly where possible (which requires /sys/ to be mounted)
#
# We generally prefer the former (to support reproducible builds), but will
# fallback to the latter.
if conf.get('BPF_FRAMEWORK') == 1
enable_vmlinux_h = get_option('vmlinux-h')
if enable_vmlinux_h == 'auto'
if provided_vmlinux_h_path != ''
use_provided_vmlinux_h = true
elif fs.exists('/sys/kernel/btf/vmlinux') and \
bpftool.found() and \
(host_machine.cpu_family() == build_machine.cpu_family()) and \
host_machine.cpu_family() in ['x86_64', 'aarch64']
# We will only generate a vmlinux.h from the running
# kernel if the host and build machine are of the same
# family. Also for now we focus on x86_64 and aarch64,
# since other archs don't seem to be ready yet.
use_generated_vmlinux_h = true
endif
elif enable_vmlinux_h == 'provided'
use_provided_vmlinux_h = true
elif enable_vmlinux_h == 'generated'
if not fs.exists('/sys/kernel/btf/vmlinux')
error('BTF data from kernel not available (/sys/kernel/btf/vmlinux missing), cannot generate vmlinux.h, but was asked to.')
endif
if not bpftool.found()
error('bpftool not available, cannot generate vmlinux.h, but was asked to.')
endif
use_generated_vmlinux_h = true
endif
endif
vmlinux_h_dependency = []
if use_provided_vmlinux_h
if not fs.exists(provided_vmlinux_h_path)
error('Path to provided vmlinux.h does not exist.')
endif
bpf_o_unstripped_cmd += ['-I' + fs.parent(provided_vmlinux_h_path)]
message(f'Using provided @provided_vmlinux_h_path@')
elif use_generated_vmlinux_h
vmlinux_h_dependency = custom_target(
output: 'vmlinux.h',
command : [ bpftool, 'btf', 'dump', 'file', '/sys/kernel/btf/vmlinux', 'format', 'c' ],
capture : true)
bpf_o_unstripped_cmd += ['-I' + fs.parent(vmlinux_h_dependency.full_path())]
generated_sources += vmlinux_h_dependency
message('Using generated @0@'.format(vmlinux_h_dependency.full_path()))
else
message('Using neither provided nor generated vmlinux.h, some features will not be available.')
endif
conf.set10('HAVE_VMLINUX_H', use_provided_vmlinux_h or use_generated_vmlinux_h)
conf.set10('ENABLE_SYSCTL_BPF', conf.get('HAVE_VMLINUX_H') == 1 and libbpf.version().version_compare('>= 0.7'))
bpf_programs = [
{
'source' : files('bind-iface.bpf.c'),
'condition' : 'BPF_FRAMEWORK',
},
{
'source' : files('restrict-fs.bpf.c'),
'condition' : 'BPF_FRAMEWORK',
},
{
'source' : files('restrict-ifaces.bpf.c'),
'condition' : 'BPF_FRAMEWORK',
},
{
'source' : files('socket-bind.bpf.c'),
'condition' : 'BPF_FRAMEWORK',
},
{
'source' : files('sysctl-monitor.bpf.c'),
'condition' : 'ENABLE_SYSCTL_BPF',
'depends' : vmlinux_h_dependency,
},
{
'source' : files('userns-restrict.bpf.c'),
'condition' : 'HAVE_VMLINUX_H',
'depends' : vmlinux_h_dependency,
},
]
bpf_programs_by_name = {}
foreach program : bpf_programs
if conf.get(program['condition']) != 1
continue
endif
source = program['source'][0]
name = fs.stem(fs.stem(source))
bpf_o_unstripped = custom_target(
input : source,
output : name + '.bpf.unstripped.o',
command : bpf_o_unstripped_cmd,
depends : program.get('depends', []))
bpf_o = custom_target(
input : bpf_o_unstripped,
output : name + '.bpf.o',
command : bpf_o_cmd)
skel_h = custom_target(
input : bpf_o,
output : name + '.bpf.skel.h',
command : skel_h_cmd,
capture : true)
# The wrapper is written at meson setup time and found via the
# include path, so we don't need to list it as a build-time source.
# Keeping it out of bpf_programs_by_name also keeps it out of the
# clang-tidy per-source test loop, which would otherwise fall back
# to a BPF compile_commands.json entry (no -Isrc/shared) and fail
# to resolve bpf-dlopen.h.
configure_file(
input : 'bpf-skel-wrapper.h.in',
output : name + '-skel.h',
configuration : { 'NAME' : name })
bpf_programs_by_name += { name : skel_h }
generated_sources += skel_h
endforeach
@@ -2,6 +2,13 @@
#pragma once
#ifdef __bpf__
#include "vmlinux.h"
#else
#include <stdint.h>
#include <sys/types.h>
#endif
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16
#endif
@@ -15,7 +15,7 @@
#include "vmlinux.h"
#include <errno.h>
#include <errno.h> /* IWYU pragma: keep */
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
+1 -1
View File
@@ -14,7 +14,7 @@
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
#include "bpf/bind-iface/bind-iface-skel.h"
#include "bind-iface-skel.h"
static struct bind_iface_bpf *bind_iface_bpf_free(struct bind_iface_bpf *obj) {
bind_iface_bpf__destroy(obj);
+1 -1
View File
@@ -17,7 +17,7 @@
/* libbpf, clang and llc compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
#include "bpf/restrict-fs/restrict-fs-skel.h"
#include "restrict-fs-skel.h"
#define CGROUP_HASH_SIZE_MAX 2048
+1 -1
View File
@@ -16,7 +16,7 @@
#include "bpf-dlopen.h"
#include "bpf-link.h"
#include "bpf/restrict-ifaces/restrict-ifaces-skel.h"
#include "restrict-ifaces-skel.h"
static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) {
restrict_ifaces_bpf__destroy(obj);
+2 -2
View File
@@ -11,8 +11,8 @@
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
#include "bpf-dlopen.h"
#include "bpf-link.h"
#include "bpf/socket-bind/socket-bind-api.bpf.h"
#include "bpf/socket-bind/socket-bind-skel.h"
#include "socket-bind-api.bpf.h"
#include "socket-bind-skel.h"
static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
/* socket_bind_bpf__destroy handles object == NULL case */
-17
View File
@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* The SPDX header above is actually correct in claiming this was
* LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
* compatible with GPL we will claim this to be GPL however, which should be
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#include "bpf/bind-iface/bind-iface.skel.h" /* IWYU pragma: export */
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('BPF_FRAMEWORK') != 1
subdir_done()
endif
bind_network_interface_bpf_o_unstripped = custom_target(
input : 'bind-iface.bpf.c',
output : 'bind-iface.bpf.unstripped.o',
command : bpf_o_unstripped_cmd)
bind_network_interface_bpf_o = custom_target(
input : bind_network_interface_bpf_o_unstripped,
output : 'bind-iface.bpf.o',
command : bpf_o_cmd)
bind_network_interface_skel_h = custom_target(
input : bind_network_interface_bpf_o,
output : 'bind-iface.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += bind_network_interface_skel_h
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('BPF_FRAMEWORK') != 1
subdir_done()
endif
restrict_fs_bpf_o_unstripped = custom_target(
input : 'restrict-fs.bpf.c',
output : 'restrict-fs.bpf.unstripped.o',
command : bpf_o_unstripped_cmd)
restrict_fs_bpf_o = custom_target(
input : restrict_fs_bpf_o_unstripped,
output : 'restrict-fs.bpf.o',
command : bpf_o_cmd)
restrict_fs_skel_h = custom_target(
input : restrict_fs_bpf_o,
output : 'restrict-fs.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += restrict_fs_skel_h
@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* The SPDX header above is actually correct in claiming this was
* LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
* compatible with GPL we will claim this to be GPL however, which should be
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#include "bpf/restrict-fs/restrict-fs.skel.h" /* IWYU pragma: export */
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('BPF_FRAMEWORK') != 1
subdir_done()
endif
restrict_ifaces_bpf_o_unstripped = custom_target(
input : 'restrict-ifaces.bpf.c',
output : 'restrict-ifaces.bpf.unstripped.o',
command : bpf_o_unstripped_cmd)
restrict_ifaces_bpf_o = custom_target(
input : restrict_ifaces_bpf_o_unstripped,
output : 'restrict-ifaces.bpf.o',
command : bpf_o_cmd)
restrict_ifaces_skel_h = custom_target(
input : restrict_ifaces_bpf_o,
output : 'restrict-ifaces.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += restrict_ifaces_skel_h
@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* The SPDX header above is actually correct in claiming this was
* LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
* compatible with GPL we will claim this to be GPL however, which should be
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#include "bpf/restrict-ifaces/restrict-ifaces.skel.h" /* IWYU pragma: export */
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('BPF_FRAMEWORK') != 1
subdir_done()
endif
socket_bind_bpf_o_unstripped = custom_target(
input : 'socket-bind.bpf.c',
output : 'socket-bind.bpf.unstripped.o',
command : bpf_o_unstripped_cmd)
socket_bind_bpf_o = custom_target(
input : socket_bind_bpf_o_unstripped,
output : 'socket-bind.bpf.o',
command : bpf_o_cmd)
socket_bind_skel_h = custom_target(
input : socket_bind_bpf_o,
output : 'socket-bind.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += socket_bind_skel_h
@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* The SPDX header above is actually correct in claiming this was
* LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
* compatible with GPL we will claim this to be GPL however, which should be
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#include "bpf/socket-bind/socket-bind.skel.h" /* IWYU pragma: export */
+3 -10
View File
@@ -76,17 +76,10 @@ libcore_sources = files(
'varlink-unit.c',
)
subdir('bpf/socket-bind')
subdir('bpf/restrict-fs')
subdir('bpf/restrict-ifaces')
subdir('bpf/bind-iface')
if conf.get('BPF_FRAMEWORK') == 1
libcore_sources += [
socket_bind_skel_h,
restrict_fs_skel_h,
restrict_ifaces_skel_h,
bind_network_interface_skel_h]
foreach name : ['socket-bind', 'restrict-fs', 'restrict-ifaces', 'bind-iface']
libcore_sources += bpf_programs_by_name[name]
endforeach
endif
sources += libcore_sources
@@ -1,24 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('ENABLE_SYSCTL_BPF') != 1
subdir_done()
endif
sysctl_monitor_bpf_o_unstripped = custom_target(
input : 'sysctl-monitor.bpf.c',
output : 'sysctl-monitor.bpf.unstripped.o',
command : bpf_o_unstripped_cmd,
depends : vmlinux_h_dependency)
sysctl_monitor_bpf_o = custom_target(
input : sysctl_monitor_bpf_o_unstripped,
output : 'sysctl-monitor.bpf.o',
command : bpf_o_cmd)
sysctl_monitor_skel_h = custom_target(
input : sysctl_monitor_bpf_o,
output : 'sysctl-monitor.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += sysctl_monitor_skel_h
@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/* The SPDX header above is actually correct in claiming this was
* LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
* compatible with GPL we will claim this to be GPL however, which should be
* fine given that LGPL-2.1-or-later downgrades to GPL if needed.
*/
#include "bpf-dlopen.h" /* IWYU pragma: keep */
/* libbpf is used via dlopen(), so rename symbols */
#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
#include "bpf/sysctl-monitor/sysctl-monitor.skel.h" /* IWYU pragma: export */
+3 -6
View File
@@ -1,7 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
subdir('bpf/sysctl-monitor')
systemd_networkd_sources = files(
'networkd.c'
)
@@ -144,10 +142,6 @@ networkctl_sources = files(
networkd_network_gperf_gperf = files('networkd-network-gperf.gperf')
networkd_netdev_gperf_gperf = files('netdev/netdev-gperf.gperf')
if conf.get('ENABLE_SYSCTL_BPF') == 1
systemd_networkd_extract_sources += sysctl_monitor_skel_h
endif
networkd_gperf_c = custom_target(
input : 'networkd-gperf.gperf',
output : 'networkd-gperf.c',
@@ -209,6 +203,9 @@ executables += [
networkd_link_with,
],
'dependencies' : threads,
'bpf_programs': [
'sysctl-monitor',
]
},
libexec_template + {
'name' : 'systemd-networkd-wait-online',
+2 -2
View File
@@ -30,8 +30,8 @@
#if ENABLE_SYSCTL_BPF
#include "bpf-link.h"
#include "bpf/sysctl-monitor/sysctl-monitor-skel.h"
#include "bpf/sysctl-monitor/sysctl-write-event.h"
#include "sysctl-monitor-skel.h"
#include "sysctl-write-event.h"
static struct sysctl_monitor_bpf* sysctl_monitor_bpf_free(struct sysctl_monitor_bpf *obj) {
sysctl_monitor_bpf__destroy(obj);
@@ -1,24 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('HAVE_VMLINUX_H') != 1
subdir_done()
endif
userns_restrict_bpf_o_unstripped = custom_target(
input : 'userns-restrict.bpf.c',
output : 'userns-restrict.bpf.unstripped.o',
command : bpf_o_unstripped_cmd,
depends : vmlinux_h_dependency)
userns_restrict_bpf_o = custom_target(
input : userns_restrict_bpf_o_unstripped,
output : 'userns-restrict.bpf.o',
command : bpf_o_cmd)
userns_restrict_skel_h = custom_target(
input : userns_restrict_bpf_o,
output : 'userns-restrict.skel.h',
command : skel_h_cmd,
capture : true)
generated_sources += userns_restrict_skel_h
+3 -8
View File
@@ -4,8 +4,6 @@ if conf.get('ENABLE_NSRESOURCED') != 1
subdir_done()
endif
subdir('bpf/userns-restrict')
systemd_nsresourced_sources = files(
'nsresourced-manager.c',
'nsresourced.c',
@@ -21,29 +19,26 @@ test_userns_restrict_sources = files(
'test-userns-restrict.c'
)
if conf.get('HAVE_VMLINUX_H') == 1
systemd_nsresourced_sources += userns_restrict_skel_h
systemd_nsresourcework_sources += userns_restrict_skel_h
test_userns_restrict_sources += userns_restrict_skel_h
endif
executables += [
libexec_template + {
'name' : 'systemd-nsresourced',
'sources' : systemd_nsresourced_sources,
'extract' : systemd_nsresourced_extract_sources,
'dependencies' : threads,
'bpf_programs': ['userns-restrict'],
},
libexec_template + {
'name' : 'systemd-nsresourcework',
'sources' : systemd_nsresourcework_sources,
'dependencies' : threads,
'objects' : ['systemd-nsresourced'],
'bpf_programs': ['userns-restrict'],
},
test_template + {
'sources' : test_userns_restrict_sources,
'conditions' : ['HAVE_VMLINUX_H'],
'objects' : ['systemd-nsresourced'],
'bpf_programs': ['userns-restrict'],
},
]
+1 -1
View File
@@ -8,7 +8,7 @@
#include "bpf-dlopen.h"
#if HAVE_VMLINUX_H
#include "bpf-link.h"
#include "bpf/userns-restrict/userns-restrict-skel.h"
#include "userns-restrict-skel.h"
#endif
#include "build-path.h"
#include "common-signal.h"
+1 -1
View File
@@ -3,7 +3,7 @@
#include <sys/stat.h>
#if HAVE_VMLINUX_H
#include "bpf/userns-restrict/userns-restrict-skel.h"
#include "userns-restrict-skel.h"
#endif
#include "bpf-dlopen.h"
+1
View File
@@ -14,3 +14,4 @@ version_h = custom_target('version',
])
version_include = include_directories('.')
userspace_sources += [version_h]
generated_sources += [version_h]