Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 33d65ed

Browse files
committedNov 26, 2024
bpf: Generally fix helper register offset check
jira VULN-72 cve CVE-2021-4204 commit-author Daniel Borkmann <[email protected]> commit 6788ab2 Right now the assertion on check_ptr_off_reg() is only enforced for register types PTR_TO_CTX (and open coded also for PTR_TO_BTF_ID), however, this is insufficient since many other PTR_TO_* register types such as PTR_TO_FUNC do not handle/expect register offsets when passed to helper functions. Given this can slip-through easily when adding new types, make this an explicit allow-list and reject all other current and future types by default if this is encountered. Also, extend check_ptr_off_reg() to handle PTR_TO_BTF_ID as well instead of duplicating it. For PTR_TO_BTF_ID, reg->off is used for BTF to match expected BTF ids if struct offset is used. This part still needs to be allowed, but the dynamic off from the tnum must be rejected. Fixes: 69c087b ("bpf: Add bpf_for_each_map_elem() helper") Fixes: eaa6bcb ("bpf: Introduce bpf_per_cpu_ptr()") Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: John Fastabend <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> (cherry picked from commit 6788ab2) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent dfc0131 commit 33d65ed

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed
 

‎kernel/bpf/verifier.c

+28-11
Original file line numberDiff line numberDiff line change
@@ -3661,14 +3661,15 @@ static int get_callee_stack_depth(struct bpf_verifier_env *env,
36613661
}
36623662
#endif
36633663

3664-
int check_ptr_off_reg(struct bpf_verifier_env *env,
3665-
const struct bpf_reg_state *reg, int regno)
3664+
static int __check_ptr_off_reg(struct bpf_verifier_env *env,
3665+
const struct bpf_reg_state *reg, int regno,
3666+
bool fixed_off_ok)
36663667
{
36673668
/* Access to this pointer-typed register or passing it to a helper
36683669
* is only allowed in its original, unmodified form.
36693670
*/
36703671

3671-
if (reg->off) {
3672+
if (!fixed_off_ok && reg->off) {
36723673
verbose(env, "dereference of modified %s ptr R%d off=%d disallowed\n",
36733674
reg_type_str(env, reg->type), regno, reg->off);
36743675
return -EACCES;
@@ -3686,6 +3687,12 @@ int check_ptr_off_reg(struct bpf_verifier_env *env,
36863687
return 0;
36873688
}
36883689

3690+
int check_ptr_off_reg(struct bpf_verifier_env *env,
3691+
const struct bpf_reg_state *reg, int regno)
3692+
{
3693+
return __check_ptr_off_reg(env, reg, regno, false);
3694+
}
3695+
36893696
static int __check_buffer_access(struct bpf_verifier_env *env,
36903697
const char *buf_info,
36913698
const struct bpf_reg_state *reg,
@@ -4866,12 +4873,6 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
48664873
kernel_type_name(btf_vmlinux, *arg_btf_id));
48674874
return -EACCES;
48684875
}
4869-
4870-
if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
4871-
verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
4872-
regno);
4873-
return -EACCES;
4874-
}
48754876
}
48764877

48774878
return 0;
@@ -4926,10 +4927,26 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
49264927
if (err)
49274928
return err;
49284929

4929-
if (type == PTR_TO_CTX) {
4930-
err = check_ptr_off_reg(env, reg, regno);
4930+
switch ((u32)type) {
4931+
case SCALAR_VALUE:
4932+
/* Pointer types where reg offset is explicitly allowed: */
4933+
case PTR_TO_PACKET:
4934+
case PTR_TO_PACKET_META:
4935+
case PTR_TO_MAP_KEY:
4936+
case PTR_TO_MAP_VALUE:
4937+
case PTR_TO_MEM:
4938+
case PTR_TO_MEM | MEM_RDONLY:
4939+
case PTR_TO_BUF:
4940+
case PTR_TO_BUF | MEM_RDONLY:
4941+
case PTR_TO_STACK:
4942+
break;
4943+
/* All the rest must be rejected: */
4944+
default:
4945+
err = __check_ptr_off_reg(env, reg, regno,
4946+
type == PTR_TO_BTF_ID);
49314947
if (err < 0)
49324948
return err;
4949+
break;
49334950
}
49344951

49354952
skip_type_check:

0 commit comments

Comments
 (0)
Please sign in to comment.