From 6c6b4146deb12d20f42490d5013f2043df942161 Mon Sep 17 00:00:00 2001 From: Yureka Lilian Date: Thu, 14 Aug 2025 20:01:12 +0200 Subject: libbpf: Fix reuse of DEVMAP Previously, re-using pinned DEVMAP maps would always fail, because get_map_info on a DEVMAP always returns flags with BPF_F_RDONLY_PROG set, but BPF_F_RDONLY_PROG being set on a map during creation is invalid. Thus, ignore the BPF_F_RDONLY_PROG flag in the flags returned from get_map_info when checking for compatibility with an existing DEVMAP. The same problem is handled in a third-party ebpf library: - https://github.com/cilium/ebpf/issues/925 - https://github.com/cilium/ebpf/pull/930 Fixes: 0cdbb4b09a06 ("devmap: Allow map lookups from eBPF") Signed-off-by: Yureka Lilian Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20250814180113.1245565-3-yuka@yuka.dev --- tools/lib/bpf/libbpf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8f5a81b672e1..fe4fc5438678 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -5093,6 +5093,16 @@ static bool map_is_reuse_compat(const struct bpf_map *map, int map_fd) return false; } + /* + * bpf_get_map_info_by_fd() for DEVMAP will always return flags with + * BPF_F_RDONLY_PROG set, but it generally is not set at map creation time. + * Thus, ignore the BPF_F_RDONLY_PROG flag in the flags returned from + * bpf_get_map_info_by_fd() when checking for compatibility with an + * existing DEVMAP. + */ + if (map->def.type == BPF_MAP_TYPE_DEVMAP || map->def.type == BPF_MAP_TYPE_DEVMAP_HASH) + map_info.map_flags &= ~BPF_F_RDONLY_PROG; + return (map_info.type == map->def.type && map_info.key_size == map->def.key_size && map_info.value_size == map->def.value_size && -- cgit v1.2.3 From 2693227c1150d58bf82ef45a394a554373be5286 Mon Sep 17 00:00:00 2001 From: Mykyta Yatsenko Date: Tue, 19 Aug 2025 22:51:19 +0100 Subject: libbpf: Export bpf_object__prepare symbol Add missing LIBBPF_API macro for bpf_object__prepare function to enable its export. libbpf.map had bpf_object__prepare already listed. Fixes: 1315c28ed809 ("libbpf: Split bpf object load into prepare/load") Signed-off-by: Mykyta Yatsenko Signed-off-by: Daniel Borkmann Acked-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20250819215119.37795-1-mykyta.yatsenko5@gmail.com --- tools/lib/bpf/libbpf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 455a957cb702..2b86e21190d3 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -252,7 +252,7 @@ bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz, * @return 0, on success; negative error code, otherwise, error code is * stored in errno */ -int bpf_object__prepare(struct bpf_object *obj); +LIBBPF_API int bpf_object__prepare(struct bpf_object *obj); /** * @brief **bpf_object__load()** loads BPF object into kernel. -- cgit v1.2.3 From 78e097fbca719ce3dbca8f81a6c339a8e0e41d1c Mon Sep 17 00:00:00 2001 From: Cryolitia PukNgae Date: Wed, 20 Aug 2025 17:22:42 +0800 Subject: libbpf: Add documentation to version and error API functions Add documentation for the following API functions: - libbpf_major_version() - libbpf_minor_version() - libbpf_version_string() - libbpf_strerror() Signed-off-by: Cryolitia PukNgae Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20250820-libbpf-doc-1-v1-1-13841f25a134@uniontech.com --- tools/lib/bpf/libbpf.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 2b86e21190d3..2e91148d9b44 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -24,8 +24,25 @@ extern "C" { #endif +/** + * @brief **libbpf_major_version()** provides the major version of libbpf. + * @return An integer, the major version number + */ LIBBPF_API __u32 libbpf_major_version(void); + +/** + * @brief **libbpf_minor_version()** provides the minor version of libbpf. + * @return An integer, the minor version number + */ LIBBPF_API __u32 libbpf_minor_version(void); + +/** + * @brief **libbpf_version_string()** provides the version of libbpf in a + * human-readable form, e.g., "v1.7". + * @return Pointer to a static string containing the version + * + * The format is *not* a part of a stable API and may change in the future. + */ LIBBPF_API const char *libbpf_version_string(void); enum libbpf_errno { @@ -49,6 +66,14 @@ enum libbpf_errno { __LIBBPF_ERRNO__END, }; +/** + * @brief **libbpf_strerror()** converts the provided error code into a + * human-readable string. + * @param err The error code to convert + * @param buf Pointer to a buffer where the error message will be stored + * @param size The number of bytes in the buffer + * @return 0, on success; negative error code, otherwise + */ LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size); /** -- cgit v1.2.3 From 758acb9ccfdbf854b55abaceaf1f3f229cde3d19 Mon Sep 17 00:00:00 2001 From: Jiawei Zhao Date: Wed, 27 Aug 2025 05:31:27 +0000 Subject: libbpf: Fix USDT SIB argument handling causing unrecognized register error On x86-64, USDT arguments can be specified using Scale-Index-Base (SIB) addressing, e.g. "1@-96(%rbp,%rax,8)". The current USDT implementation in libbpf cannot parse this format, causing `bpf_program__attach_usdt()` to fail with -ENOENT (unrecognized register). This patch fixes this by implementing the necessary changes: - add correct handling for SIB-addressed arguments in `bpf_usdt_arg`. - add adaptive support to `__bpf_usdt_arg_type` and `__bpf_usdt_arg_spec` to represent SIB addressing parameters. Signed-off-by: Jiawei Zhao Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20250827053128.1301287-2-phoenix500526@163.com --- tools/lib/bpf/usdt.bpf.h | 44 ++++++++++++++++++++++++++++++++-- tools/lib/bpf/usdt.c | 62 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 99 insertions(+), 7 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/usdt.bpf.h b/tools/lib/bpf/usdt.bpf.h index 2a7865c8e3fe..43deb05a5197 100644 --- a/tools/lib/bpf/usdt.bpf.h +++ b/tools/lib/bpf/usdt.bpf.h @@ -34,13 +34,32 @@ enum __bpf_usdt_arg_type { BPF_USDT_ARG_CONST, BPF_USDT_ARG_REG, BPF_USDT_ARG_REG_DEREF, + BPF_USDT_ARG_SIB, }; +/* + * This struct layout is designed specifically to be backwards/forward + * compatible between libbpf versions for ARG_CONST, ARG_REG, and + * ARG_REG_DEREF modes. ARG_SIB requires libbpf v1.7+. + */ struct __bpf_usdt_arg_spec { /* u64 scalar interpreted depending on arg_type, see below */ __u64 val_off; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* arg location case, see bpf_usdt_arg() for details */ - enum __bpf_usdt_arg_type arg_type; + enum __bpf_usdt_arg_type arg_type: 8; + /* index register offset within struct pt_regs */ + __u16 idx_reg_off: 12; + /* scale factor for index register (1, 2, 4, or 8) */ + __u16 scale_bitshift: 4; + /* reserved for future use, keeps reg_off offset stable */ + __u8 __reserved: 8; +#else + __u8 __reserved: 8; + __u16 idx_reg_off: 12; + __u16 scale_bitshift: 4; + enum __bpf_usdt_arg_type arg_type: 8; +#endif /* offset of referenced register within struct pt_regs */ short reg_off; /* whether arg should be interpreted as signed value */ @@ -149,7 +168,7 @@ int bpf_usdt_arg(struct pt_regs *ctx, __u64 arg_num, long *res) { struct __bpf_usdt_spec *spec; struct __bpf_usdt_arg_spec *arg_spec; - unsigned long val; + unsigned long val, idx; int err, spec_id; *res = 0; @@ -202,6 +221,27 @@ int bpf_usdt_arg(struct pt_regs *ctx, __u64 arg_num, long *res) return err; #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ val >>= arg_spec->arg_bitshift; +#endif + break; + case BPF_USDT_ARG_SIB: + /* Arg is in memory addressed by SIB (Scale-Index-Base) mode + * (e.g., "-1@-96(%rbp,%rax,8)" in USDT arg spec). We first + * fetch the base register contents and the index register + * contents from pt_regs. Then we calculate the final address + * as base + (index * scale) + offset, and do a user-space + * probe read to fetch the argument value. + */ + err = bpf_probe_read_kernel(&val, sizeof(val), (void *)ctx + arg_spec->reg_off); + if (err) + return err; + err = bpf_probe_read_kernel(&idx, sizeof(idx), (void *)ctx + arg_spec->idx_reg_off); + if (err) + return err; + err = bpf_probe_read_user(&val, sizeof(val), (void *)(val + (idx << arg_spec->scale_bitshift) + arg_spec->val_off)); + if (err) + return err; +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + val >>= arg_spec->arg_bitshift; #endif break; default: diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c index 3373b9d45ac4..867bff6b0699 100644 --- a/tools/lib/bpf/usdt.c +++ b/tools/lib/bpf/usdt.c @@ -200,12 +200,23 @@ enum usdt_arg_type { USDT_ARG_CONST, USDT_ARG_REG, USDT_ARG_REG_DEREF, + USDT_ARG_SIB, }; /* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */ struct usdt_arg_spec { __u64 val_off; - enum usdt_arg_type arg_type; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + enum usdt_arg_type arg_type: 8; + __u16 idx_reg_off: 12; + __u16 scale_bitshift: 4; + __u8 __reserved: 8; /* keep reg_off offset stable */ +#else + __u8 __reserved: 8; /* keep reg_off offset stable */ + __u16 idx_reg_off: 12; + __u16 scale_bitshift: 4; + enum usdt_arg_type arg_type: 8; +#endif short reg_off; bool arg_signed; char arg_bitshift; @@ -1283,11 +1294,51 @@ static int calc_pt_regs_off(const char *reg_name) static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz) { - char reg_name[16]; - int len, reg_off; - long off; + char reg_name[16] = {0}, idx_reg_name[16] = {0}; + int len, reg_off, idx_reg_off, scale = 1; + long off = 0; + + if (sscanf(arg_str, " %d @ %ld ( %%%15[^,] , %%%15[^,] , %d ) %n", + arg_sz, &off, reg_name, idx_reg_name, &scale, &len) == 5 || + sscanf(arg_str, " %d @ ( %%%15[^,] , %%%15[^,] , %d ) %n", + arg_sz, reg_name, idx_reg_name, &scale, &len) == 4 || + sscanf(arg_str, " %d @ %ld ( %%%15[^,] , %%%15[^)] ) %n", + arg_sz, &off, reg_name, idx_reg_name, &len) == 4 || + sscanf(arg_str, " %d @ ( %%%15[^,] , %%%15[^)] ) %n", + arg_sz, reg_name, idx_reg_name, &len) == 3 + ) { + /* + * Scale Index Base case: + * 1@-96(%rbp,%rax,8) + * 1@(%rbp,%rax,8) + * 1@-96(%rbp,%rax) + * 1@(%rbp,%rax) + */ + arg->arg_type = USDT_ARG_SIB; + arg->val_off = off; - if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", arg_sz, &off, reg_name, &len) == 3) { + reg_off = calc_pt_regs_off(reg_name); + if (reg_off < 0) + return reg_off; + arg->reg_off = reg_off; + + idx_reg_off = calc_pt_regs_off(idx_reg_name); + if (idx_reg_off < 0) + return idx_reg_off; + arg->idx_reg_off = idx_reg_off; + + /* validate scale factor and set fields directly */ + switch (scale) { + case 1: arg->scale_bitshift = 0; break; + case 2: arg->scale_bitshift = 1; break; + case 4: arg->scale_bitshift = 2; break; + case 8: arg->scale_bitshift = 3; break; + default: + pr_warn("usdt: invalid SIB scale %d, expected 1, 2, 4, 8\n", scale); + return -EINVAL; + } + } else if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", + arg_sz, &off, reg_name, &len) == 3) { /* Memory dereference case, e.g., -4@-20(%rbp) */ arg->arg_type = USDT_ARG_REG_DEREF; arg->val_off = off; @@ -1306,6 +1357,7 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec } else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) { /* Register read case, e.g., -4@%eax */ arg->arg_type = USDT_ARG_REG; + /* register read has no memory offset */ arg->val_off = 0; reg_off = calc_pt_regs_off(reg_name); -- cgit v1.2.3 From b39c915a4f365cce6bdc0e538ed95d31823aea8f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 21 Aug 2025 09:38:19 -0700 Subject: libperf event: Ensure tracing data is multiple of 8 sized Perf's synthetic-events.c will ensure 8-byte alignment of tracing data, writing it after a perf_record_header_tracing_data event. Add padding to struct perf_record_header_tracing_data to make it 16-byte rather than 12-byte sized. Fixes: 055c67ed39887c55 ("perf tools: Move event synthesizing routines to separate .c file") Reviewed-by: James Clark Signed-off-by: Ian Rogers Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Athira Rajeev Cc: Blake Jones Cc: Chun-Tse Shao Cc: Collin Funk Cc: Howard Chu Cc: Ingo Molnar Cc: Jan Polensky Cc: Jiri Olsa Cc: Kan Liang Cc: Li Huafei Cc: Mark Rutland Cc: Nam Cao Cc: Peter Zijlstra Cc: Steinar H. Gunderson Cc: Thomas Gleixner Link: https://lore.kernel.org/r/20250821163820.1132977-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/include/perf/event.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/lib') diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h index 6608f1e3701b..aa1e91c97a22 100644 --- a/tools/lib/perf/include/perf/event.h +++ b/tools/lib/perf/include/perf/event.h @@ -291,6 +291,7 @@ struct perf_record_header_event_type { struct perf_record_header_tracing_data { struct perf_event_header header; __u32 size; + __u32 pad; }; #define PERF_RECORD_MISC_BUILD_ID_SIZE (1 << 15) -- cgit v1.2.3 From b338cf849ec82a3063119c9902c5ae21bc9dccb1 Mon Sep 17 00:00:00 2001 From: Jiawei Zhao Date: Thu, 4 Sep 2025 03:05:23 +0000 Subject: libbpf: Remove unused args in parse_usdt_note Remove unused 'elf' and 'path' parameters from parse_usdt_note function signature. These parameters are not referenced within the function body and only add unnecessary complexity. The function only requires the note header, data buffer, offsets, and output structure to perform USDT note parsing. Update function declaration, definition, and the single call site in collect_usdt_targets() to match the simplified signature. This is a safe internal cleanup as parse_usdt_note is a static function. Signed-off-by: Jiawei Zhao Signed-off-by: Andrii Nakryiko Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20250904030525.1932293-1-phoenix500526@163.com --- tools/lib/bpf/usdt.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c index 867bff6b0699..fc2785eecc17 100644 --- a/tools/lib/bpf/usdt.c +++ b/tools/lib/bpf/usdt.c @@ -581,9 +581,8 @@ static struct elf_seg *find_vma_seg(struct elf_seg *segs, size_t seg_cnt, long o return NULL; } -static int parse_usdt_note(Elf *elf, const char *path, GElf_Nhdr *nhdr, - const char *data, size_t name_off, size_t desc_off, - struct usdt_note *usdt_note); +static int parse_usdt_note(GElf_Nhdr *nhdr, const char *data, size_t name_off, + size_t desc_off, struct usdt_note *usdt_note); static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie); @@ -637,7 +636,7 @@ static int collect_usdt_targets(struct usdt_manager *man, Elf *elf, const char * struct elf_seg *seg = NULL; void *tmp; - err = parse_usdt_note(elf, path, &nhdr, data->d_buf, name_off, desc_off, ¬e); + err = parse_usdt_note(&nhdr, data->d_buf, name_off, desc_off, ¬e); if (err) goto err_out; @@ -1143,8 +1142,7 @@ err_out: /* Parse out USDT ELF note from '.note.stapsdt' section. * Logic inspired by perf's code. */ -static int parse_usdt_note(Elf *elf, const char *path, GElf_Nhdr *nhdr, - const char *data, size_t name_off, size_t desc_off, +static int parse_usdt_note(GElf_Nhdr *nhdr, const char *data, size_t name_off, size_t desc_off, struct usdt_note *note) { const char *provider, *name, *args; -- cgit v1.2.3 From a5edf3550f4260504b7e0ab3d40d13ffe924b773 Mon Sep 17 00:00:00 2001 From: hupu Date: Wed, 10 Sep 2025 16:16:55 +0800 Subject: perf subcmd: avoid crash in exclude_cmds when excludes is empty When cross-compiling the perf tool for ARM64, `perf help` may crash with the following assertion failure: help.c:122: exclude_cmds: Assertion `cmds->names[ci] == NULL' failed. This happens when the perf binary is not named exactly "perf" or when multiple "perf-*" binaries exist in the same directory. In such cases, the `excludes` command list can be empty, which leads to the final assertion in exclude_cmds() being triggered. Add a simple guard at the beginning of exclude_cmds() to return early if excludes->cnt is zero, preventing the crash. Signed-off-by: hupu Reported-by: Guilherme Amadio Reviewed-by: Namhyung Kim Link: https://lore.kernel.org/r/20250909094953.106706-1-amadio@gentoo.org Signed-off-by: Namhyung Kim --- tools/lib/subcmd/help.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/subcmd/help.c b/tools/lib/subcmd/help.c index 9ef569492560..ddaeb4eb3e24 100644 --- a/tools/lib/subcmd/help.c +++ b/tools/lib/subcmd/help.c @@ -75,6 +75,9 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) size_t ci, cj, ei; int cmp; + if (!excludes->cnt) + return; + ci = cj = ei = 0; while (ci < cmds->cnt && ei < excludes->cnt) { cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); -- cgit v1.2.3 From c297fe3e9f9917e8bfd569442290736a551bfc60 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Sun, 14 Sep 2025 23:51:32 +0200 Subject: libbpf: Implement SHA256 internal helper Use AF_ALG sockets to not have libbpf depend on OpenSSL. The helper is used for the loader generation code to embed the metadata hash in the loader program and also by the bpf_map__make_exclusive API to calculate the hash of the program the map is exclusive to. Acked-by: Andrii Nakryiko Signed-off-by: KP Singh Link: https://lore.kernel.org/r/20250914215141.15144-4-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf.c | 59 +++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 4 +++ 2 files changed, 63 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index fe4fc5438678..a39640bd5448 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -43,6 +43,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -14217,3 +14220,59 @@ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s) free(s->progs); free(s); } + +int libbpf_sha256(const void *data, size_t data_sz, void *sha_out, size_t sha_out_sz) +{ + struct sockaddr_alg sa = { + .salg_family = AF_ALG, + .salg_type = "hash", + .salg_name = "sha256" + }; + int sock_fd = -1; + int op_fd = -1; + int err = 0; + + if (sha_out_sz != SHA256_DIGEST_LENGTH) { + pr_warn("sha_out_sz should be exactly 32 bytes for a SHA256 digest"); + return -EINVAL; + } + + sock_fd = socket(AF_ALG, SOCK_SEQPACKET, 0); + if (sock_fd < 0) { + err = -errno; + pr_warn("failed to create AF_ALG socket for SHA256: %s\n", errstr(err)); + return err; + } + + if (bind(sock_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { + err = -errno; + pr_warn("failed to bind to AF_ALG socket for SHA256: %s\n", errstr(err)); + goto out; + } + + op_fd = accept(sock_fd, NULL, 0); + if (op_fd < 0) { + err = -errno; + pr_warn("failed to accept from AF_ALG socket for SHA256: %s\n", errstr(err)); + goto out; + } + + if (write(op_fd, data, data_sz) != data_sz) { + err = -errno; + pr_warn("failed to write data to AF_ALG socket for SHA256: %s\n", errstr(err)); + goto out; + } + + if (read(op_fd, sha_out, SHA256_DIGEST_LENGTH) != SHA256_DIGEST_LENGTH) { + err = -errno; + pr_warn("failed to read SHA256 from AF_ALG socket: %s\n", errstr(err)); + goto out; + } + +out: + if (op_fd >= 0) + close(op_fd); + if (sock_fd >= 0) + close(sock_fd); + return err; +} diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 477a3b3389a0..8a055de0d324 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -736,4 +736,8 @@ int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern, int probe_fd(int fd); +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DWORD_SIZE SHA256_DIGEST_LENGTH / sizeof(__u64) + +int libbpf_sha256(const void *data, size_t data_sz, void *sha_out, size_t sha_out_sz); #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ -- cgit v1.2.3 From 567010a5478ff4cbf1f14a01fa03cb50f68ac354 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Sun, 14 Sep 2025 23:51:33 +0200 Subject: libbpf: Support exclusive map creation Implement setters and getters that allow map to be registered as exclusive to the specified program. The registration should be done before the exclusive program is loaded. Signed-off-by: KP Singh Acked-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20250914215141.15144-5-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/bpf.c | 4 ++- tools/lib/bpf/bpf.h | 5 +++- tools/lib/bpf/libbpf.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 22 +++++++++++++++ tools/lib/bpf/libbpf.map | 3 +++ 5 files changed, 101 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index ab40dbf9f020..19ad7bcf0c2f 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -172,7 +172,7 @@ int bpf_map_create(enum bpf_map_type map_type, __u32 max_entries, const struct bpf_map_create_opts *opts) { - const size_t attr_sz = offsetofend(union bpf_attr, map_token_fd); + const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size); union bpf_attr attr; int fd; @@ -203,6 +203,8 @@ int bpf_map_create(enum bpf_map_type map_type, attr.map_ifindex = OPTS_GET(opts, map_ifindex, 0); attr.map_token_fd = OPTS_GET(opts, token_fd, 0); + attr.excl_prog_hash = ptr_to_u64(OPTS_GET(opts, excl_prog_hash, NULL)); + attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0); fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz); return libbpf_err_errno(fd); diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 7252150e7ad3..e983a3e40d61 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -54,9 +54,12 @@ struct bpf_map_create_opts { __s32 value_type_btf_obj_fd; __u32 token_fd; + + const void *excl_prog_hash; + __u32 excl_prog_hash_size; size_t :0; }; -#define bpf_map_create_opts__last_field token_fd +#define bpf_map_create_opts__last_field excl_prog_hash_size LIBBPF_API int bpf_map_create(enum bpf_map_type map_type, const char *map_name, diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index a39640bd5448..5161c2b39875 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -499,6 +499,7 @@ struct bpf_program { __u32 line_info_rec_size; __u32 line_info_cnt; __u32 prog_flags; + __u8 hash[SHA256_DIGEST_LENGTH]; }; struct bpf_struct_ops { @@ -578,6 +579,7 @@ struct bpf_map { bool autocreate; bool autoattach; __u64 map_extra; + struct bpf_program *excl_prog; }; enum extern_type { @@ -4488,6 +4490,44 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx) } } +static int bpf_prog_compute_hash(struct bpf_program *prog) +{ + struct bpf_insn *purged; + int i, err; + + purged = calloc(prog->insns_cnt, BPF_INSN_SZ); + if (!purged) + return -ENOMEM; + + /* If relocations have been done, the map_fd needs to be + * discarded for the digest calculation. + */ + for (i = 0; i < prog->insns_cnt; i++) { + purged[i] = prog->insns[i]; + if (purged[i].code == (BPF_LD | BPF_IMM | BPF_DW) && + (purged[i].src_reg == BPF_PSEUDO_MAP_FD || + purged[i].src_reg == BPF_PSEUDO_MAP_VALUE)) { + purged[i].imm = 0; + i++; + if (i >= prog->insns_cnt || + prog->insns[i].code != 0 || + prog->insns[i].dst_reg != 0 || + prog->insns[i].src_reg != 0 || + prog->insns[i].off != 0) { + err = -EINVAL; + goto out; + } + purged[i] = prog->insns[i]; + purged[i].imm = 0; + } + } + err = libbpf_sha256(purged, prog->insns_cnt * sizeof(struct bpf_insn), + prog->hash, SHA256_DIGEST_LENGTH); +out: + free(purged); + return err; +} + static int bpf_program__record_reloc(struct bpf_program *prog, struct reloc_desc *reloc_desc, __u32 insn_idx, const char *sym_name, @@ -5237,6 +5277,14 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b create_attr.token_fd = obj->token_fd; if (obj->token_fd) create_attr.map_flags |= BPF_F_TOKEN_FD; + if (map->excl_prog) { + err = bpf_prog_compute_hash(map->excl_prog); + if (err) + return err; + + create_attr.excl_prog_hash = map->excl_prog->hash; + create_attr.excl_prog_hash_size = SHA256_DIGEST_LENGTH; + } if (bpf_map__is_struct_ops(map)) { create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id; @@ -10527,6 +10575,27 @@ int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd) return 0; } +int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog) +{ + if (map_is_created(map)) { + pr_warn("exclusive programs must be set before map creation\n"); + return libbpf_err(-EINVAL); + } + + if (map->obj != prog->obj) { + pr_warn("excl_prog and map must be from the same bpf object\n"); + return libbpf_err(-EINVAL); + } + + map->excl_prog = prog; + return 0; +} + +struct bpf_program *bpf_map__exclusive_program(struct bpf_map *map) +{ + return map->excl_prog; +} + static struct bpf_map * __bpf_map__iter(const struct bpf_map *m, const struct bpf_object *obj, int i) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 2e91148d9b44..e978bc093c39 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -1291,6 +1291,28 @@ LIBBPF_API int bpf_map__lookup_and_delete_elem(const struct bpf_map *map, */ LIBBPF_API int bpf_map__get_next_key(const struct bpf_map *map, const void *cur_key, void *next_key, size_t key_sz); +/** + * @brief **bpf_map__set_exclusive_program()** sets a map to be exclusive to the + * specified program. This must be called *before* the map is created. + * + * @param map BPF map to make exclusive. + * @param prog BPF program to be the exclusive user of the map. Must belong + * to the same bpf_object as the map. + * @return 0 on success; a negative error code otherwise. + * + * This function must be called after the BPF object is opened but before + * it is loaded. Once the object is loaded, only the specified program + * will be able to access the map's contents. + */ +LIBBPF_API int bpf_map__set_exclusive_program(struct bpf_map *map, struct bpf_program *prog); + +/** + * @brief **bpf_map__exclusive_program()** returns the exclusive program + * that is registered with the map (if any). + * @param map BPF map to which the exclusive program is registered. + * @return the registered exclusive program. + */ +LIBBPF_API struct bpf_program *bpf_map__exclusive_program(struct bpf_map *map); struct bpf_xdp_set_link_opts { size_t sz; diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index d7bd463e7017..8ed8749907d4 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -448,4 +448,7 @@ LIBBPF_1.6.0 { } LIBBPF_1.5.0; LIBBPF_1.7.0 { + global: + bpf_map__set_exclusive_program; + bpf_map__exclusive_program; } LIBBPF_1.6.0; -- cgit v1.2.3 From 349271568303695f0ac3563af153d2b4542f6986 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Sun, 21 Sep 2025 18:01:16 +0200 Subject: bpf: Implement signature verification for BPF programs This patch extends the BPF_PROG_LOAD command by adding three new fields to `union bpf_attr` in the user-space API: - signature: A pointer to the signature blob. - signature_size: The size of the signature blob. - keyring_id: The serial number of a loaded kernel keyring (e.g., the user or session keyring) containing the trusted public keys. When a BPF program is loaded with a signature, the kernel: 1. Retrieves the trusted keyring using the provided `keyring_id`. 2. Verifies the supplied signature against the BPF program's instruction buffer. 3. If the signature is valid and was generated by a key in the trusted keyring, the program load proceeds. 4. If no signature is provided, the load proceeds as before, allowing for backward compatibility. LSMs can chose to restrict unsigned programs and implement a security policy. 5. If signature verification fails for any reason, the program is not loaded. Tested-by: syzbot@syzkaller.appspotmail.com Signed-off-by: KP Singh Link: https://lore.kernel.org/r/20250921160120.9711-2-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov --- crypto/asymmetric_keys/pkcs7_verify.c | 1 + include/linux/verification.h | 1 + include/uapi/linux/bpf.h | 10 ++++++++ kernel/bpf/helpers.c | 2 +- kernel/bpf/syscall.c | 45 ++++++++++++++++++++++++++++++++++- tools/include/uapi/linux/bpf.h | 10 ++++++++ tools/lib/bpf/bpf.c | 2 +- 7 files changed, 68 insertions(+), 3 deletions(-) (limited to 'tools/lib') diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index f0d4ff3c20a8..6d6475e3a9bf 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -429,6 +429,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, /* Authattr presence checked in parser */ break; case VERIFYING_UNSPECIFIED_SIGNATURE: + case VERIFYING_BPF_SIGNATURE: if (pkcs7->data_type != OID_data) { pr_warn("Invalid unspecified sig (not pkcs7-data)\n"); return -EKEYREJECTED; diff --git a/include/linux/verification.h b/include/linux/verification.h index 4f3022d081c3..dec7f2beabfd 100644 --- a/include/linux/verification.h +++ b/include/linux/verification.h @@ -36,6 +36,7 @@ enum key_being_used_for { VERIFYING_KEY_SIGNATURE, VERIFYING_KEY_SELF_SIGNATURE, VERIFYING_UNSPECIFIED_SIGNATURE, + VERIFYING_BPF_SIGNATURE, NR__KEY_BEING_USED_FOR }; #ifdef CONFIG_SYSTEM_DATA_VERIFICATION diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0987b52d5648..f3b173e48b0f 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1611,6 +1611,16 @@ union bpf_attr { * continuous. */ __u32 fd_array_cnt; + /* Pointer to a buffer containing the signature of the BPF + * program. + */ + __aligned_u64 signature; + /* Size of the signature buffer in bytes. */ + __u32 signature_size; + /* ID of the kernel keyring to be used for signature + * verification. + */ + __s32 keyring_id; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index ef4ede8bb74f..969f63f8ca28 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -3898,7 +3898,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p, return verify_pkcs7_signature(data, data_len, sig, sig_len, trusted_keyring->key, - VERIFYING_UNSPECIFIED_SIGNATURE, NULL, + VERIFYING_BPF_SIGNATURE, NULL, NULL); #else return -EOPNOTSUPP; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index cf7173b1bb83..8a3c3d26f6e2 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -2785,8 +2786,44 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type) } } +static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr, + bool is_kernel) +{ + bpfptr_t usig = make_bpfptr(attr->signature, is_kernel); + struct bpf_dynptr_kern sig_ptr, insns_ptr; + struct bpf_key *key = NULL; + void *sig; + int err = 0; + + if (system_keyring_id_check(attr->keyring_id) == 0) + key = bpf_lookup_system_key(attr->keyring_id); + else + key = bpf_lookup_user_key(attr->keyring_id, 0); + + if (!key) + return -EINVAL; + + sig = kvmemdup_bpfptr(usig, attr->signature_size); + if (IS_ERR(sig)) { + bpf_key_put(key); + return -ENOMEM; + } + + bpf_dynptr_init(&sig_ptr, sig, BPF_DYNPTR_TYPE_LOCAL, 0, + attr->signature_size); + bpf_dynptr_init(&insns_ptr, prog->insnsi, BPF_DYNPTR_TYPE_LOCAL, 0, + prog->len * sizeof(struct bpf_insn)); + + err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&insns_ptr, + (struct bpf_dynptr *)&sig_ptr, key); + + bpf_key_put(key); + kvfree(sig); + return err; +} + /* last field in 'union bpf_attr' used by this command */ -#define BPF_PROG_LOAD_LAST_FIELD fd_array_cnt +#define BPF_PROG_LOAD_LAST_FIELD keyring_id static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size) { @@ -2950,6 +2987,12 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size) /* eBPF programs must be GPL compatible to use GPL-ed functions */ prog->gpl_compatible = license_is_gpl_compatible(license) ? 1 : 0; + if (attr->signature) { + err = bpf_prog_verify_signature(prog, attr, uattr.is_kernel); + if (err) + goto free_prog; + } + prog->orig_prog = NULL; prog->jited = 0; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 0987b52d5648..f3b173e48b0f 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1611,6 +1611,16 @@ union bpf_attr { * continuous. */ __u32 fd_array_cnt; + /* Pointer to a buffer containing the signature of the BPF + * program. + */ + __aligned_u64 signature; + /* Size of the signature buffer in bytes. */ + __u32 signature_size; + /* ID of the kernel keyring to be used for signature + * verification. + */ + __s32 keyring_id; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 19ad7bcf0c2f..339b19797237 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -240,7 +240,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, size_t insn_cnt, struct bpf_prog_load_opts *opts) { - const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt); + const size_t attr_sz = offsetofend(union bpf_attr, keyring_id); void *finfo = NULL, *linfo = NULL; const char *func_info, *line_info; __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd; -- cgit v1.2.3 From fb2b0e290147ba01a53dfd92cf91058c9d2ee254 Mon Sep 17 00:00:00 2001 From: KP Singh Date: Sun, 21 Sep 2025 18:01:17 +0200 Subject: libbpf: Update light skeleton for signing * The metadata map is created with as an exclusive map (with an excl_prog_hash) This restricts map access exclusively to the signed loader program, preventing tampering by other processes. * The map is then frozen, making it read-only from userspace. * BPF_OBJ_GET_INFO_BY_ID instructs the kernel to compute the hash of the metadata map (H') and store it in bpf_map->sha. * The loader is then loaded with the signature which is then verified by the kernel. loading signed programs prebuilt into the kernel are not currently supported. These can supported by enabling BPF_OBJ_GET_INFO_BY_ID to be called from the kernel. Signed-off-by: KP Singh Link: https://lore.kernel.org/r/20250921160120.9711-3-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/skel_internal.h | 76 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h index 4d5fa079b5d6..6a8f5c7a02eb 100644 --- a/tools/lib/bpf/skel_internal.h +++ b/tools/lib/bpf/skel_internal.h @@ -13,10 +13,15 @@ #include #include #include +#include #include #include "bpf.h" #endif +#ifndef SHA256_DIGEST_LENGTH +#define SHA256_DIGEST_LENGTH 32 +#endif + #ifndef __NR_bpf # if defined(__mips__) && defined(_ABIO32) # define __NR_bpf 4355 @@ -64,6 +69,11 @@ struct bpf_load_and_run_opts { __u32 data_sz; __u32 insns_sz; const char *errstr; + void *signature; + __u32 signature_sz; + __s32 keyring_id; + void *excl_prog_hash; + __u32 excl_prog_hash_sz; }; long kern_sys_bpf(__u32 cmd, void *attr, __u32 attr_size); @@ -220,14 +230,19 @@ static inline int skel_map_create(enum bpf_map_type map_type, const char *map_name, __u32 key_size, __u32 value_size, - __u32 max_entries) + __u32 max_entries, + const void *excl_prog_hash, + __u32 excl_prog_hash_sz) { - const size_t attr_sz = offsetofend(union bpf_attr, map_extra); + const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size); union bpf_attr attr; memset(&attr, 0, attr_sz); attr.map_type = map_type; + attr.excl_prog_hash = (unsigned long) excl_prog_hash; + attr.excl_prog_hash_size = excl_prog_hash_sz; + strncpy(attr.map_name, map_name, sizeof(attr.map_name)); attr.key_size = key_size; attr.value_size = value_size; @@ -300,6 +315,35 @@ static inline int skel_link_create(int prog_fd, int target_fd, return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz); } +static inline int skel_obj_get_info_by_fd(int fd) +{ + const size_t attr_sz = offsetofend(union bpf_attr, info); + __u8 sha[SHA256_DIGEST_LENGTH]; + struct bpf_map_info info; + __u32 info_len = sizeof(info); + union bpf_attr attr; + + memset(&info, 0, sizeof(info)); + info.hash = (long) &sha; + info.hash_size = SHA256_DIGEST_LENGTH; + + memset(&attr, 0, attr_sz); + attr.info.bpf_fd = fd; + attr.info.info = (long) &info; + attr.info.info_len = info_len; + return skel_sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz); +} + +static inline int skel_map_freeze(int fd) +{ + const size_t attr_sz = offsetofend(union bpf_attr, map_fd); + union bpf_attr attr; + + memset(&attr, 0, attr_sz); + attr.map_fd = fd; + + return skel_sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz); +} #ifdef __KERNEL__ #define set_err #else @@ -308,12 +352,13 @@ static inline int skel_link_create(int prog_fd, int target_fd, static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) { - const size_t prog_load_attr_sz = offsetofend(union bpf_attr, fd_array); + const size_t prog_load_attr_sz = offsetofend(union bpf_attr, keyring_id); const size_t test_run_attr_sz = offsetofend(union bpf_attr, test); int map_fd = -1, prog_fd = -1, key = 0, err; union bpf_attr attr; - err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1); + err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1, + opts->excl_prog_hash, opts->excl_prog_hash_sz); if (map_fd < 0) { opts->errstr = "failed to create loader map"; set_err; @@ -327,11 +372,34 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) goto out; } +#ifndef __KERNEL__ + err = skel_map_freeze(map_fd); + if (err < 0) { + opts->errstr = "failed to freeze map"; + set_err; + goto out; + } + err = skel_obj_get_info_by_fd(map_fd); + if (err < 0) { + opts->errstr = "failed to fetch obj info"; + set_err; + goto out; + } +#endif + memset(&attr, 0, prog_load_attr_sz); attr.prog_type = BPF_PROG_TYPE_SYSCALL; attr.insns = (long) opts->insns; attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn); attr.license = (long) "Dual BSD/GPL"; +#ifndef __KERNEL__ + attr.signature = (long) opts->signature; + attr.signature_size = opts->signature_sz; +#else + if (opts->signature || opts->signature_sz) + pr_warn("signatures are not supported from bpf_preload\n"); +#endif + attr.keyring_id = opts->keyring_id; memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog")); attr.fd_array = (long) &map_fd; attr.log_level = opts->ctx->log_level; -- cgit v1.2.3 From ea923080c14578504c2e142760d9de547e38e87c Mon Sep 17 00:00:00 2001 From: KP Singh Date: Sun, 21 Sep 2025 18:01:18 +0200 Subject: libbpf: Embed and verify the metadata hash in the loader To fulfill the BPF signing contract, represented as Sig(I_loader || H_meta), the generated trusted loader program must verify the integrity of the metadata. This signature cryptographically binds the loader's instructions (I_loader) to a hash of the metadata (H_meta). The verification process is embedded directly into the loader program. Upon execution, the loader loads the runtime hash from struct bpf_map i.e. BPF_PSEUDO_MAP_IDX and compares this runtime hash against an expected hash value that has been hardcoded directly by bpf_obj__gen_loader. The load from bpf_map can be improved by calling BPF_OBJ_GET_INFO_BY_FD from the kernel context after BPF_OBJ_GET_INFO_BY_FD has been updated for being called from the kernel context. The following instructions are generated: ld_imm64 r1, const_ptr_to_map // insn[0].src_reg == BPF_PSEUDO_MAP_IDX r2 = *(u64 *)(r1 + 0); ld_imm64 r3, sha256_of_map_part1 // constant precomputed by bpftool (part of H_meta) if r2 != r3 goto out; r2 = *(u64 *)(r1 + 8); ld_imm64 r3, sha256_of_map_part2 // (part of H_meta) if r2 != r3 goto out; r2 = *(u64 *)(r1 + 16); ld_imm64 r3, sha256_of_map_part3 // (part of H_meta) if r2 != r3 goto out; r2 = *(u64 *)(r1 + 24); ld_imm64 r3, sha256_of_map_part4 // (part of H_meta) if r2 != r3 goto out; ... Signed-off-by: KP Singh Link: https://lore.kernel.org/r/20250921160120.9711-4-kpsingh@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/bpf_gen_internal.h | 2 ++ tools/lib/bpf/gen_loader.c | 55 ++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 3 ++- 3 files changed, 59 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/bpf_gen_internal.h b/tools/lib/bpf/bpf_gen_internal.h index 6ff963a491d9..49af4260b8e6 100644 --- a/tools/lib/bpf/bpf_gen_internal.h +++ b/tools/lib/bpf/bpf_gen_internal.h @@ -4,6 +4,7 @@ #define __BPF_GEN_INTERNAL_H #include "bpf.h" +#include "libbpf_internal.h" struct ksym_relo_desc { const char *name; @@ -50,6 +51,7 @@ struct bpf_gen { __u32 nr_ksyms; int fd_array; int nr_fd_array; + int hash_insn_offset[SHA256_DWORD_SIZE]; }; void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps); diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index 113ae4abd345..376eef292d3a 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -110,6 +110,7 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in static int add_data(struct bpf_gen *gen, const void *data, __u32 size); static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off); +static void emit_signature_match(struct bpf_gen *gen); void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps) { @@ -152,6 +153,8 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps /* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */ emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7)); emit(gen, BPF_EXIT_INSN()); + if (OPTS_GET(gen->opts, gen_hash, false)) + emit_signature_match(gen); } static int add_data(struct bpf_gen *gen, const void *data, __u32 size) @@ -368,6 +371,8 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off) __emit_sys_close(gen); } +static int compute_sha_udpate_offsets(struct bpf_gen *gen); + int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) { int i; @@ -394,6 +399,12 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) blob_fd_array_off(gen, i)); emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0)); emit(gen, BPF_EXIT_INSN()); + if (OPTS_GET(gen->opts, gen_hash, false)) { + gen->error = compute_sha_udpate_offsets(gen); + if (gen->error) + return gen->error; + } + pr_debug("gen: finish %s\n", errstr(gen->error)); if (!gen->error) { struct gen_loader_opts *opts = gen->opts; @@ -446,6 +457,27 @@ void bpf_gen__free(struct bpf_gen *gen) _val; \ }) +static int compute_sha_udpate_offsets(struct bpf_gen *gen) +{ + __u64 sha[SHA256_DWORD_SIZE]; + __u64 sha_dw; + int i, err; + + err = libbpf_sha256(gen->data_start, gen->data_cur - gen->data_start, sha, SHA256_DIGEST_LENGTH); + if (err < 0) { + pr_warn("sha256 computation of the metadata failed"); + return err; + } + for (i = 0; i < SHA256_DWORD_SIZE; i++) { + struct bpf_insn *insn = + (struct bpf_insn *)(gen->insn_start + gen->hash_insn_offset[i]); + sha_dw = tgt_endian(sha[i]); + insn[0].imm = (__u32)sha_dw; + insn[1].imm = sha_dw >> 32; + } + return 0; +} + void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data, __u32 btf_raw_size) { @@ -557,6 +589,29 @@ void bpf_gen__map_create(struct bpf_gen *gen, emit_sys_close_stack(gen, stack_off(inner_map_fd)); } +static void emit_signature_match(struct bpf_gen *gen) +{ + __s64 off; + int i; + + for (i = 0; i < SHA256_DWORD_SIZE; i++) { + emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX, + 0, 0, 0, 0)); + emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, i * sizeof(__u64))); + gen->hash_insn_offset[i] = gen->insn_cur - gen->insn_start; + emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_3, 0, 0, 0, 0, 0)); + + off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1; + if (is_simm16(off)) { + emit(gen, BPF_MOV64_IMM(BPF_REG_7, -EINVAL)); + emit(gen, BPF_JMP_REG(BPF_JNE, BPF_REG_2, BPF_REG_3, off)); + } else { + gen->error = -ERANGE; + emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1)); + } + } +} + void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name, enum bpf_attach_type type) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index e978bc093c39..5118d0a90e24 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -1857,9 +1857,10 @@ struct gen_loader_opts { const char *insns; __u32 data_sz; __u32 insns_sz; + bool gen_hash; }; -#define gen_loader_opts__last_field insns_sz +#define gen_loader_opts__last_field gen_hash LIBBPF_API int bpf_object__gen_loader(struct bpf_object *obj, struct gen_loader_opts *opts); -- cgit v1.2.3 From 0cc114dc358cf8da2ca23a366e761e89a46ca277 Mon Sep 17 00:00:00 2001 From: "D. Wythe" Date: Fri, 26 Sep 2025 15:17:51 +0800 Subject: libbpf: Fix error when st-prefix_ops and ops from differ btf When a module registers a struct_ops, the struct_ops type and its corresponding map_value type ("bpf_struct_ops_") may reside in different btf objects, here are four possible case: +--------+---------------+-------------+---------------------------------+ | |bpf_struct_ops_| xxx_ops | | +--------+---------------+-------------+---------------------------------+ | case 0 | btf_vmlinux | btf_vmlinux | be used and reg only in vmlinux | +--------+---------------+-------------+---------------------------------+ | case 1 | btf_vmlinux | mod_btf | INVALID | +--------+---------------+-------------+---------------------------------+ | case 2 | mod_btf | btf_vmlinux | reg in mod but be used both in | | | | | vmlinux and mod. | +--------+---------------+-------------+---------------------------------+ | case 3 | mod_btf | mod_btf | be used and reg only in mod | +--------+---------------+-------------+---------------------------------+ Currently we figure out the mod_btf by searching with the struct_ops type, which makes it impossible to figure out the mod_btf when the struct_ops type is in btf_vmlinux while it's corresponding map_value type is in mod_btf (case 2). The fix is to use the corresponding map_value type ("bpf_struct_ops_") as the lookup anchor instead of the struct_ops type to figure out the `btf` and `mod_btf` via find_ksym_btf_id(), and then we can locate the kern_type_id via btf__find_by_name_kind() with the `btf` we just obtained from find_ksym_btf_id(). With this change the lookup obtains the correct btf and mod_btf for case 2, preserves correct behavior for other valid cases, and still fails as expected for the invalid scenario (case 1). Fixes: 590a00888250 ("bpf: libbpf: Add STRUCT_OPS support") Signed-off-by: D. Wythe Signed-off-by: Andrii Nakryiko Acked-by: Andrii Nakryiko Acked-by: Martin KaFai Lau Link: https://lore.kernel.org/bpf/20250926071751.108293-1-alibuda@linux.alibaba.com --- tools/lib/bpf/libbpf.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 5161c2b39875..7edb36aa88e1 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -1018,35 +1018,33 @@ find_struct_ops_kern_types(struct bpf_object *obj, const char *tname_raw, const struct btf_member *kern_data_member; struct btf *btf = NULL; __s32 kern_vtype_id, kern_type_id; - char tname[256]; + char tname[192], stname[256]; __u32 i; snprintf(tname, sizeof(tname), "%.*s", (int)bpf_core_essential_name_len(tname_raw), tname_raw); - kern_type_id = find_ksym_btf_id(obj, tname, BTF_KIND_STRUCT, - &btf, mod_btf); - if (kern_type_id < 0) { - pr_warn("struct_ops init_kern: struct %s is not found in kernel BTF\n", - tname); - return kern_type_id; - } - kern_type = btf__type_by_id(btf, kern_type_id); + snprintf(stname, sizeof(stname), "%s%s", STRUCT_OPS_VALUE_PREFIX, tname); - /* Find the corresponding "map_value" type that will be used - * in map_update(BPF_MAP_TYPE_STRUCT_OPS). For example, - * find "struct bpf_struct_ops_tcp_congestion_ops" from the - * btf_vmlinux. + /* Look for the corresponding "map_value" type that will be used + * in map_update(BPF_MAP_TYPE_STRUCT_OPS) first, figure out the btf + * and the mod_btf. + * For example, find "struct bpf_struct_ops_tcp_congestion_ops". */ - kern_vtype_id = find_btf_by_prefix_kind(btf, STRUCT_OPS_VALUE_PREFIX, - tname, BTF_KIND_STRUCT); + kern_vtype_id = find_ksym_btf_id(obj, stname, BTF_KIND_STRUCT, &btf, mod_btf); if (kern_vtype_id < 0) { - pr_warn("struct_ops init_kern: struct %s%s is not found in kernel BTF\n", - STRUCT_OPS_VALUE_PREFIX, tname); + pr_warn("struct_ops init_kern: struct %s is not found in kernel BTF\n", stname); return kern_vtype_id; } kern_vtype = btf__type_by_id(btf, kern_vtype_id); + kern_type_id = btf__find_by_name_kind(btf, tname, BTF_KIND_STRUCT); + if (kern_type_id < 0) { + pr_warn("struct_ops init_kern: struct %s is not found in kernel BTF\n", tname); + return kern_type_id; + } + kern_type = btf__type_by_id(btf, kern_type_id); + /* Find "struct tcp_congestion_ops" from * struct bpf_struct_ops_tcp_congestion_ops { * [ ... ] @@ -1059,8 +1057,8 @@ find_struct_ops_kern_types(struct bpf_object *obj, const char *tname_raw, break; } if (i == btf_vlen(kern_vtype)) { - pr_warn("struct_ops init_kern: struct %s data is not found in struct %s%s\n", - tname, STRUCT_OPS_VALUE_PREFIX, tname); + pr_warn("struct_ops init_kern: struct %s data is not found in struct %s\n", + tname, stname); return -EINVAL; } -- cgit v1.2.3 From 4ef77dd584cfd915526328f516fec59e3a54d66e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 27 Sep 2025 17:38:33 -0700 Subject: libbpf: Replace AF_ALG with open coded SHA-256 Reimplement libbpf_sha256() using some basic SHA-256 C code. This eliminates the newly-added dependency on AF_ALG, which is a problematic UAPI that is not supported by all kernels. Make libbpf_sha256() return void, since it can no longer fail. This simplifies some callers. Also drop the unnecessary 'sha_out_sz' parameter. Finally, also fix the typo in "compute_sha_udpate_offsets". Fixes: c297fe3e9f99 ("libbpf: Implement SHA256 internal helper") Signed-off-by: Eric Biggers Link: https://lore.kernel.org/r/20250928003833.138407-1-ebiggers@kernel.org Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/gen_loader.c | 20 ++---- tools/lib/bpf/libbpf.c | 143 +++++++++++++++++++++++++--------------- tools/lib/bpf/libbpf_internal.h | 2 +- 3 files changed, 98 insertions(+), 67 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index 376eef292d3a..6945dd99a846 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -371,7 +371,7 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off) __emit_sys_close(gen); } -static int compute_sha_udpate_offsets(struct bpf_gen *gen); +static void compute_sha_update_offsets(struct bpf_gen *gen); int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) { @@ -399,11 +399,8 @@ int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps) blob_fd_array_off(gen, i)); emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0)); emit(gen, BPF_EXIT_INSN()); - if (OPTS_GET(gen->opts, gen_hash, false)) { - gen->error = compute_sha_udpate_offsets(gen); - if (gen->error) - return gen->error; - } + if (OPTS_GET(gen->opts, gen_hash, false)) + compute_sha_update_offsets(gen); pr_debug("gen: finish %s\n", errstr(gen->error)); if (!gen->error) { @@ -457,17 +454,13 @@ void bpf_gen__free(struct bpf_gen *gen) _val; \ }) -static int compute_sha_udpate_offsets(struct bpf_gen *gen) +static void compute_sha_update_offsets(struct bpf_gen *gen) { __u64 sha[SHA256_DWORD_SIZE]; __u64 sha_dw; - int i, err; + int i; - err = libbpf_sha256(gen->data_start, gen->data_cur - gen->data_start, sha, SHA256_DIGEST_LENGTH); - if (err < 0) { - pr_warn("sha256 computation of the metadata failed"); - return err; - } + libbpf_sha256(gen->data_start, gen->data_cur - gen->data_start, (__u8 *)sha); for (i = 0; i < SHA256_DWORD_SIZE; i++) { struct bpf_insn *insn = (struct bpf_insn *)(gen->insn_start + gen->hash_insn_offset[i]); @@ -475,7 +468,6 @@ static int compute_sha_udpate_offsets(struct bpf_gen *gen) insn[0].imm = (__u32)sha_dw; insn[1].imm = sha_dw >> 32; } - return 0; } void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data, diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 7edb36aa88e1..f92083f51bdb 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -43,9 +44,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -4491,7 +4489,7 @@ bpf_object__section_to_libbpf_map_type(const struct bpf_object *obj, int shndx) static int bpf_prog_compute_hash(struct bpf_program *prog) { struct bpf_insn *purged; - int i, err; + int i, err = 0; purged = calloc(prog->insns_cnt, BPF_INSN_SZ); if (!purged) @@ -4519,8 +4517,8 @@ static int bpf_prog_compute_hash(struct bpf_program *prog) purged[i].imm = 0; } } - err = libbpf_sha256(purged, prog->insns_cnt * sizeof(struct bpf_insn), - prog->hash, SHA256_DIGEST_LENGTH); + libbpf_sha256(purged, prog->insns_cnt * sizeof(struct bpf_insn), + prog->hash); out: free(purged); return err; @@ -14288,58 +14286,99 @@ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s) free(s); } -int libbpf_sha256(const void *data, size_t data_sz, void *sha_out, size_t sha_out_sz) +static inline __u32 ror32(__u32 v, int bits) { - struct sockaddr_alg sa = { - .salg_family = AF_ALG, - .salg_type = "hash", - .salg_name = "sha256" - }; - int sock_fd = -1; - int op_fd = -1; - int err = 0; + return (v >> bits) | (v << (32 - bits)); +} - if (sha_out_sz != SHA256_DIGEST_LENGTH) { - pr_warn("sha_out_sz should be exactly 32 bytes for a SHA256 digest"); - return -EINVAL; - } +#define SHA256_BLOCK_LENGTH 64 +#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define Sigma_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22)) +#define Sigma_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25)) +#define sigma_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3)) +#define sigma_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10)) - sock_fd = socket(AF_ALG, SOCK_SEQPACKET, 0); - if (sock_fd < 0) { - err = -errno; - pr_warn("failed to create AF_ALG socket for SHA256: %s\n", errstr(err)); - return err; - } +static const __u32 sha256_K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; - if (bind(sock_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { - err = -errno; - pr_warn("failed to bind to AF_ALG socket for SHA256: %s\n", errstr(err)); - goto out; - } +#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) \ + { \ + __u32 tmp = h + Sigma_1(e) + Ch(e, f, g) + sha256_K[i] + w[i]; \ + d += tmp; \ + h = tmp + Sigma_0(a) + Maj(a, b, c); \ + } + +static void sha256_blocks(__u32 state[8], const __u8 *data, size_t nblocks) +{ + while (nblocks--) { + __u32 a = state[0]; + __u32 b = state[1]; + __u32 c = state[2]; + __u32 d = state[3]; + __u32 e = state[4]; + __u32 f = state[5]; + __u32 g = state[6]; + __u32 h = state[7]; + __u32 w[64]; + int i; + + for (i = 0; i < 16; i++) + w[i] = get_unaligned_be32(&data[4 * i]); + for (; i < ARRAY_SIZE(w); i++) + w[i] = sigma_1(w[i - 2]) + w[i - 7] + + sigma_0(w[i - 15]) + w[i - 16]; + for (i = 0; i < ARRAY_SIZE(w); i += 8) { + SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h); + SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g); + SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f); + SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e); + SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d); + SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c); + SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b); + SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a); + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + data += SHA256_BLOCK_LENGTH; + } +} + +void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]) +{ + __u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; + const __be64 bitcount = cpu_to_be64((__u64)len * 8); + __u8 final_data[2 * SHA256_BLOCK_LENGTH] = { 0 }; + size_t final_len = len % SHA256_BLOCK_LENGTH; + int i; - op_fd = accept(sock_fd, NULL, 0); - if (op_fd < 0) { - err = -errno; - pr_warn("failed to accept from AF_ALG socket for SHA256: %s\n", errstr(err)); - goto out; - } + sha256_blocks(state, data, len / SHA256_BLOCK_LENGTH); - if (write(op_fd, data, data_sz) != data_sz) { - err = -errno; - pr_warn("failed to write data to AF_ALG socket for SHA256: %s\n", errstr(err)); - goto out; - } + memcpy(final_data, data + len - final_len, final_len); + final_data[final_len] = 0x80; + final_len = round_up(final_len + 9, SHA256_BLOCK_LENGTH); + memcpy(&final_data[final_len - 8], &bitcount, 8); - if (read(op_fd, sha_out, SHA256_DIGEST_LENGTH) != SHA256_DIGEST_LENGTH) { - err = -errno; - pr_warn("failed to read SHA256 from AF_ALG socket: %s\n", errstr(err)); - goto out; - } + sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH); -out: - if (op_fd >= 0) - close(op_fd); - if (sock_fd >= 0) - close(sock_fd); - return err; + for (i = 0; i < ARRAY_SIZE(state); i++) + put_unaligned_be32(state[i], &out[4 * i]); } diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 8a055de0d324..c93797dcaf5b 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -739,5 +739,5 @@ int probe_fd(int fd); #define SHA256_DIGEST_LENGTH 32 #define SHA256_DWORD_SIZE SHA256_DIGEST_LENGTH / sizeof(__u64) -int libbpf_sha256(const void *data, size_t data_sz, void *sha_out, size_t sha_out_sz); +void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]); #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ -- cgit v1.2.3 From 44d42bd80804d117fd83b849820e26dafd25a5f9 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 1 Oct 2025 10:13:22 -0700 Subject: libbpf: make libbpf_errno.c into more generic libbpf_utils.c Libbpf is missing one convenient place to put common "utils"-like code that is generic and usable from multiple places. Use libbpf_errno.c as the base for more generic libbpf_utils.c. Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20251001171326.3883055-2-andrii@kernel.org Signed-off-by: Alexei Starovoitov Acked-by: Eduard Zingerman --- tools/lib/bpf/Build | 2 +- tools/lib/bpf/libbpf_errno.c | 75 -------------------------------------------- tools/lib/bpf/libbpf_utils.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 76 deletions(-) delete mode 100644 tools/lib/bpf/libbpf_errno.c create mode 100644 tools/lib/bpf/libbpf_utils.c (limited to 'tools/lib') diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build index e2cd558ca0b4..c30927135fd6 100644 --- a/tools/lib/bpf/Build +++ b/tools/lib/bpf/Build @@ -1,4 +1,4 @@ -libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o str_error.o \ +libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_utils.o str_error.o \ netlink.o bpf_prog_linfo.o libbpf_probes.o hashmap.o \ btf_dump.o ringbuf.o strset.o linker.o gen_loader.o relo_core.o \ usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.o diff --git a/tools/lib/bpf/libbpf_errno.c b/tools/lib/bpf/libbpf_errno.c deleted file mode 100644 index 6b180172ec6b..000000000000 --- a/tools/lib/bpf/libbpf_errno.c +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) - -/* - * Copyright (C) 2013-2015 Alexei Starovoitov - * Copyright (C) 2015 Wang Nan - * Copyright (C) 2015 Huawei Inc. - * Copyright (C) 2017 Nicira, Inc. - */ - -#undef _GNU_SOURCE -#include -#include - -#include "libbpf.h" -#include "libbpf_internal.h" - -/* make sure libbpf doesn't use kernel-only integer typedefs */ -#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 - -#define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START) -#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c) -#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) - -static const char *libbpf_strerror_table[NR_ERRNO] = { - [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", - [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", - [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", - [ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch", - [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", - [ERRCODE_OFFSET(RELOC)] = "Relocation failed", - [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", - [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", - [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", - [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", - [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message", - [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence", - [ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing", -}; - -int libbpf_strerror(int err, char *buf, size_t size) -{ - int ret; - - if (!buf || !size) - return libbpf_err(-EINVAL); - - err = err > 0 ? err : -err; - - if (err < __LIBBPF_ERRNO__START) { - ret = strerror_r(err, buf, size); - buf[size - 1] = '\0'; - return libbpf_err_errno(ret); - } - - if (err < __LIBBPF_ERRNO__END) { - const char *msg; - - msg = libbpf_strerror_table[ERRNO_OFFSET(err)]; - ret = snprintf(buf, size, "%s", msg); - buf[size - 1] = '\0'; - /* The length of the buf and msg is positive. - * A negative number may be returned only when the - * size exceeds INT_MAX. Not likely to appear. - */ - if (ret >= size) - return libbpf_err(-ERANGE); - return 0; - } - - ret = snprintf(buf, size, "Unknown libbpf error %d", err); - buf[size - 1] = '\0'; - if (ret >= size) - return libbpf_err(-ERANGE); - return libbpf_err(-ENOENT); -} diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c new file mode 100644 index 000000000000..6b180172ec6b --- /dev/null +++ b/tools/lib/bpf/libbpf_utils.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +/* + * Copyright (C) 2013-2015 Alexei Starovoitov + * Copyright (C) 2015 Wang Nan + * Copyright (C) 2015 Huawei Inc. + * Copyright (C) 2017 Nicira, Inc. + */ + +#undef _GNU_SOURCE +#include +#include + +#include "libbpf.h" +#include "libbpf_internal.h" + +/* make sure libbpf doesn't use kernel-only integer typedefs */ +#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 + +#define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START) +#define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c) +#define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) + +static const char *libbpf_strerror_table[NR_ERRNO] = { + [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", + [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", + [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", + [ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch", + [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", + [ERRCODE_OFFSET(RELOC)] = "Relocation failed", + [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", + [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", + [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", + [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", + [ERRCODE_OFFSET(WRNGPID)] = "Wrong pid in netlink message", + [ERRCODE_OFFSET(INVSEQ)] = "Invalid netlink sequence", + [ERRCODE_OFFSET(NLPARSE)] = "Incorrect netlink message parsing", +}; + +int libbpf_strerror(int err, char *buf, size_t size) +{ + int ret; + + if (!buf || !size) + return libbpf_err(-EINVAL); + + err = err > 0 ? err : -err; + + if (err < __LIBBPF_ERRNO__START) { + ret = strerror_r(err, buf, size); + buf[size - 1] = '\0'; + return libbpf_err_errno(ret); + } + + if (err < __LIBBPF_ERRNO__END) { + const char *msg; + + msg = libbpf_strerror_table[ERRNO_OFFSET(err)]; + ret = snprintf(buf, size, "%s", msg); + buf[size - 1] = '\0'; + /* The length of the buf and msg is positive. + * A negative number may be returned only when the + * size exceeds INT_MAX. Not likely to appear. + */ + if (ret >= size) + return libbpf_err(-ERANGE); + return 0; + } + + ret = snprintf(buf, size, "Unknown libbpf error %d", err); + buf[size - 1] = '\0'; + if (ret >= size) + return libbpf_err(-ERANGE); + return libbpf_err(-ENOENT); +} -- cgit v1.2.3 From d05ab6181be0060ca259a49e69de9bc95b19edb7 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 1 Oct 2025 10:13:23 -0700 Subject: libbpf: remove unused libbpf_strerror_r and STRERR_BUFSIZE libbpf_strerror_r() is not exposed as public API and neither is it used inside libbpf itself. Remove it altogether. Same for STRERR_BUFSIZE, it's just an orphaned leftover constant which we missed to clean up some time earlier. Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20251001171326.3883055-3-andrii@kernel.org Signed-off-by: Alexei Starovoitov Acked-by: Eduard Zingerman --- tools/lib/bpf/libbpf.c | 2 -- tools/lib/bpf/str_error.c | 24 ------------------------ tools/lib/bpf/str_error.h | 4 ---- 3 files changed, 30 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index f92083f51bdb..c21bc61f5ff4 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -319,8 +319,6 @@ static void pr_perm_msg(int err) buf); } -#define STRERR_BUFSIZE 128 - /* Copied from tools/perf/util/util.h */ #ifndef zfree # define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) diff --git a/tools/lib/bpf/str_error.c b/tools/lib/bpf/str_error.c index 9a541762f54c..92dbd801102f 100644 --- a/tools/lib/bpf/str_error.c +++ b/tools/lib/bpf/str_error.c @@ -12,30 +12,6 @@ /* make sure libbpf doesn't use kernel-only integer typedefs */ #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 -/* - * Wrapper to allow for building in non-GNU systems such as Alpine Linux's musl - * libc, while checking strerror_r() return to avoid having to check this in - * all places calling it. - */ -char *libbpf_strerror_r(int err, char *dst, int len) -{ - int ret = strerror_r(err < 0 ? -err : err, dst, len); - /* on glibc <2.13, ret == -1 and errno is set, if strerror_r() can't - * handle the error, on glibc >=2.13 *positive* (errno-like) error - * code is returned directly - */ - if (ret == -1) - ret = errno; - if (ret) { - if (ret == EINVAL) - /* strerror_r() doesn't recognize this specific error */ - snprintf(dst, len, "unknown error (%d)", err < 0 ? err : -err); - else - snprintf(dst, len, "ERROR: strerror_r(%d)=%d", err, ret); - } - return dst; -} - const char *libbpf_errstr(int err) { static __thread char buf[12]; diff --git a/tools/lib/bpf/str_error.h b/tools/lib/bpf/str_error.h index 53e7fbffc13e..d4c82eec034d 100644 --- a/tools/lib/bpf/str_error.h +++ b/tools/lib/bpf/str_error.h @@ -2,10 +2,6 @@ #ifndef __LIBBPF_STR_ERROR_H #define __LIBBPF_STR_ERROR_H -#define STRERR_BUFSIZE 128 - -char *libbpf_strerror_r(int err, char *dst, int len); - /** * @brief **libbpf_errstr()** returns string corresponding to numeric errno * @param err negative numeric errno -- cgit v1.2.3 From c68b6fdc3600466e3c265bad34d099eb8c5280f1 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 1 Oct 2025 10:13:24 -0700 Subject: libbpf: move libbpf_errstr() into libbpf_utils.c Get rid of str_err.{c,h} by moving implementation of libbpf_errstr() into libbpf_utils.c and declarations into libbpf_internal.h. Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20251001171326.3883055-4-andrii@kernel.org Signed-off-by: Alexei Starovoitov Acked-by: Eduard Zingerman --- tools/lib/bpf/Build | 2 +- tools/lib/bpf/btf.c | 1 - tools/lib/bpf/btf_dump.c | 1 - tools/lib/bpf/elf.c | 1 - tools/lib/bpf/features.c | 1 - tools/lib/bpf/gen_loader.c | 3 +- tools/lib/bpf/libbpf.c | 1 - tools/lib/bpf/libbpf_internal.h | 10 ++++++ tools/lib/bpf/libbpf_utils.c | 72 +++++++++++++++++++++++++++++++++++++ tools/lib/bpf/linker.c | 1 - tools/lib/bpf/relo_core.c | 1 - tools/lib/bpf/ringbuf.c | 1 - tools/lib/bpf/str_error.c | 80 ----------------------------------------- tools/lib/bpf/str_error.h | 15 -------- tools/lib/bpf/usdt.c | 1 - 15 files changed, 84 insertions(+), 107 deletions(-) delete mode 100644 tools/lib/bpf/str_error.c delete mode 100644 tools/lib/bpf/str_error.h (limited to 'tools/lib') diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build index c30927135fd6..c80204bb72a2 100644 --- a/tools/lib/bpf/Build +++ b/tools/lib/bpf/Build @@ -1,4 +1,4 @@ -libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_utils.o str_error.o \ +libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_utils.o \ netlink.o bpf_prog_linfo.o libbpf_probes.o hashmap.o \ btf_dump.o ringbuf.o strset.o linker.o gen_loader.o relo_core.o \ usdt.o zip.o elf.o features.o btf_iter.o btf_relocate.o diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 37682908cb0f..18907f0fcf9f 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -23,7 +23,6 @@ #include "libbpf_internal.h" #include "hashmap.h" #include "strset.h" -#include "str_error.h" #define BTF_MAX_NR_TYPES 0x7fffffffU #define BTF_MAX_STR_OFFSET 0x7fffffffU diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index f09f25eccf3c..6388392f49a0 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -21,7 +21,6 @@ #include "hashmap.h" #include "libbpf.h" #include "libbpf_internal.h" -#include "str_error.h" static const char PREFIXES[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t"; static const size_t PREFIX_CNT = sizeof(PREFIXES) - 1; diff --git a/tools/lib/bpf/elf.c b/tools/lib/bpf/elf.c index 823f83ad819c..295dbda24580 100644 --- a/tools/lib/bpf/elf.c +++ b/tools/lib/bpf/elf.c @@ -9,7 +9,6 @@ #include #include "libbpf_internal.h" -#include "str_error.h" /* A SHT_GNU_versym section holds 16-bit words. This bit is set if * the symbol is hidden and can only be seen when referenced using an diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c index 760657f5224c..b842b83e2480 100644 --- a/tools/lib/bpf/features.c +++ b/tools/lib/bpf/features.c @@ -6,7 +6,6 @@ #include "libbpf.h" #include "libbpf_common.h" #include "libbpf_internal.h" -#include "str_error.h" static inline __u64 ptr_to_u64(const void *ptr) { diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index 6945dd99a846..cd5c2543f54d 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "btf.h" @@ -13,8 +14,6 @@ #include "hashmap.h" #include "bpf_gen_internal.h" #include "skel_internal.h" -#include -#include "str_error.h" #define MAX_USED_MAPS 64 #define MAX_USED_PROGS 32 diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index c21bc61f5ff4..6d19e0db492c 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -51,7 +51,6 @@ #include "libbpf.h" #include "bpf.h" #include "btf.h" -#include "str_error.h" #include "libbpf_internal.h" #include "hashmap.h" #include "bpf_gen_internal.h" diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index c93797dcaf5b..a8f204139371 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -172,6 +172,16 @@ do { \ #define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__) #define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__) +/** + * @brief **libbpf_errstr()** returns string corresponding to numeric errno + * @param err negative numeric errno + * @return pointer to string representation of the errno, that is invalidated + * upon the next call. + */ +const char *libbpf_errstr(int err); + +#define errstr(err) libbpf_errstr(err) + #ifndef __has_builtin #define __has_builtin(x) 0 #endif diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c index 6b180172ec6b..ee3013e9b77c 100644 --- a/tools/lib/bpf/libbpf_utils.c +++ b/tools/lib/bpf/libbpf_utils.c @@ -10,10 +10,15 @@ #undef _GNU_SOURCE #include #include +#include #include "libbpf.h" #include "libbpf_internal.h" +#ifndef ENOTSUPP +#define ENOTSUPP 524 +#endif + /* make sure libbpf doesn't use kernel-only integer typedefs */ #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 @@ -73,3 +78,70 @@ int libbpf_strerror(int err, char *buf, size_t size) return libbpf_err(-ERANGE); return libbpf_err(-ENOENT); } + +const char *libbpf_errstr(int err) +{ + static __thread char buf[12]; + + if (err > 0) + err = -err; + + switch (err) { + case -E2BIG: return "-E2BIG"; + case -EACCES: return "-EACCES"; + case -EADDRINUSE: return "-EADDRINUSE"; + case -EADDRNOTAVAIL: return "-EADDRNOTAVAIL"; + case -EAGAIN: return "-EAGAIN"; + case -EALREADY: return "-EALREADY"; + case -EBADF: return "-EBADF"; + case -EBADFD: return "-EBADFD"; + case -EBUSY: return "-EBUSY"; + case -ECANCELED: return "-ECANCELED"; + case -ECHILD: return "-ECHILD"; + case -EDEADLK: return "-EDEADLK"; + case -EDOM: return "-EDOM"; + case -EEXIST: return "-EEXIST"; + case -EFAULT: return "-EFAULT"; + case -EFBIG: return "-EFBIG"; + case -EILSEQ: return "-EILSEQ"; + case -EINPROGRESS: return "-EINPROGRESS"; + case -EINTR: return "-EINTR"; + case -EINVAL: return "-EINVAL"; + case -EIO: return "-EIO"; + case -EISDIR: return "-EISDIR"; + case -ELOOP: return "-ELOOP"; + case -EMFILE: return "-EMFILE"; + case -EMLINK: return "-EMLINK"; + case -EMSGSIZE: return "-EMSGSIZE"; + case -ENAMETOOLONG: return "-ENAMETOOLONG"; + case -ENFILE: return "-ENFILE"; + case -ENODATA: return "-ENODATA"; + case -ENODEV: return "-ENODEV"; + case -ENOENT: return "-ENOENT"; + case -ENOEXEC: return "-ENOEXEC"; + case -ENOLINK: return "-ENOLINK"; + case -ENOMEM: return "-ENOMEM"; + case -ENOSPC: return "-ENOSPC"; + case -ENOTBLK: return "-ENOTBLK"; + case -ENOTDIR: return "-ENOTDIR"; + case -ENOTSUPP: return "-ENOTSUPP"; + case -ENOTTY: return "-ENOTTY"; + case -ENXIO: return "-ENXIO"; + case -EOPNOTSUPP: return "-EOPNOTSUPP"; + case -EOVERFLOW: return "-EOVERFLOW"; + case -EPERM: return "-EPERM"; + case -EPIPE: return "-EPIPE"; + case -EPROTO: return "-EPROTO"; + case -EPROTONOSUPPORT: return "-EPROTONOSUPPORT"; + case -ERANGE: return "-ERANGE"; + case -EROFS: return "-EROFS"; + case -ESPIPE: return "-ESPIPE"; + case -ESRCH: return "-ESRCH"; + case -ETXTBSY: return "-ETXTBSY"; + case -EUCLEAN: return "-EUCLEAN"; + case -EXDEV: return "-EXDEV"; + default: + snprintf(buf, sizeof(buf), "%d", err); + return buf; + } +} diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c index a469e5d4fee7..56ae77047bc3 100644 --- a/tools/lib/bpf/linker.c +++ b/tools/lib/bpf/linker.c @@ -25,7 +25,6 @@ #include "btf.h" #include "libbpf_internal.h" #include "strset.h" -#include "str_error.h" #define BTF_EXTERN_SEC ".extern" diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c index 2b83c98a1137..6eea5edba58a 100644 --- a/tools/lib/bpf/relo_core.c +++ b/tools/lib/bpf/relo_core.c @@ -64,7 +64,6 @@ enum libbpf_print_level { #include "libbpf.h" #include "bpf.h" #include "btf.h" -#include "str_error.h" #include "libbpf_internal.h" #endif diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c index 9702b70da444..00ec4837a06d 100644 --- a/tools/lib/bpf/ringbuf.c +++ b/tools/lib/bpf/ringbuf.c @@ -21,7 +21,6 @@ #include "libbpf.h" #include "libbpf_internal.h" #include "bpf.h" -#include "str_error.h" struct ring { ring_buffer_sample_fn sample_cb; diff --git a/tools/lib/bpf/str_error.c b/tools/lib/bpf/str_error.c deleted file mode 100644 index 92dbd801102f..000000000000 --- a/tools/lib/bpf/str_error.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -#undef _GNU_SOURCE -#include -#include -#include -#include "str_error.h" - -#ifndef ENOTSUPP -#define ENOTSUPP 524 -#endif - -/* make sure libbpf doesn't use kernel-only integer typedefs */ -#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 - -const char *libbpf_errstr(int err) -{ - static __thread char buf[12]; - - if (err > 0) - err = -err; - - switch (err) { - case -E2BIG: return "-E2BIG"; - case -EACCES: return "-EACCES"; - case -EADDRINUSE: return "-EADDRINUSE"; - case -EADDRNOTAVAIL: return "-EADDRNOTAVAIL"; - case -EAGAIN: return "-EAGAIN"; - case -EALREADY: return "-EALREADY"; - case -EBADF: return "-EBADF"; - case -EBADFD: return "-EBADFD"; - case -EBUSY: return "-EBUSY"; - case -ECANCELED: return "-ECANCELED"; - case -ECHILD: return "-ECHILD"; - case -EDEADLK: return "-EDEADLK"; - case -EDOM: return "-EDOM"; - case -EEXIST: return "-EEXIST"; - case -EFAULT: return "-EFAULT"; - case -EFBIG: return "-EFBIG"; - case -EILSEQ: return "-EILSEQ"; - case -EINPROGRESS: return "-EINPROGRESS"; - case -EINTR: return "-EINTR"; - case -EINVAL: return "-EINVAL"; - case -EIO: return "-EIO"; - case -EISDIR: return "-EISDIR"; - case -ELOOP: return "-ELOOP"; - case -EMFILE: return "-EMFILE"; - case -EMLINK: return "-EMLINK"; - case -EMSGSIZE: return "-EMSGSIZE"; - case -ENAMETOOLONG: return "-ENAMETOOLONG"; - case -ENFILE: return "-ENFILE"; - case -ENODATA: return "-ENODATA"; - case -ENODEV: return "-ENODEV"; - case -ENOENT: return "-ENOENT"; - case -ENOEXEC: return "-ENOEXEC"; - case -ENOLINK: return "-ENOLINK"; - case -ENOMEM: return "-ENOMEM"; - case -ENOSPC: return "-ENOSPC"; - case -ENOTBLK: return "-ENOTBLK"; - case -ENOTDIR: return "-ENOTDIR"; - case -ENOTSUPP: return "-ENOTSUPP"; - case -ENOTTY: return "-ENOTTY"; - case -ENXIO: return "-ENXIO"; - case -EOPNOTSUPP: return "-EOPNOTSUPP"; - case -EOVERFLOW: return "-EOVERFLOW"; - case -EPERM: return "-EPERM"; - case -EPIPE: return "-EPIPE"; - case -EPROTO: return "-EPROTO"; - case -EPROTONOSUPPORT: return "-EPROTONOSUPPORT"; - case -ERANGE: return "-ERANGE"; - case -EROFS: return "-EROFS"; - case -ESPIPE: return "-ESPIPE"; - case -ESRCH: return "-ESRCH"; - case -ETXTBSY: return "-ETXTBSY"; - case -EUCLEAN: return "-EUCLEAN"; - case -EXDEV: return "-EXDEV"; - default: - snprintf(buf, sizeof(buf), "%d", err); - return buf; - } -} diff --git a/tools/lib/bpf/str_error.h b/tools/lib/bpf/str_error.h deleted file mode 100644 index d4c82eec034d..000000000000 --- a/tools/lib/bpf/str_error.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ -#ifndef __LIBBPF_STR_ERROR_H -#define __LIBBPF_STR_ERROR_H - -/** - * @brief **libbpf_errstr()** returns string corresponding to numeric errno - * @param err negative numeric errno - * @return pointer to string representation of the errno, that is invalidated - * upon the next call. - */ -const char *libbpf_errstr(int err); - -#define errstr(err) libbpf_errstr(err) - -#endif /* __LIBBPF_STR_ERROR_H */ diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c index fc2785eecc17..c174b4086673 100644 --- a/tools/lib/bpf/usdt.c +++ b/tools/lib/bpf/usdt.c @@ -20,7 +20,6 @@ #include "libbpf_common.h" #include "libbpf_internal.h" #include "hashmap.h" -#include "str_error.h" /* libbpf's USDT support consists of BPF-side state/code and user-space * state/code working together in concert. BPF-side parts are defined in -- cgit v1.2.3 From a7f36f81d0bde9e274606f771f7bfd59b2c8c083 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 1 Oct 2025 10:13:25 -0700 Subject: libbpf: move libbpf_sha256() implementation into libbpf_utils.c Move sha256 implementation out of already large and unwieldy libbpf.c into libbpf_utils.c where we'll keep reusable helpers. Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20251001171326.3883055-5-andrii@kernel.org Signed-off-by: Alexei Starovoitov Acked-by: Eduard Zingerman --- tools/lib/bpf/libbpf.c | 98 ----------------------------------------- tools/lib/bpf/libbpf_internal.h | 5 +++ tools/lib/bpf/libbpf_utils.c | 95 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 98 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 6d19e0db492c..dd3b2f57082d 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -14282,100 +14281,3 @@ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s) free(s->progs); free(s); } - -static inline __u32 ror32(__u32 v, int bits) -{ - return (v >> bits) | (v << (32 - bits)); -} - -#define SHA256_BLOCK_LENGTH 64 -#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) -#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define Sigma_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22)) -#define Sigma_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25)) -#define sigma_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3)) -#define sigma_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10)) - -static const __u32 sha256_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -}; - -#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) \ - { \ - __u32 tmp = h + Sigma_1(e) + Ch(e, f, g) + sha256_K[i] + w[i]; \ - d += tmp; \ - h = tmp + Sigma_0(a) + Maj(a, b, c); \ - } - -static void sha256_blocks(__u32 state[8], const __u8 *data, size_t nblocks) -{ - while (nblocks--) { - __u32 a = state[0]; - __u32 b = state[1]; - __u32 c = state[2]; - __u32 d = state[3]; - __u32 e = state[4]; - __u32 f = state[5]; - __u32 g = state[6]; - __u32 h = state[7]; - __u32 w[64]; - int i; - - for (i = 0; i < 16; i++) - w[i] = get_unaligned_be32(&data[4 * i]); - for (; i < ARRAY_SIZE(w); i++) - w[i] = sigma_1(w[i - 2]) + w[i - 7] + - sigma_0(w[i - 15]) + w[i - 16]; - for (i = 0; i < ARRAY_SIZE(w); i += 8) { - SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h); - SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g); - SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f); - SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e); - SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d); - SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c); - SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b); - SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a); - } - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; - data += SHA256_BLOCK_LENGTH; - } -} - -void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]) -{ - __u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - const __be64 bitcount = cpu_to_be64((__u64)len * 8); - __u8 final_data[2 * SHA256_BLOCK_LENGTH] = { 0 }; - size_t final_len = len % SHA256_BLOCK_LENGTH; - int i; - - sha256_blocks(state, data, len / SHA256_BLOCK_LENGTH); - - memcpy(final_data, data + len - final_len, final_len); - final_data[final_len] = 0x80; - final_len = round_up(final_len + 9, SHA256_BLOCK_LENGTH); - memcpy(&final_data[final_len - 8], &bitcount, 8); - - sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH); - - for (i = 0; i < ARRAY_SIZE(state); i++) - put_unaligned_be32(state[i], &out[4 * i]); -} diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index a8f204139371..35b2527bedec 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -722,6 +722,11 @@ static inline bool is_pow_of_2(size_t x) return x && (x & (x - 1)) == 0; } +static inline __u32 ror32(__u32 v, int bits) +{ + return (v >> bits) | (v << (32 - bits)); +} + #define PROG_LOAD_ATTEMPTS 5 int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts); diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c index ee3013e9b77c..f8290a0b3aaf 100644 --- a/tools/lib/bpf/libbpf_utils.c +++ b/tools/lib/bpf/libbpf_utils.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include "libbpf.h" #include "libbpf_internal.h" @@ -145,3 +148,95 @@ const char *libbpf_errstr(int err) return buf; } } + +#define SHA256_BLOCK_LENGTH 64 +#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define Sigma_0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22)) +#define Sigma_1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25)) +#define sigma_0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3)) +#define sigma_1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10)) + +static const __u32 sha256_K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, +}; + +#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) \ + { \ + __u32 tmp = h + Sigma_1(e) + Ch(e, f, g) + sha256_K[i] + w[i]; \ + d += tmp; \ + h = tmp + Sigma_0(a) + Maj(a, b, c); \ + } + +static void sha256_blocks(__u32 state[8], const __u8 *data, size_t nblocks) +{ + while (nblocks--) { + __u32 a = state[0]; + __u32 b = state[1]; + __u32 c = state[2]; + __u32 d = state[3]; + __u32 e = state[4]; + __u32 f = state[5]; + __u32 g = state[6]; + __u32 h = state[7]; + __u32 w[64]; + int i; + + for (i = 0; i < 16; i++) + w[i] = get_unaligned_be32(&data[4 * i]); + for (; i < ARRAY_SIZE(w); i++) + w[i] = sigma_1(w[i - 2]) + w[i - 7] + + sigma_0(w[i - 15]) + w[i - 16]; + for (i = 0; i < ARRAY_SIZE(w); i += 8) { + SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h); + SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g); + SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f); + SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e); + SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d); + SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c); + SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b); + SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a); + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + data += SHA256_BLOCK_LENGTH; + } +} + +void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]) +{ + __u32 state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; + const __be64 bitcount = cpu_to_be64((__u64)len * 8); + __u8 final_data[2 * SHA256_BLOCK_LENGTH] = { 0 }; + size_t final_len = len % SHA256_BLOCK_LENGTH; + int i; + + sha256_blocks(state, data, len / SHA256_BLOCK_LENGTH); + + memcpy(final_data, data + len - final_len, final_len); + final_data[final_len] = 0x80; + final_len = round_up(final_len + 9, SHA256_BLOCK_LENGTH); + memcpy(&final_data[final_len - 8], &bitcount, 8); + + sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH); + + for (i = 0; i < ARRAY_SIZE(state); i++) + put_unaligned_be32(state[i], &out[4 * i]); +} -- cgit v1.2.3 From 4a1c9e544b8dd0c5456e0feb614f427dc46c4835 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 1 Oct 2025 10:13:26 -0700 Subject: libbpf: remove linux/unaligned.h dependency for libbpf_sha256() linux/unaligned.h include dependency is causing issues for libbpf's Github mirror due to {get,put}_unaligned_be32() usage. So get rid of it by implementing custom variants of those macros that will work both in kernel and Github mirror repos. Also switch round_up() to roundup(), as the former is not available in Github mirror (and is just a subtly more specific variant of roundup() anyways). Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/r/20251001171326.3883055-6-andrii@kernel.org Signed-off-by: Alexei Starovoitov Acked-by: Eduard Zingerman --- tools/lib/bpf/libbpf_utils.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c index f8290a0b3aaf..2bae8cafc077 100644 --- a/tools/lib/bpf/libbpf_utils.c +++ b/tools/lib/bpf/libbpf_utils.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "libbpf.h" #include "libbpf_internal.h" @@ -149,6 +148,16 @@ const char *libbpf_errstr(int err) } } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" +struct __packed_u32 { __u32 __val; } __attribute__((packed)); +#pragma GCC diagnostic pop + +#define get_unaligned_be32(p) be32_to_cpu((((struct __packed_u32 *)(p))->__val)) +#define put_unaligned_be32(v, p) do { \ + ((struct __packed_u32 *)(p))->__val = cpu_to_be32(v); \ +} while (0) + #define SHA256_BLOCK_LENGTH 64 #define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) #define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) @@ -232,7 +241,7 @@ void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]) memcpy(final_data, data + len - final_len, final_len); final_data[final_len] = 0x80; - final_len = round_up(final_len + 9, SHA256_BLOCK_LENGTH); + final_len = roundup(final_len + 9, SHA256_BLOCK_LENGTH); memcpy(&final_data[final_len - 8], &bitcount, 8); sha256_blocks(state, final_data, final_len / SHA256_BLOCK_LENGTH); -- cgit v1.2.3 From 8dc364fa484df22d301a16148d1b356931d0cbb0 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sun, 14 Sep 2025 11:24:37 -0700 Subject: libperf mmap: In user mmap rdpmc avoid undefined behavior A shift left of a signed 64-bit s64 may overflow and result in undefined behavior caught by ubsan. Switch to a u64 instead. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ingo Molnar Cc: Jiri Olsa Cc: Kan Liang Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/perf/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/perf/mmap.c b/tools/lib/perf/mmap.c index c1a51d925e0e..ec124eb0ec0a 100644 --- a/tools/lib/perf/mmap.c +++ b/tools/lib/perf/mmap.c @@ -508,7 +508,7 @@ int perf_mmap__read_self(struct perf_mmap *map, struct perf_counts_values *count idx = READ_ONCE(pc->index); cnt = READ_ONCE(pc->offset); if (pc->cap_user_rdpmc && idx) { - s64 evcnt = read_perf_counter(idx - 1); + u64 evcnt = read_perf_counter(idx - 1); u16 width = READ_ONCE(pc->pmc_width); evcnt <<= 64 - width; -- cgit v1.2.3 From 63d2247e2e37d9c589a0a26aa4e684f736a45e29 Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Thu, 2 Oct 2025 13:31:50 -0700 Subject: libbpf: Fix missing #pragma in libbpf_utils.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recent sha256 patch uses a GCC pragma to suppress compile errors for a packed struct, but omits a needed pragma (see related link) and thus still raises errors: (e.g. on GCC 12.3 armhf) libbpf_utils.c:153:29: error: packed attribute causes inefficient alignment for ‘__val’ [-Werror=attributes] 153 | struct __packed_u32 { __u32 __val; } __attribute__((packed)); | ^~~~~ Resolve by adding the GCC diagnostic pragma to ignore "-Wattributes". Link: https://lore.kernel.org/bpf/CAP-5=fXURWoZu2j6Y8xQy23i7=DfgThq3WC1RkGFBx-4moQKYQ@mail.gmail.com/ Fixes: 4a1c9e544b8d ("libbpf: remove linux/unaligned.h dependency for libbpf_sha256()") Signed-off-by: Tony Ambardar Acked-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/libbpf_utils.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c index 2bae8cafc077..5d66bc6ff098 100644 --- a/tools/lib/bpf/libbpf_utils.c +++ b/tools/lib/bpf/libbpf_utils.c @@ -150,6 +150,7 @@ const char *libbpf_errstr(int err) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" +#pragma GCC diagnostic ignored "-Wattributes" struct __packed_u32 { __u32 __val; } __attribute__((packed)); #pragma GCC diagnostic pop -- cgit v1.2.3 From b31f7f725cd932e2c2b41f3e4b66273653953687 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 1 Oct 2025 13:40:55 +0200 Subject: tools: lib: thermal: use pkg-config to locate libnl3 To make libthermal more cross compile friendly use pkg-config to locate libnl3. Only if that fails fall back to hardcoded /usr/include/libnl3. Signed-off-by: Sascha Hauer Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- tools/lib/thermal/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/thermal/Makefile b/tools/lib/thermal/Makefile index a1f5e388644d..fdde0c4f85b4 100644 --- a/tools/lib/thermal/Makefile +++ b/tools/lib/thermal/Makefile @@ -46,8 +46,12 @@ else CFLAGS := -g -Wall endif +NL3_CFLAGS = $(shell pkg-config --cflags libnl-3.0 2>/dev/null) +ifeq ($(NL3_CFLAGS),) +NL3_CFLAGS = -I/usr/include/libnl3 +endif + INCLUDES = \ --I/usr/include/libnl3 \ -I$(srctree)/tools/lib/thermal/include \ -I$(srctree)/tools/lib/ \ -I$(srctree)/tools/include \ @@ -59,6 +63,7 @@ INCLUDES = \ override CFLAGS += $(EXTRA_WARNINGS) override CFLAGS += -Werror -Wall override CFLAGS += -fPIC +override CFLAGS += $(NL3_CFLAGS) override CFLAGS += $(INCLUDES) override CFLAGS += -fvisibility=hidden override CFGLAS += -Wl,-L. -- cgit v1.2.3 From 1375152bb02ab2a8435e87ea27034482dbc95f57 Mon Sep 17 00:00:00 2001 From: Emil Dahl Juhl Date: Wed, 1 Oct 2025 13:40:56 +0200 Subject: tools: lib: thermal: don't preserve owner in install Instead of preserving mode, timestamp, and owner, for the object files during installation, just preserve the mode and timestamp. When installing as root, the installed files should be owned by root. When installing as user, --preserve=ownership doesn't work anyway. This makes --preserve=ownership rather pointless. Signed-off-by: Emil Dahl Juhl Signed-off-by: Sascha Hauer Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- tools/lib/thermal/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/thermal/Makefile b/tools/lib/thermal/Makefile index fdde0c4f85b4..41aa7a324ff4 100644 --- a/tools/lib/thermal/Makefile +++ b/tools/lib/thermal/Makefile @@ -139,7 +139,7 @@ endef install_lib: libs $(call QUIET_INSTALL, $(LIBTHERMAL_ALL)) \ $(call do_install_mkdir,$(libdir_SQ)); \ - cp -fpR $(LIBTHERMAL_ALL) $(DESTDIR)$(libdir_SQ) + cp -fR --preserve=mode,timestamp $(LIBTHERMAL_ALL) $(DESTDIR)$(libdir_SQ) install_headers: $(call QUIET_INSTALL, headers) \ -- cgit v1.2.3 From dea00c204e7e99aca9a4cb8603174c4cd0051728 Mon Sep 17 00:00:00 2001 From: Emil Dahl Juhl Date: Wed, 1 Oct 2025 13:40:57 +0200 Subject: tools: lib: thermal: expose thermal_exit symbols Remove duplicate entry for thermal_init and add the missing entries for thermal_exit and their respectives in cmd, events, and sampling context. Signed-off-by: Emil Dahl Juhl Signed-off-by: Sascha Hauer Acked-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- tools/lib/thermal/libthermal.map | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/thermal/libthermal.map b/tools/lib/thermal/libthermal.map index d657176aa47f..1d3d0c04e4b6 100644 --- a/tools/lib/thermal/libthermal.map +++ b/tools/lib/thermal/libthermal.map @@ -1,6 +1,5 @@ LIBTHERMAL_0.0.1 { global: - thermal_init; for_each_thermal_zone; for_each_thermal_trip; for_each_thermal_cdev; @@ -9,9 +8,12 @@ LIBTHERMAL_0.0.1 { thermal_zone_find_by_id; thermal_zone_discover; thermal_init; + thermal_exit; + thermal_events_exit; thermal_events_init; thermal_events_handle; thermal_events_fd; + thermal_cmd_exit; thermal_cmd_init; thermal_cmd_get_tz; thermal_cmd_get_cdev; @@ -22,6 +24,7 @@ LIBTHERMAL_0.0.1 { thermal_cmd_threshold_add; thermal_cmd_threshold_delete; thermal_cmd_threshold_flush; + thermal_sampling_exit; thermal_sampling_init; thermal_sampling_handle; thermal_sampling_fd; -- cgit v1.2.3 From 4d920ed684392ae064af62957d6f5a90312dfaf6 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Oct 2025 18:20:37 -0700 Subject: libbpf: Fix undefined behavior in {get,put}_unaligned_be32() These violate aliasing rules and may be miscompiled unless -fno-strict-aliasing is used. Replace them with the standard memcpy() solution. Note that compilers know how to optimize this properly. Fixes: 4a1c9e544b8d ("libbpf: remove linux/unaligned.h dependency for libbpf_sha256()") Signed-off-by: Eric Biggers Signed-off-by: Andrii Nakryiko Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20251006012037.159295-1-ebiggers@kernel.org --- tools/lib/bpf/libbpf_utils.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/bpf/libbpf_utils.c b/tools/lib/bpf/libbpf_utils.c index 5d66bc6ff098..ac3beae54cf6 100644 --- a/tools/lib/bpf/libbpf_utils.c +++ b/tools/lib/bpf/libbpf_utils.c @@ -148,16 +148,20 @@ const char *libbpf_errstr(int err) } } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpacked" -#pragma GCC diagnostic ignored "-Wattributes" -struct __packed_u32 { __u32 __val; } __attribute__((packed)); -#pragma GCC diagnostic pop - -#define get_unaligned_be32(p) be32_to_cpu((((struct __packed_u32 *)(p))->__val)) -#define put_unaligned_be32(v, p) do { \ - ((struct __packed_u32 *)(p))->__val = cpu_to_be32(v); \ -} while (0) +static inline __u32 get_unaligned_be32(const void *p) +{ + __be32 val; + + memcpy(&val, p, sizeof(val)); + return be32_to_cpu(val); +} + +static inline void put_unaligned_be32(__u32 val, void *p) +{ + __be32 be_val = cpu_to_be32(val); + + memcpy(p, &be_val, sizeof(be_val)); +} #define SHA256_BLOCK_LENGTH 64 #define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) -- cgit v1.2.3