Skip to content

Commit 9101cf8

Browse files
committed
bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem.
jira VULN-136 cve-pre CVE-2022-0500 commit-author Hao Luo <[email protected]> commit 216e3cd Some helper functions may modify its arguments, for example, bpf_d_path, bpf_get_stack etc. Previously, their argument types were marked as ARG_PTR_TO_MEM, which is compatible with read-only mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate, but technically incorrect, to modify a read-only memory by passing it into one of such helper functions. This patch tags the bpf_args compatible with immutable memory with MEM_RDONLY flag. The arguments that don't have this flag will be only compatible with mutable memory types, preventing the helper from modifying a read-only memory. The bpf_args that have MEM_RDONLY are compatible with both mutable memory and immutable memory. Signed-off-by: Hao Luo <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected] (cherry picked from commit 216e3cd) Signed-off-by: Brett Mastbergen <[email protected]>
1 parent 7ab300d commit 9101cf8

File tree

9 files changed

+70
-54
lines changed

9 files changed

+70
-54
lines changed

include/linux/bpf.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,9 @@ enum bpf_type_flag {
293293
/* PTR may be NULL. */
294294
PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS),
295295

296-
/* MEM is read-only. */
296+
/* MEM is read-only. When applied on bpf_arg, it indicates the arg is
297+
* compatible with both mutable and immutable memory.
298+
*/
297299
MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS),
298300

299301
__BPF_TYPE_LAST_FLAG = MEM_RDONLY,

kernel/bpf/btf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6157,7 +6157,7 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = {
61576157
.func = bpf_btf_find_by_name_kind,
61586158
.gpl_only = false,
61596159
.ret_type = RET_INTEGER,
6160-
.arg1_type = ARG_PTR_TO_MEM,
6160+
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
61616161
.arg2_type = ARG_CONST_SIZE,
61626162
.arg3_type = ARG_ANYTHING,
61636163
.arg4_type = ARG_ANYTHING,

kernel/bpf/cgroup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,7 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = {
17381738
.gpl_only = false,
17391739
.ret_type = RET_INTEGER,
17401740
.arg1_type = ARG_PTR_TO_CTX,
1741-
.arg2_type = ARG_PTR_TO_MEM,
1741+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
17421742
.arg3_type = ARG_CONST_SIZE,
17431743
};
17441744

kernel/bpf/helpers.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ const struct bpf_func_proto bpf_strtol_proto = {
533533
.func = bpf_strtol,
534534
.gpl_only = false,
535535
.ret_type = RET_INTEGER,
536-
.arg1_type = ARG_PTR_TO_MEM,
536+
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
537537
.arg2_type = ARG_CONST_SIZE,
538538
.arg3_type = ARG_ANYTHING,
539539
.arg4_type = ARG_PTR_TO_LONG,
@@ -561,7 +561,7 @@ const struct bpf_func_proto bpf_strtoul_proto = {
561561
.func = bpf_strtoul,
562562
.gpl_only = false,
563563
.ret_type = RET_INTEGER,
564-
.arg1_type = ARG_PTR_TO_MEM,
564+
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
565565
.arg2_type = ARG_CONST_SIZE,
566566
.arg3_type = ARG_ANYTHING,
567567
.arg4_type = ARG_PTR_TO_LONG,
@@ -633,7 +633,7 @@ const struct bpf_func_proto bpf_event_output_data_proto = {
633633
.arg1_type = ARG_PTR_TO_CTX,
634634
.arg2_type = ARG_CONST_MAP_PTR,
635635
.arg3_type = ARG_ANYTHING,
636-
.arg4_type = ARG_PTR_TO_MEM,
636+
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
637637
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
638638
};
639639

@@ -1002,7 +1002,7 @@ const struct bpf_func_proto bpf_snprintf_proto = {
10021002
.arg1_type = ARG_PTR_TO_MEM_OR_NULL,
10031003
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
10041004
.arg3_type = ARG_PTR_TO_CONST_STR,
1005-
.arg4_type = ARG_PTR_TO_MEM_OR_NULL,
1005+
.arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
10061006
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
10071007
};
10081008

kernel/bpf/ringbuf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ const struct bpf_func_proto bpf_ringbuf_output_proto = {
444444
.func = bpf_ringbuf_output,
445445
.ret_type = RET_INTEGER,
446446
.arg1_type = ARG_CONST_MAP_PTR,
447-
.arg2_type = ARG_PTR_TO_MEM,
447+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
448448
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
449449
.arg4_type = ARG_ANYTHING,
450450
};

kernel/bpf/syscall.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4630,7 +4630,7 @@ static const struct bpf_func_proto bpf_sys_bpf_proto = {
46304630
.gpl_only = false,
46314631
.ret_type = RET_INTEGER,
46324632
.arg1_type = ARG_ANYTHING,
4633-
.arg2_type = ARG_PTR_TO_MEM,
4633+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
46344634
.arg3_type = ARG_CONST_SIZE,
46354635
};
46364636

kernel/bpf/verifier.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,7 +4741,6 @@ static const struct bpf_reg_types mem_types = {
47414741
PTR_TO_MAP_VALUE,
47424742
PTR_TO_MEM,
47434743
PTR_TO_BUF,
4744-
PTR_TO_BUF | MEM_RDONLY,
47454744
},
47464745
};
47474746

@@ -4809,6 +4808,21 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
48094808
return -EFAULT;
48104809
}
48114810

4811+
/* ARG_PTR_TO_MEM + RDONLY is compatible with PTR_TO_MEM and PTR_TO_MEM + RDONLY,
4812+
* but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM and NOT with PTR_TO_MEM + RDONLY
4813+
*
4814+
* Same for MAYBE_NULL:
4815+
*
4816+
* ARG_PTR_TO_MEM + MAYBE_NULL is compatible with PTR_TO_MEM and PTR_TO_MEM + MAYBE_NULL,
4817+
* but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM but NOT with PTR_TO_MEM + MAYBE_NULL
4818+
*
4819+
* Therefore we fold these flags depending on the arg_type before comparison.
4820+
*/
4821+
if (arg_type & MEM_RDONLY)
4822+
type &= ~MEM_RDONLY;
4823+
if (arg_type & PTR_MAYBE_NULL)
4824+
type &= ~PTR_MAYBE_NULL;
4825+
48124826
for (i = 0; i < ARRAY_SIZE(compatible->types); i++) {
48134827
expected = compatible->types[i];
48144828
if (expected == NOT_INIT)
@@ -4818,14 +4832,14 @@ static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
48184832
goto found;
48194833
}
48204834

4821-
verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, type));
4835+
verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, reg->type));
48224836
for (j = 0; j + 1 < i; j++)
48234837
verbose(env, "%s, ", reg_type_str(env, compatible->types[j]));
48244838
verbose(env, "%s\n", reg_type_str(env, compatible->types[j]));
48254839
return -EACCES;
48264840

48274841
found:
4828-
if (type == PTR_TO_BTF_ID) {
4842+
if (reg->type == PTR_TO_BTF_ID) {
48294843
if (!arg_btf_id) {
48304844
if (!compatible->btf_id) {
48314845
verbose(env, "verifier internal error: missing arg compatible BTF ID\n");

kernel/trace/bpf_trace.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ static const struct bpf_func_proto bpf_probe_write_user_proto = {
347347
.gpl_only = true,
348348
.ret_type = RET_INTEGER,
349349
.arg1_type = ARG_ANYTHING,
350-
.arg2_type = ARG_PTR_TO_MEM,
350+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
351351
.arg3_type = ARG_CONST_SIZE,
352352
};
353353

@@ -396,7 +396,7 @@ static const struct bpf_func_proto bpf_trace_printk_proto = {
396396
.func = bpf_trace_printk,
397397
.gpl_only = true,
398398
.ret_type = RET_INTEGER,
399-
.arg1_type = ARG_PTR_TO_MEM,
399+
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
400400
.arg2_type = ARG_CONST_SIZE,
401401
};
402402

@@ -448,9 +448,9 @@ static const struct bpf_func_proto bpf_seq_printf_proto = {
448448
.ret_type = RET_INTEGER,
449449
.arg1_type = ARG_PTR_TO_BTF_ID,
450450
.arg1_btf_id = &btf_seq_file_ids[0],
451-
.arg2_type = ARG_PTR_TO_MEM,
451+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
452452
.arg3_type = ARG_CONST_SIZE,
453-
.arg4_type = ARG_PTR_TO_MEM_OR_NULL,
453+
.arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
454454
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
455455
};
456456

@@ -465,7 +465,7 @@ static const struct bpf_func_proto bpf_seq_write_proto = {
465465
.ret_type = RET_INTEGER,
466466
.arg1_type = ARG_PTR_TO_BTF_ID,
467467
.arg1_btf_id = &btf_seq_file_ids[0],
468-
.arg2_type = ARG_PTR_TO_MEM,
468+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
469469
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
470470
};
471471

@@ -489,7 +489,7 @@ static const struct bpf_func_proto bpf_seq_printf_btf_proto = {
489489
.ret_type = RET_INTEGER,
490490
.arg1_type = ARG_PTR_TO_BTF_ID,
491491
.arg1_btf_id = &btf_seq_file_ids[0],
492-
.arg2_type = ARG_PTR_TO_MEM,
492+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
493493
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
494494
.arg4_type = ARG_ANYTHING,
495495
};
@@ -650,7 +650,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
650650
.arg1_type = ARG_PTR_TO_CTX,
651651
.arg2_type = ARG_CONST_MAP_PTR,
652652
.arg3_type = ARG_ANYTHING,
653-
.arg4_type = ARG_PTR_TO_MEM,
653+
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
654654
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
655655
};
656656

@@ -945,7 +945,7 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
945945
.ret_type = RET_INTEGER,
946946
.arg1_type = ARG_PTR_TO_MEM,
947947
.arg2_type = ARG_CONST_SIZE,
948-
.arg3_type = ARG_PTR_TO_MEM,
948+
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
949949
.arg4_type = ARG_CONST_SIZE,
950950
.arg5_type = ARG_ANYTHING,
951951
};
@@ -1125,7 +1125,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_tp = {
11251125
.arg1_type = ARG_PTR_TO_CTX,
11261126
.arg2_type = ARG_CONST_MAP_PTR,
11271127
.arg3_type = ARG_ANYTHING,
1128-
.arg4_type = ARG_PTR_TO_MEM,
1128+
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
11291129
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
11301130
};
11311131

@@ -1343,7 +1343,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
13431343
.arg1_type = ARG_PTR_TO_CTX,
13441344
.arg2_type = ARG_CONST_MAP_PTR,
13451345
.arg3_type = ARG_ANYTHING,
1346-
.arg4_type = ARG_PTR_TO_MEM,
1346+
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
13471347
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
13481348
};
13491349

@@ -1397,7 +1397,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
13971397
.gpl_only = true,
13981398
.ret_type = RET_INTEGER,
13991399
.arg1_type = ARG_PTR_TO_CTX,
1400-
.arg2_type = ARG_PTR_TO_MEM,
1400+
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
14011401
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
14021402
.arg4_type = ARG_ANYTHING,
14031403
};

0 commit comments

Comments
 (0)