Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Zero index arg error string for dynptr and iter

Andrii spotted that process_dynptr_func's rejection of incorrect
argument register type will print an error string where argument numbers
are not zero-indexed, unlike elsewhere in the verifier. Fix this by
subtracting 1 from regno. The same scenario exists for iterator
messages. Fix selftest error strings that match on the exact argument
number while we're at it to ensure clean bisection.

Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20241203002235.3776418-1-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Kumar Kartikeya Dwivedi and committed by
Alexei Starovoitov
bd74e238 d4c44354

+29 -29
+6 -6
kernel/bpf/verifier.c
··· 8071 8071 if (reg->type != PTR_TO_STACK && reg->type != CONST_PTR_TO_DYNPTR) { 8072 8072 verbose(env, 8073 8073 "arg#%d expected pointer to stack or const struct bpf_dynptr\n", 8074 - regno); 8074 + regno - 1); 8075 8075 return -EINVAL; 8076 8076 } 8077 8077 ··· 8125 8125 if (!is_dynptr_reg_valid_init(env, reg)) { 8126 8126 verbose(env, 8127 8127 "Expected an initialized dynptr as arg #%d\n", 8128 - regno); 8128 + regno - 1); 8129 8129 return -EINVAL; 8130 8130 } 8131 8131 ··· 8133 8133 if (!is_dynptr_type_expected(env, reg, arg_type & ~MEM_RDONLY)) { 8134 8134 verbose(env, 8135 8135 "Expected a dynptr of type %s as arg #%d\n", 8136 - dynptr_type_str(arg_to_dynptr_type(arg_type)), regno); 8136 + dynptr_type_str(arg_to_dynptr_type(arg_type)), regno - 1); 8137 8137 return -EINVAL; 8138 8138 } 8139 8139 ··· 8202 8202 */ 8203 8203 btf_id = btf_check_iter_arg(meta->btf, meta->func_proto, regno - 1); 8204 8204 if (btf_id < 0) { 8205 - verbose(env, "expected valid iter pointer as arg #%d\n", regno); 8205 + verbose(env, "expected valid iter pointer as arg #%d\n", regno - 1); 8206 8206 return -EINVAL; 8207 8207 } 8208 8208 t = btf_type_by_id(meta->btf, btf_id); ··· 8212 8212 /* bpf_iter_<type>_new() expects pointer to uninit iter state */ 8213 8213 if (!is_iter_reg_valid_uninit(env, reg, nr_slots)) { 8214 8214 verbose(env, "expected uninitialized iter_%s as arg #%d\n", 8215 - iter_type_str(meta->btf, btf_id), regno); 8215 + iter_type_str(meta->btf, btf_id), regno - 1); 8216 8216 return -EINVAL; 8217 8217 } 8218 8218 ··· 8236 8236 break; 8237 8237 case -EINVAL: 8238 8238 verbose(env, "expected an initialized iter_%s as arg #%d\n", 8239 - iter_type_str(meta->btf, btf_id), regno); 8239 + iter_type_str(meta->btf, btf_id), regno - 1); 8240 8240 return err; 8241 8241 case -EPROTO: 8242 8242 verbose(env, "expected an RCU CS when using %s\n", meta->func_name);
+11 -11
tools/testing/selftests/bpf/progs/dynptr_fail.c
··· 149 149 150 150 /* A dynptr can't be used after it has been invalidated */ 151 151 SEC("?raw_tp") 152 - __failure __msg("Expected an initialized dynptr as arg #3") 152 + __failure __msg("Expected an initialized dynptr as arg #2") 153 153 int use_after_invalid(void *ctx) 154 154 { 155 155 struct bpf_dynptr ptr; ··· 428 428 429 429 /* A bpf_dynptr is invalidated if it's been written into */ 430 430 SEC("?raw_tp") 431 - __failure __msg("Expected an initialized dynptr as arg #1") 431 + __failure __msg("Expected an initialized dynptr as arg #0") 432 432 int invalid_write1(void *ctx) 433 433 { 434 434 struct bpf_dynptr ptr; ··· 1407 1407 1408 1408 /* bpf_dynptr_adjust can only be called on initialized dynptrs */ 1409 1409 SEC("?raw_tp") 1410 - __failure __msg("Expected an initialized dynptr as arg #1") 1410 + __failure __msg("Expected an initialized dynptr as arg #0") 1411 1411 int dynptr_adjust_invalid(void *ctx) 1412 1412 { 1413 1413 struct bpf_dynptr ptr = {}; ··· 1420 1420 1421 1421 /* bpf_dynptr_is_null can only be called on initialized dynptrs */ 1422 1422 SEC("?raw_tp") 1423 - __failure __msg("Expected an initialized dynptr as arg #1") 1423 + __failure __msg("Expected an initialized dynptr as arg #0") 1424 1424 int dynptr_is_null_invalid(void *ctx) 1425 1425 { 1426 1426 struct bpf_dynptr ptr = {}; ··· 1433 1433 1434 1434 /* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */ 1435 1435 SEC("?raw_tp") 1436 - __failure __msg("Expected an initialized dynptr as arg #1") 1436 + __failure __msg("Expected an initialized dynptr as arg #0") 1437 1437 int dynptr_is_rdonly_invalid(void *ctx) 1438 1438 { 1439 1439 struct bpf_dynptr ptr = {}; ··· 1446 1446 1447 1447 /* bpf_dynptr_size can only be called on initialized dynptrs */ 1448 1448 SEC("?raw_tp") 1449 - __failure __msg("Expected an initialized dynptr as arg #1") 1449 + __failure __msg("Expected an initialized dynptr as arg #0") 1450 1450 int dynptr_size_invalid(void *ctx) 1451 1451 { 1452 1452 struct bpf_dynptr ptr = {}; ··· 1459 1459 1460 1460 /* Only initialized dynptrs can be cloned */ 1461 1461 SEC("?raw_tp") 1462 - __failure __msg("Expected an initialized dynptr as arg #1") 1462 + __failure __msg("Expected an initialized dynptr as arg #0") 1463 1463 int clone_invalid1(void *ctx) 1464 1464 { 1465 1465 struct bpf_dynptr ptr1 = {}; ··· 1493 1493 1494 1494 /* Invalidating a dynptr should invalidate its clones */ 1495 1495 SEC("?raw_tp") 1496 - __failure __msg("Expected an initialized dynptr as arg #3") 1496 + __failure __msg("Expected an initialized dynptr as arg #2") 1497 1497 int clone_invalidate1(void *ctx) 1498 1498 { 1499 1499 struct bpf_dynptr clone; ··· 1514 1514 1515 1515 /* Invalidating a dynptr should invalidate its parent */ 1516 1516 SEC("?raw_tp") 1517 - __failure __msg("Expected an initialized dynptr as arg #3") 1517 + __failure __msg("Expected an initialized dynptr as arg #2") 1518 1518 int clone_invalidate2(void *ctx) 1519 1519 { 1520 1520 struct bpf_dynptr ptr; ··· 1535 1535 1536 1536 /* Invalidating a dynptr should invalidate its siblings */ 1537 1537 SEC("?raw_tp") 1538 - __failure __msg("Expected an initialized dynptr as arg #3") 1538 + __failure __msg("Expected an initialized dynptr as arg #2") 1539 1539 int clone_invalidate3(void *ctx) 1540 1540 { 1541 1541 struct bpf_dynptr ptr; ··· 1723 1723 } 1724 1724 1725 1725 SEC("?raw_tp") 1726 - __failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr") 1726 + __failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr") 1727 1727 int test_dynptr_reg_type(void *ctx) 1728 1728 { 1729 1729 struct task_struct *current = NULL;
+7 -7
tools/testing/selftests/bpf/progs/iters_state_safety.c
··· 73 73 } 74 74 75 75 SEC("?raw_tp") 76 - __failure __msg("expected an initialized iter_num as arg #1") 76 + __failure __msg("expected an initialized iter_num as arg #0") 77 77 int destroy_without_creating_fail(void *ctx) 78 78 { 79 79 /* init with zeros to stop verifier complaining about uninit stack */ ··· 91 91 } 92 92 93 93 SEC("?raw_tp") 94 - __failure __msg("expected an initialized iter_num as arg #1") 94 + __failure __msg("expected an initialized iter_num as arg #0") 95 95 int compromise_iter_w_direct_write_fail(void *ctx) 96 96 { 97 97 struct bpf_iter_num iter; ··· 143 143 } 144 144 145 145 SEC("?raw_tp") 146 - __failure __msg("expected an initialized iter_num as arg #1") 146 + __failure __msg("expected an initialized iter_num as arg #0") 147 147 int compromise_iter_w_helper_write_fail(void *ctx) 148 148 { 149 149 struct bpf_iter_num iter; ··· 230 230 } 231 231 232 232 SEC("?raw_tp") 233 - __failure __msg("expected uninitialized iter_num as arg #1") 233 + __failure __msg("expected uninitialized iter_num as arg #0") 234 234 int double_create_fail(void *ctx) 235 235 { 236 236 struct bpf_iter_num iter; ··· 258 258 } 259 259 260 260 SEC("?raw_tp") 261 - __failure __msg("expected an initialized iter_num as arg #1") 261 + __failure __msg("expected an initialized iter_num as arg #0") 262 262 int double_destroy_fail(void *ctx) 263 263 { 264 264 struct bpf_iter_num iter; ··· 284 284 } 285 285 286 286 SEC("?raw_tp") 287 - __failure __msg("expected an initialized iter_num as arg #1") 287 + __failure __msg("expected an initialized iter_num as arg #0") 288 288 int next_without_new_fail(void *ctx) 289 289 { 290 290 struct bpf_iter_num iter; ··· 305 305 } 306 306 307 307 SEC("?raw_tp") 308 - __failure __msg("expected an initialized iter_num as arg #1") 308 + __failure __msg("expected an initialized iter_num as arg #0") 309 309 int next_after_destroy_fail(void *ctx) 310 310 { 311 311 struct bpf_iter_num iter;
+2 -2
tools/testing/selftests/bpf/progs/iters_testmod_seq.c
··· 79 79 80 80 SEC("?raw_tp") 81 81 __failure 82 - __msg("expected an initialized iter_testmod_seq as arg #2") 82 + __msg("expected an initialized iter_testmod_seq as arg #1") 83 83 int testmod_seq_getter_before_bad(const void *ctx) 84 84 { 85 85 struct bpf_iter_testmod_seq it; ··· 89 89 90 90 SEC("?raw_tp") 91 91 __failure 92 - __msg("expected an initialized iter_testmod_seq as arg #2") 92 + __msg("expected an initialized iter_testmod_seq as arg #1") 93 93 int testmod_seq_getter_after_bad(const void *ctx) 94 94 { 95 95 struct bpf_iter_testmod_seq it;
+1 -1
tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
··· 45 45 } 46 46 47 47 SEC("?lsm.s/bpf") 48 - __failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr") 48 + __failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr") 49 49 int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size) 50 50 { 51 51 unsigned long val = 0;
+2 -2
tools/testing/selftests/bpf/progs/verifier_bits_iter.c
··· 32 32 33 33 SEC("iter/cgroup") 34 34 __description("uninitialized iter in ->next()") 35 - __failure __msg("expected an initialized iter_bits as arg #1") 35 + __failure __msg("expected an initialized iter_bits as arg #0") 36 36 int BPF_PROG(next_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp) 37 37 { 38 38 struct bpf_iter_bits it = {}; ··· 43 43 44 44 SEC("iter/cgroup") 45 45 __description("uninitialized iter in ->destroy()") 46 - __failure __msg("expected an initialized iter_bits as arg #1") 46 + __failure __msg("expected an initialized iter_bits as arg #0") 47 47 int BPF_PROG(destroy_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp) 48 48 { 49 49 struct bpf_iter_bits it = {};