Context |
Check |
Description |
bpf/vmtest-bpf-next-VM_Test-34 |
success
|
Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-25 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-38 |
success
|
Logs for x86_64-llvm-17 / veristat
|
bpf/vmtest-bpf-next-VM_Test-42 |
success
|
Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-27 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-26 |
success
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-31 |
success
|
Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-39 |
success
|
Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-37 |
success
|
Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-32 |
success
|
Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-33 |
success
|
Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
|
bpf/vmtest-bpf-next-VM_Test-29 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-44 |
success
|
Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-45 |
success
|
Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-43 |
success
|
Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-41 |
success
|
Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-30 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-28 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-40 |
success
|
Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
|
bpf/vmtest-bpf-next-VM_Test-36 |
success
|
Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-46 |
success
|
Logs for x86_64-llvm-18 / veristat
|
bpf/vmtest-bpf-next-VM_Test-35 |
success
|
Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-PR |
fail
|
PR summary
|
netdev/series_format |
success
|
Single patches do not need cover letters
|
netdev/tree_selection |
success
|
Clearly marked for bpf-next
|
netdev/ynl |
success
|
Generated files up to date;
no warnings/errors;
no diff in generated;
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
success
|
Errors and warnings before: 955 this patch: 955
|
netdev/build_tools |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/cc_maintainers |
warning
|
13 maintainers not CCed: sdf@google.com daniel@iogearbox.net kpsingh@kernel.org maxim@isovalent.com martin.lau@linux.dev yonghong.song@linux.dev shuah@kernel.org linux-kselftest@vger.kernel.org mykolal@fb.com haoluo@google.com jolsa@kernel.org song@kernel.org eddyz87@gmail.com
|
netdev/build_clang |
success
|
Errors and warnings before: 955 this patch: 955
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
netdev/check_selftest |
success
|
No net selftest shell script
|
netdev/verify_fixes |
success
|
Fixes tag looks correct
|
netdev/build_allmodconfig_warn |
success
|
Errors and warnings before: 966 this patch: 966
|
netdev/checkpatch |
fail
|
CHECK: Blank lines aren't necessary after an open brace '{'
CHECK: Comparison to NULL could be written "!str_cpy"
CHECK: Comparison to NULL could be written "token"
CHECK: Concatenated strings should use spaces between elements
ERROR: code indent should use tabs where possible
ERROR: open brace '{' following function definitions go on the next line
ERROR: switch and case should be at the same indent
WARNING: Avoid line continuations in quoted strings
WARNING: Missing a blank line after declarations
WARNING: Prefer strscpy over strcpy - see: https://github.com/KSPP/linux/issues/88
WARNING: line length of 116 exceeds 80 columns
WARNING: line length of 87 exceeds 80 columns
WARNING: line length of 88 exceeds 80 columns
WARNING: line length of 90 exceeds 80 columns
WARNING: line length of 92 exceeds 80 columns
WARNING: line length of 94 exceeds 80 columns
WARNING: please, no spaces at the start of a line
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Unittests
|
bpf/vmtest-bpf-next-VM_Test-5 |
success
|
Logs for aarch64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-18 |
fail
|
Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
|
bpf/vmtest-bpf-next-VM_Test-16 |
success
|
Logs for x86_64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-6 |
success
|
Logs for aarch64-gcc / test
|
bpf/vmtest-bpf-next-VM_Test-14 |
success
|
Logs for x86_64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-8 |
fail
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-10 |
success
|
Logs for s390x-gcc / test
|
bpf/vmtest-bpf-next-VM_Test-13 |
fail
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-7 |
success
|
Logs for aarch64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-4 |
fail
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-11 |
success
|
Logs for s390x-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-24 |
success
|
Logs for x86_64-llvm-18 / veristat
|
bpf/vmtest-bpf-next-VM_Test-22 |
fail
|
Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
|
bpf/vmtest-bpf-next-VM_Test-12 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-19 |
success
|
Logs for x86_64-llvm-17 / test
|
bpf/vmtest-bpf-next-VM_Test-9 |
success
|
Logs for s390x-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-20 |
success
|
Logs for x86_64-llvm-17 / veristat
|
bpf/vmtest-bpf-next-VM_Test-21 |
fail
|
Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-23 |
success
|
Logs for x86_64-llvm-18 / test
|
bpf/vmtest-bpf-next-VM_Test-17 |
fail
|
Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-15 |
success
|
Logs for x86_64-gcc / test
|
@@ -4493,6 +4493,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
*/
if (!env->allow_ptr_leaks &&
is_spilled_reg(&state->stack[spi]) &&
+ !is_spilled_scalar_reg(&state->stack[spi]) &&
size != BPF_REG_SIZE) {
verbose(env, "attempt to corrupt spilled pointer on stack\n");
return -EACCES;
@@ -2,6 +2,10 @@
#ifndef __BPF_MISC_H__
#define __BPF_MISC_H__
+/* Expand a macro and then stringize the expansion */
+#define QUOTE(str) #str
+#define EXPAND_QUOTE(str) QUOTE(str)
+
/* This set of attributes controls behavior of the
* test_loader.c:test_loader__run_subtests().
*
@@ -24,11 +28,15 @@
* Multiple __msg attributes could be specified.
* __msg_unpriv Same as __msg but for unprivileged mode.
*
+ * __msg_caps Same as __msg but for specified capabilities.
+ *
* __success Expect program load success in privileged mode.
* __success_unpriv Expect program load success in unprivileged mode.
+ * __success_caps Expect program load success in specified cap mode.
*
* __failure Expect program load failure in privileged mode.
* __failure_unpriv Expect program load failure in unprivileged mode.
+ * __failure_caps Expect program load failure in specified cap mode.
*
* __retval Execute the program using BPF_PROG_TEST_RUN command,
* expect return value to match passed parameter:
@@ -38,6 +46,7 @@
* - literal POINTER_VALUE (see definition below)
* - literal TEST_DATA_LEN (see definition below)
* __retval_unpriv Same, but load program in unprivileged mode.
+ * __retval_caps Same, but load program in specified cap mode.
*
* __description Text to be used instead of a program name for display
* and filtering purposes.
@@ -63,12 +72,16 @@
#define __success __attribute__((btf_decl_tag("comment:test_expect_success")))
#define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc)))
#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" msg)))
+#define __msg_caps(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_caps=" msg)))
#define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))
#define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))
+#define __failure_caps(caps) __attribute__((btf_decl_tag("comment:test_expect_failure_caps="EXPAND_QUOTE(caps))))
+#define __success_caps(caps) __attribute__((btf_decl_tag("comment:test_expect_success_caps="EXPAND_QUOTE(caps))))
#define __log_level(lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl)))
#define __flag(flag) __attribute__((btf_decl_tag("comment:test_prog_flags="#flag)))
#define __retval(val) __attribute__((btf_decl_tag("comment:test_retval="#val)))
#define __retval_unpriv(val) __attribute__((btf_decl_tag("comment:test_retval_unpriv="#val)))
+#define __retval_caps(val) __attribute__((btf_decl_tag("comment:test_retval_caps="#val)))
#define __auxiliary __attribute__((btf_decl_tag("comment:test_auxiliary")))
#define __auxiliary_unpriv __attribute__((btf_decl_tag("comment:test_auxiliary_unpriv")))
#define __btf_path(path) __attribute__((btf_decl_tag("comment:test_btf_path=" path)))
@@ -5,6 +5,7 @@
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"
#include <../../../tools/include/linux/filter.h>
+#include "../cap_helpers.h"
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
@@ -1244,4 +1245,21 @@ __naked void old_stack_misc_vs_cur_ctx_ptr(void)
: __clobber_all);
}
+SEC("socket")
+__description("32-bit scalars should be able to overwrite 64-bit scalar spilled slots")
+__log_level(2)
+__success __success_unpriv
+__success_caps(CAP_BPF) __retval_caps(0)
+__naked void spill_32bit_onto_64bit_slot(void)
+{
+ asm volatile(" \
+ *(u64*)(r10 - 8) = 1; \
+ *(u32*)(r10 - 8) = 1; \
+ r0 = 0; \
+ exit; \
+" :
+ :
+ : __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
@@ -20,11 +20,15 @@
#define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv"
#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv"
#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv="
+#define TEST_TAG_EXPECT_FAILURE_CAPS "comment:test_expect_failure_caps="
+#define TEST_TAG_EXPECT_SUCCESS_CAPS "comment:test_expect_success_caps="
+#define TEST_TAG_EXPECT_MSG_PFX_CAPS "comment:test_expect_msg_caps="
#define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level="
#define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags="
#define TEST_TAG_DESCRIPTION_PFX "comment:test_description="
#define TEST_TAG_RETVAL_PFX "comment:test_retval="
#define TEST_TAG_RETVAL_PFX_UNPRIV "comment:test_retval_unpriv="
+#define TEST_TAG_RETVAL_PFX_CAPS "comment:test_retval_caps="
#define TEST_TAG_AUXILIARY "comment:test_auxiliary"
#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
#define TEST_BTF_PATH "comment:test_btf_path="
@@ -43,7 +47,8 @@ static int sysctl_unpriv_disabled = -1;
enum mode {
PRIV = 1,
- UNPRIV = 2
+ UNPRIV = 2,
+ CUSTCAPS = 4
};
struct test_subspec {
@@ -59,6 +64,8 @@ struct test_spec {
const char *prog_name;
struct test_subspec priv;
struct test_subspec unpriv;
+ struct test_subspec custom_caps;
+ __u64 caps;
const char *btf_custom_path;
int log_level;
int prog_flags;
@@ -133,6 +140,33 @@ static int parse_int(const char *str, int *val, const char *name)
return 0;
}
+static int parse_caps(const char *str, __u64 *val, const char *name)
+{
+ int cap_flag = 0;
+ char *token = NULL, *saveptr = NULL;
+
+ char *str_cpy = strdup(str);
+ if (str_cpy == NULL) {
+ PRINT_FAIL("Memory allocation failed\n");
+ return -EINVAL;
+ }
+
+ token = strtok_r(str_cpy, "|", &saveptr);
+ while (token != NULL) {
+ errno = 0;
+ cap_flag = strtol(token, NULL, 10);
+ if (errno) {
+ PRINT_FAIL("failed to parse caps %s\n", name);
+ return -EINVAL;
+ }
+ *val |= (1ULL << cap_flag);
+ token = strtok_r(NULL, "|", &saveptr);
+ }
+
+ free(str_cpy);
+ return 0;
+}
+
static int parse_retval(const char *str, int *val, const char *name)
{
struct {
@@ -163,6 +197,22 @@ static void update_flags(int *flags, int flag, bool clear)
*flags |= flag;
}
+static char *create_desc(const char *description, const char *suffix)
+{
+ int descr_len = strlen(description);
+ char *name;
+
+ name = malloc(descr_len + strlen(suffix) + 1);
+ if (!name) {
+ PRINT_FAIL("failed to allocate memory for unpriv.name\n");
+ return NULL;
+ }
+
+ strcpy(name, description);
+ strcpy(&name[descr_len], suffix);
+ return name;
+}
+
/* Uses btf_decl_tag attributes to describe the expected test
* behavior, see bpf_misc.h for detailed description of each attribute
* and attribute combinations.
@@ -225,6 +275,20 @@ static int parse_test_spec(struct test_loader *tester,
spec->unpriv.expect_failure = false;
spec->mode_mask |= UNPRIV;
has_unpriv_result = true;
+ } else if (str_has_pfx(s, TEST_TAG_EXPECT_FAILURE_CAPS)) {
+ val = s + sizeof(TEST_TAG_EXPECT_FAILURE_CAPS) - 1;
+ err = parse_caps(val, &spec->caps, "test caps");
+ if (err)
+ goto cleanup;
+ spec->custom_caps.expect_failure = true;
+ spec->mode_mask |= CUSTCAPS;
+ } else if (str_has_pfx(s, TEST_TAG_EXPECT_SUCCESS_CAPS)) {
+ val = s + sizeof(TEST_TAG_EXPECT_SUCCESS_CAPS) - 1;
+ err = parse_caps(val, &spec->caps, "test caps");
+ if (err)
+ goto cleanup;
+ spec->custom_caps.expect_failure = false;
+ spec->mode_mask |= CUSTCAPS;
} else if (strcmp(s, TEST_TAG_AUXILIARY) == 0) {
spec->auxiliary = true;
spec->mode_mask |= PRIV;
@@ -243,6 +307,12 @@ static int parse_test_spec(struct test_loader *tester,
if (err)
goto cleanup;
spec->mode_mask |= UNPRIV;
+ } else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_CAPS)) {
+ msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX_CAPS) - 1;
+ err = push_msg(msg, &spec->custom_caps);
+ if (err)
+ goto cleanup;
+ spec->mode_mask |= CUSTCAPS;
} else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX)) {
val = s + sizeof(TEST_TAG_RETVAL_PFX) - 1;
err = parse_retval(val, &spec->priv.retval, "__retval");
@@ -258,6 +328,13 @@ static int parse_test_spec(struct test_loader *tester,
spec->mode_mask |= UNPRIV;
spec->unpriv.execute = true;
has_unpriv_retval = true;
+ } else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX_CAPS)) {
+ val = s + sizeof(TEST_TAG_RETVAL_PFX_CAPS) - 1;
+ err = parse_retval(val, &spec->custom_caps.retval, "__retval_caps");
+ if (err)
+ goto cleanup;
+ spec->mode_mask |= CUSTCAPS;
+ spec->custom_caps.execute = true;
} else if (str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX)) {
val = s + sizeof(TEST_TAG_LOG_LEVEL_PFX) - 1;
err = parse_int(val, &spec->log_level, "test log level");
@@ -311,22 +388,23 @@ static int parse_test_spec(struct test_loader *tester,
}
if (spec->mode_mask & UNPRIV) {
- int descr_len = strlen(description);
- const char *suffix = " @unpriv";
- char *name;
-
- name = malloc(descr_len + strlen(suffix) + 1);
+ char *name = create_desc(description, " @unpriv");
if (!name) {
- PRINT_FAIL("failed to allocate memory for unpriv.name\n");
err = -ENOMEM;
goto cleanup;
}
-
- strcpy(name, description);
- strcpy(&name[descr_len], suffix);
spec->unpriv.name = name;
}
+ if (spec->mode_mask & CUSTCAPS) {
+ char *name = create_desc(description, " @caps");
+ if (!name) {
+ err = -ENOMEM;
+ goto cleanup;
+ }
+ spec->custom_caps.name = name;
+ }
+
if (spec->mode_mask & (PRIV | UNPRIV)) {
if (!has_unpriv_result)
spec->unpriv.expect_failure = spec->priv.expect_failure;
@@ -461,6 +539,28 @@ static int restore_capabilities(struct cap_state *caps)
return err;
}
+static int set_capabilities(__u64 new_caps, struct cap_state *save_caps) {
+
+ int err;
+
+ /* Drop all bpf related caps */
+ err = drop_capabilities(save_caps);
+ if (err) {
+ PRINT_FAIL("failed to drop capabilities: %i, %s\n", err, strerror(err));
+ return err;
+ }
+
+ /* Set the specified caps */
+ err = cap_enable_effective(new_caps, NULL);
+ if (err) {
+ PRINT_FAIL("failed to set capabilities: %i, %s\n", err, strerror(err));
+ return err;
+ }
+
+ save_caps->initialized = true;
+ return 0;
+}
+
static bool can_execute_unpriv(struct test_loader *tester, struct test_spec *spec)
{
if (sysctl_unpriv_disabled < 0)
@@ -560,21 +660,34 @@ void run_subtest(struct test_loader *tester,
size_t obj_byte_cnt,
struct test_spec *specs,
struct test_spec *spec,
- bool unpriv)
+ int priv_level)
{
- struct test_subspec *subspec = unpriv ? &spec->unpriv : &spec->priv;
+ struct test_subspec *subspec = NULL;
struct bpf_program *tprog = NULL, *tprog_iter;
struct test_spec *spec_iter;
struct cap_state caps = {};
struct bpf_object *tobj;
struct bpf_map *map;
int retval, err, i;
- bool should_load;
+ bool should_load, unpriv = (priv_level != PRIV);
+
+ switch (priv_level) {
+ case PRIV:
+ subspec = &spec->priv;
+ break;
+ case UNPRIV:
+ subspec = &spec->unpriv;
+ break;
+ case CUSTCAPS:
+ subspec = &spec->custom_caps;
+ break;
+ default:
+ }
if (!test__start_subtest(subspec->name))
return;
- if (unpriv) {
+ if (priv_level == UNPRIV) {
if (!can_execute_unpriv(tester, spec)) {
test__skip();
test__end_subtest();
@@ -584,6 +697,11 @@ void run_subtest(struct test_loader *tester,
test__end_subtest();
return;
}
+ } else if (priv_level == CUSTCAPS) {
+ if (set_capabilities(spec->caps, &caps)) {
+ test__end_subtest();
+ return;
+ }
}
/* Implicitly reset to NULL if next test case doesn't specify */
@@ -714,11 +832,13 @@ static void process_subtest(struct test_loader *tester,
if (spec->mode_mask & PRIV)
run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
- specs, spec, false);
+ specs, spec, PRIV);
if (spec->mode_mask & UNPRIV)
run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
- specs, spec, true);
-
+ specs, spec, UNPRIV);
+ if (spec->mode_mask & CUSTCAPS)
+ run_subtest(tester, &open_opts, obj_bytes, obj_byte_cnt,
+ specs, spec, CUSTCAPS);
}
for (i = 0; i < nr_progs; ++i)
When CAP_PERFMON and CAP_SYS_ADMIN (allow_ptr_leaks) are disabled, the verifier previously aimed to reject partial overwrite on an 8-byte stack slot that contains a spilled pointer. However, it rejects all partial stack overwrites as long as the targeted stack slot is a spilled register in that cap setting, because it does not check if the stack slot is a spilled pointer. Finally, incomplete checks will result in the rejection of valid programs, which spill narrower scalar values onto scalar slots, as shown below. 0: R1=ctx() R10=fp0 ; asm volatile ( @ repro.bpf.c:679 0: (7a) *(u64 *)(r10 -8) = 1 ; R10=fp0 fp-8_w=1 1: (62) *(u32 *)(r10 -8) = 1 attempt to corrupt spilled pointer on stack processed 2 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0. Note that only when CAP_BPF or CAP_SYS_ADMIN are enabled, are 64-bit scalars stored onto stacks marked as spilled scalars. Thus, to reproduce this issue, we can only assign CAP_BPF capability to the test. However, the existing bpf selftest doesn't support setting specific caps. So, I modified the test_loader.c and some related header files to enabled set specific capabilities on a test with the following attributes: __msg_caps(msg) __failure_caps(caps) __success_caps(caps) __retval_caps(val) Here, caps can be any combination of capabilities, like "CAP_BPF | CAP_PERFMON". Finally, the issue is fixed by checking the spilled register type of targeted slots. Fixes: ab125ed3ec1c ("bpf: fix check for attempt to corrupt spilled pointer") Signed-off-by: Tao Lyu <tao.lyu@epfl.ch> --- kernel/bpf/verifier.c | 1 + tools/testing/selftests/bpf/progs/bpf_misc.h | 13 ++ .../selftests/bpf/progs/verifier_spill_fill.c | 18 ++ tools/testing/selftests/bpf/test_loader.c | 154 ++++++++++++++++-- 4 files changed, 169 insertions(+), 17 deletions(-)