diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 6600e126fbfb..83de8fb9b9aa 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -6278,7 +6278,9 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size, memset(&attr_common, 0, sizeof(attr_common)); if (cmd & BPF_COMMON_ATTRS) { - err = bpf_check_uarg_tail_zero(uattr_common, sizeof(attr_common), size_common); + err = bpf_check_uarg_tail_zero(uattr_common, + offsetofend(struct bpf_common_attr, log_true_size), + size_common); if (err) return err; diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 483c02cf21d1..3cd705802330 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -246,6 +246,9 @@ int bpf_map_create(enum bpf_map_type map_type, attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0); log_opts = OPTS_GET(opts, log_opts, NULL); + if (!OPTS_VALID(log_opts, bpf_log_opts)) + return libbpf_err(-EINVAL); + if (log_opts && feat_supported(NULL, FEAT_BPF_SYSCALL_COMMON_ATTRS)) { memset(&attr_common, 0, attr_common_sz); attr_common.log_buf = ptr_to_u64(OPTS_GET(log_opts, buf, NULL)); diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c index 5c61c8e37306..c804c3ce9be9 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_init.c +++ b/tools/testing/selftests/bpf/prog_tests/map_init.c @@ -306,7 +306,7 @@ 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, + .token_fd = -1, ); test_map_create_array(&opts, msg); @@ -353,6 +353,30 @@ static void test_excl_prog_hash_size_2(void) test_map_create_array(&opts, msg); } +static void test_common_attr_padding(void) +{ + struct bpf_common_attr_fake { + __u8 attrs[offsetofend(struct bpf_common_attr, log_true_size)]; + __u32 pad; + } attr_common = { + .pad = 1, + }; + union bpf_attr attr = { + .map_type = BPF_MAP_TYPE_ARRAY, + .key_size = 4, + .value_size = 4, + .max_entries = 1, + }; + int fd; + + fd = syscall(__NR_bpf, BPF_MAP_CREATE | BPF_COMMON_ATTRS, &attr, sizeof(attr), &attr_common, + sizeof(attr_common)); + if (!ASSERT_LT(fd, 0, "syscall")) + close(fd); + else + ASSERT_EQ(errno, E2BIG, "errno"); +} + void test_map_create_failure(void) { if (test__start_subtest("invalid_vmlinux_value_type_id_struct_ops")) @@ -377,4 +401,6 @@ void test_map_create_failure(void) test_excl_prog_hash_size_1(); if (test__start_subtest("invalid_excl_prog_hash_size_2")) test_excl_prog_hash_size_2(); + if (test__start_subtest("common_attr_padding")) + test_common_attr_padding(); }