[PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log

Leon Hwang posted 9 patches 4 days, 23 hours ago
[PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
Posted by Leon Hwang 4 days, 23 hours ago
Add tests to verify that the kernel reports the expected error messages
when map creation fails.

Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
 .../selftests/bpf/prog_tests/map_init.c       | 168 ++++++++++++++++++
 1 file changed, 168 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c
index 14a31109dd0e..89e6daf2fcfd 100644
--- a/tools/testing/selftests/bpf/prog_tests/map_init.c
+++ b/tools/testing/selftests/bpf/prog_tests/map_init.c
@@ -212,3 +212,171 @@ void test_map_init(void)
 	if (test__start_subtest("pcpu_lru_map_init"))
 		test_pcpu_lru_map_init();
 }
+
+#define BPF_LOG_FIXED	8
+
+static void test_map_create(enum bpf_map_type map_type, const char *map_name,
+			    struct bpf_map_create_opts *opts, const char *exp_msg)
+{
+	const int key_size = 4, value_size = 4, max_entries = 1;
+	char log_buf[128];
+	int fd;
+	LIBBPF_OPTS(bpf_log_opts, log_opts);
+
+	log_buf[0] = '\0';
+	log_opts.log_buf = log_buf;
+	log_opts.log_size = sizeof(log_buf);
+	log_opts.log_level = BPF_LOG_FIXED;
+	opts->log_opts = &log_opts;
+	fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, opts);
+	if (!ASSERT_LT(fd, 0, "bpf_map_create")) {
+		close(fd);
+		return;
+	}
+
+	ASSERT_STREQ(log_buf, exp_msg, "log_buf");
+	ASSERT_EQ(log_opts.log_true_size, strlen(exp_msg) + 1, "log_true_size");
+}
+
+static void test_map_create_array(struct bpf_map_create_opts *opts, const char *exp_msg)
+{
+	test_map_create(BPF_MAP_TYPE_ARRAY, "test_map_create", opts, exp_msg);
+}
+
+static void test_invalid_vmlinux_value_type_id_struct_ops(void)
+{
+	const char *msg = "btf_vmlinux_value_type_id can only be used with struct_ops maps.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .btf_vmlinux_value_type_id = 1,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_vmlinux_value_type_id_kv_type_id(void)
+{
+	const char *msg = "btf_vmlinux_value_type_id is mutually exclusive with btf_key_type_id and btf_value_type_id.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .btf_vmlinux_value_type_id = 1,
+		    .btf_key_type_id = 1,
+	);
+
+	test_map_create(BPF_MAP_TYPE_STRUCT_OPS, "test_map_create", &opts, msg);
+}
+
+static void test_invalid_value_type_id(void)
+{
+	const char *msg = "Invalid btf_value_type_id.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .btf_key_type_id = 1,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_extra(void)
+{
+	const char *msg = "Invalid map_extra.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .map_extra = 1,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_numa_node(void)
+{
+	const char *msg = "Invalid numa_node.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .map_flags = BPF_F_NUMA_NODE,
+		    .numa_node = 0xFF,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_type(void)
+{
+	const char *msg = "Invalid map_type.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts);
+
+	test_map_create(__MAX_BPF_MAP_TYPE, "test_map_create", &opts, msg);
+}
+
+static void test_invalid_token_fd(void)
+{
+	const char *msg = "Invalid map_token_fd.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .map_flags = BPF_F_TOKEN_FD,
+		    .token_fd = 0xFF,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_name(void)
+{
+	const char *msg = "Invalid map_name.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts);
+
+	test_map_create(BPF_MAP_TYPE_ARRAY, "test-!@#", &opts, msg);
+}
+
+static void test_invalid_btf_fd(void)
+{
+	const char *msg = "Invalid btf_fd.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .btf_fd = -1,
+		    .btf_key_type_id = 1,
+		    .btf_value_type_id = 1,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_excl_prog_hash_size_1(void)
+{
+	const char *msg = "Invalid excl_prog_hash_size.\n";
+	const char *hash = "DEADCODE";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .excl_prog_hash = hash,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+static void test_excl_prog_hash_size_2(void)
+{
+	const char *msg = "Invalid excl_prog_hash_size.\n";
+	LIBBPF_OPTS(bpf_map_create_opts, opts,
+		    .excl_prog_hash_size = 1,
+	);
+
+	test_map_create_array(&opts, msg);
+}
+
+void test_map_create_failure(void)
+{
+	if (test__start_subtest("invalid_vmlinux_value_type_id_struct_ops"))
+		test_invalid_vmlinux_value_type_id_struct_ops();
+	if (test__start_subtest("invalid_vmlinux_value_type_id_kv_type_id"))
+		test_invalid_vmlinux_value_type_id_kv_type_id();
+	if (test__start_subtest("invalid_value_type_id"))
+		test_invalid_value_type_id();
+	if (test__start_subtest("invalid_map_extra"))
+		test_invalid_map_extra();
+	if (test__start_subtest("invalid_numa_node"))
+		test_invalid_numa_node();
+	if (test__start_subtest("invalid_map_type"))
+		test_invalid_map_type();
+	if (test__start_subtest("invalid_token_fd"))
+		test_invalid_token_fd();
+	if (test__start_subtest("invalid_map_name"))
+		test_invalid_map_name();
+	if (test__start_subtest("invalid_btf_fd"))
+		test_invalid_btf_fd();
+	if (test__start_subtest("invalid_excl_prog_hash_size_1"))
+		test_excl_prog_hash_size_1();
+	if (test__start_subtest("invalid_excl_prog_hash_size_2"))
+		test_excl_prog_hash_size_2();
+}
-- 
2.52.0
Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
Posted by Alexei Starovoitov 2 days, 17 hours ago
On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> +
> +#define BPF_LOG_FIXED  8
> +
> +static void test_map_create(enum bpf_map_type map_type, const char *map_name,
> +                           struct bpf_map_create_opts *opts, const char *exp_msg)
> +{
> +       const int key_size = 4, value_size = 4, max_entries = 1;
> +       char log_buf[128];
> +       int fd;
> +       LIBBPF_OPTS(bpf_log_opts, log_opts);
> +
> +       log_buf[0] = '\0';
> +       log_opts.log_buf = log_buf;
> +       log_opts.log_size = sizeof(log_buf);
> +       log_opts.log_level = BPF_LOG_FIXED;

Why? Which part of the test needs the log with this flag?
Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
Posted by Leon Hwang 2 days, 9 hours ago

On 5/2/26 04:14, Alexei Starovoitov wrote:
> On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>> +
>> +#define BPF_LOG_FIXED  8
>> +
>> +static void test_map_create(enum bpf_map_type map_type, const char *map_name,
>> +                           struct bpf_map_create_opts *opts, const char *exp_msg)
>> +{
>> +       const int key_size = 4, value_size = 4, max_entries = 1;
>> +       char log_buf[128];
>> +       int fd;
>> +       LIBBPF_OPTS(bpf_log_opts, log_opts);
>> +
>> +       log_buf[0] = '\0';
>> +       log_opts.log_buf = log_buf;
>> +       log_opts.log_size = sizeof(log_buf);
>> +       log_opts.log_level = BPF_LOG_FIXED;
> 
> Why? Which part of the test needs the log with this flag?

BPF_LOG_FIXED looks odd here.

This test sets 'log_level = BPF_LOG_FIXED' to match the behavior of
bpf_vlog_init() as initialized by bpf_log_attr_create_vlog() in
patch #7. BPF_LOG_FIXED is intended to be the default log_level
there.

Thanks,
Leon




Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
Posted by Alexei Starovoitov 1 day, 14 hours ago
On Wed, Feb 4, 2026 at 7:54 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
>
>
> On 5/2/26 04:14, Alexei Starovoitov wrote:
> > On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
> >>
> >> +
> >> +#define BPF_LOG_FIXED  8
> >> +
> >> +static void test_map_create(enum bpf_map_type map_type, const char *map_name,
> >> +                           struct bpf_map_create_opts *opts, const char *exp_msg)
> >> +{
> >> +       const int key_size = 4, value_size = 4, max_entries = 1;
> >> +       char log_buf[128];
> >> +       int fd;
> >> +       LIBBPF_OPTS(bpf_log_opts, log_opts);
> >> +
> >> +       log_buf[0] = '\0';
> >> +       log_opts.log_buf = log_buf;
> >> +       log_opts.log_size = sizeof(log_buf);
> >> +       log_opts.log_level = BPF_LOG_FIXED;
> >
> > Why? Which part of the test needs the log with this flag?
>
> BPF_LOG_FIXED looks odd here.
>
> This test sets 'log_level = BPF_LOG_FIXED' to match the behavior of
> bpf_vlog_init() as initialized by bpf_log_attr_create_vlog() in
> patch #7. BPF_LOG_FIXED is intended to be the default log_level
> there.

I don't think you answered my question.
bpf_vlog_init() is using whatever log_level user space provided.
Why do you pass BPF_LOG_FIXED ?
Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
Posted by Leon Hwang 1 day, 10 hours ago

On 6/2/26 07:18, Alexei Starovoitov wrote:
> On Wed, Feb 4, 2026 at 7:54 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>>
>>
>> On 5/2/26 04:14, Alexei Starovoitov wrote:
>>> On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>>>
>>>> +
>>>> +#define BPF_LOG_FIXED  8
>>>> +
>>>> +static void test_map_create(enum bpf_map_type map_type, const char *map_name,
>>>> +                           struct bpf_map_create_opts *opts, const char *exp_msg)
>>>> +{
>>>> +       const int key_size = 4, value_size = 4, max_entries = 1;
>>>> +       char log_buf[128];
>>>> +       int fd;
>>>> +       LIBBPF_OPTS(bpf_log_opts, log_opts);
>>>> +
>>>> +       log_buf[0] = '\0';
>>>> +       log_opts.log_buf = log_buf;
>>>> +       log_opts.log_size = sizeof(log_buf);
>>>> +       log_opts.log_level = BPF_LOG_FIXED;
>>>
>>> Why? Which part of the test needs the log with this flag?
>>
>> BPF_LOG_FIXED looks odd here.
>>
>> This test sets 'log_level = BPF_LOG_FIXED' to match the behavior of
>> bpf_vlog_init() as initialized by bpf_log_attr_create_vlog() in
>> patch #7. BPF_LOG_FIXED is intended to be the default log_level
>> there.
> 
> I don't think you answered my question.
> bpf_vlog_init() is using whatever log_level user space provided.
> Why do you pass BPF_LOG_FIXED ?
>

The intention behind passing BPF_LOG_FIXED was to ensure the log used
the buffer in a fixed mode, since the allocated buffer was large enough
to hold the full log message from the kernel. It was not intended to
test against log_level itself.

After reviewing commit 121664093803 ("bpf: Switch BPF verifier log to be
a rotating log by default"), I realized that BPF_LOG_FIXED was
introduced specifically to disable the rotating log behavior. In this
test case, that distinction is not relevant, so BPF_LOG_FIXED is indeed
unnecessary.

I tested with 'log_level is 0' and 'log_level is non-zero'. The tests
fail when log_level is 0, and pass when log_level is non-zero. So I will
switch to using 'log_level = 1' in the next revision.

Thanks,
Leon