selftests/bpf: Add tests for a variable that is smaller than its type

Check that a variable in DATASEC that is smaller than its type is not
printed when the map is read from bpffs and when bpftool dumps it.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20261002124714.180012-12-alexei.starovoitov@gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
Alexei Starovoitov 2026-10-02 12:47:10 +00:00 committed by Kumar Kartikeya Dwivedi
parent 124a5a2bc0
commit 87be058a3b
No known key found for this signature in database
GPG Key ID: 472D377B63542F83

View File

@ -2,6 +2,7 @@
#include <test_progs.h>
#include <bpf/btf.h>
#include "bpftool_helpers.h"
#define FUNC_NAME "write_fmt<scx_simple::BpfStream>"
#define KSYM_NAME "write_fmt_scx_simple__BpfStream_"
@ -61,9 +62,81 @@ static void test_func_name(void)
btf__free(btf);
}
#define PIN_PATH "/sys/fs/bpf/btf_rust_piece"
/*
* A piece of a static that LLVM split has the type of the whole static.
* It's the last variable in the section, so its type ends past the map value.
*/
static void test_piece(void)
{
LIBBPF_OPTS(bpf_map_create_opts, opts);
int int_id, struct_id, var_id, piece_id, sec_id, map_fd = -1, key = 0;
__u32 value[2] = { 0x11111111, 0x22222222 };
char line[256] = {}, out[1024] = {};
struct btf *btf;
FILE *f = NULL;
btf = btf__new_empty();
if (!ASSERT_OK_PTR(btf, "btf"))
return;
int_id = btf__add_int(btf, "u32", 4, 0);
ASSERT_GT(int_id, 0, "int");
struct_id = btf__add_struct(btf, "Whole", 8);
ASSERT_GT(struct_id, 0, "struct");
ASSERT_OK(btf__add_field(btf, "a", int_id, 0, 0), "field");
ASSERT_OK(btf__add_field(btf, "b", int_id, 32, 0), "field");
var_id = btf__add_var(btf, "CNT", BTF_VAR_STATIC, int_id);
ASSERT_GT(var_id, 0, "var");
piece_id = btf__add_var(btf, "WHOLE.1", BTF_VAR_STATIC, struct_id);
ASSERT_GT(piece_id, 0, "piece");
sec_id = btf__add_datasec(btf, ".bss", sizeof(value));
ASSERT_GT(sec_id, 0, "datasec");
ASSERT_OK(btf__add_datasec_var_info(btf, var_id, 0, 4), "var info");
ASSERT_OK(btf__add_datasec_var_info(btf, piece_id, 4, 4), "piece info");
if (!ASSERT_OK(btf__load_into_kernel(btf), "btf load"))
goto out;
opts.btf_fd = btf__fd(btf);
opts.btf_value_type_id = sec_id;
map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, ".bss", sizeof(key), sizeof(value), 1, &opts);
if (!ASSERT_GE(map_fd, 0, "map create"))
goto out;
if (!ASSERT_OK(bpf_map_update_elem(map_fd, &key, value, 0), "map update"))
goto out;
/* the variable is printed, the piece is not */
unlink(PIN_PATH);
if (!ASSERT_OK(bpf_obj_pin(map_fd, PIN_PATH), "pin"))
goto out;
f = fopen(PIN_PATH, "r");
if (!ASSERT_OK_PTR(f, "open"))
goto out;
while (fgets(line, sizeof(line), f) && line[0] == '#')
;
ASSERT_HAS_SUBSTR(line, "286331153", "var");
ASSERT_NULL(strstr(line, "572662306"), "piece");
/* the same for bpftool */
if (!ASSERT_OK(get_bpftool_command_output("map dump pinned " PIN_PATH, out, sizeof(out)),
"bpftool"))
goto out;
ASSERT_HAS_SUBSTR(out, "CNT", "var");
ASSERT_NULL(strstr(out, "WHOLE.1"), "piece");
out:
if (f)
fclose(f);
unlink(PIN_PATH);
if (map_fd >= 0)
close(map_fd);
btf__free(btf);
}
/* Serial: programs are not in kallsyms while another test sets bpf_jit_harden */
void serial_test_btf_rust(void)
{
if (test__start_subtest("func_name"))
test_func_name();
if (test__start_subtest("piece"))
test_piece();
}