Check kernel/bpf/syscall.c:CHECK_ATTR macro implementation. The syscall should fail when we have non-zero memory in the union beyond the last element of the active sub-command struct.
Signed-off-by: Zachary Leaf zachary.leaf@arm.com --- .../kernel/syscalls/bpf/bpf_check_attr.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 testcases/kernel/syscalls/bpf/bpf_check_attr.c
diff --git a/testcases/kernel/syscalls/bpf/bpf_check_attr.c b/testcases/kernel/syscalls/bpf/bpf_check_attr.c new file mode 100644 index 000000000..2ad70ee2e --- /dev/null +++ b/testcases/kernel/syscalls/bpf/bpf_check_attr.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) Arm Ltd. 2023. All rights reserved. + * Author: Zachary Leaf zachary.leaf@arm.com + * + * Check kernel/bpf/syscall.c:CHECK_ATTR macro implementation. The syscall + * should fail when we have non-zero memory in the union beyond the last + * element of the active sub-command struct. + */ + +#include <limits.h> +#include <string.h> +#include <stdio.h> +#include <stddef.h> + +#include "config.h" +#include "tst_test.h" +#include "lapi/bpf.h" +#include "bpf_common.h" + +static char *bpf_log_buf; +static union bpf_attr *attr; + +void run(void) +{ + size_t offset; + char *ptr; + + printf("sizeof(bpf_attr): %lu\n", sizeof(union bpf_attr)); + memset(attr, 0, sizeof(*attr)); + attr->map_type = BPF_MAP_TYPE_ARRAY; + attr->key_size = 4; + attr->value_size = 8; + attr->max_entries = 1; + attr->map_flags = 0; + + /* + * test CHECK_ATTR() macro + * check syscall fails if there is non-null data somewhere beyond + * the last struct member for the BPF_MAP_CREATE option + */ + offset = offsetof(union bpf_attr, map_extra); + printf("offset map_extra: %#lx\n", offset); + offset += 8; + ptr = (char *)attr; + *(ptr+offset) = 'x'; + TST_EXP_FAIL(bpf(BPF_MAP_CREATE, attr, sizeof(*attr)), EINVAL); + + /* remove the non-null data and BPF_MAP_CREATE should pass */ + *(ptr+offset) = '\0'; + TST_EXP_POSITIVE(bpf_map_create(attr)); +} + +static struct tst_test test = { + .test_all = run, + .min_kver = "5.16", /* map_extra field added in commit 9330986c0300 */ + .bufs = (struct tst_buffers []) { + {&bpf_log_buf, .size = BUFSIZE}, + {&attr, .size = sizeof(*attr)}, + {}, + } +};