Skip to content

Commit 0e5aefa

Browse files
author
Alexei Starovoitov
committed
Merge branch 'Ensure type tags are always ordered first in BTF'
Kumar Kartikeya Dwivedi says: ==================== When iterating over modifiers, ensure that type tags can only occur at head of the chain, and don't occur later, such that checking for them once in the start tells us there are no more type tags in later modifiers. Clang already ensures to emit such BTF, but user can craft their own BTF which violates such assumptions if relied upon in the kernel. Changelog: ---------- v2 -> v3 v2: https://lore.kernel.org/bpf/[email protected] * Address nit from Yonghong, add Acked-by v1 -> v2 v1: https://lore.kernel.org/bpf/[email protected] * Fix for bug pointed out by Yonghong * Update selftests to include Yonghong's example ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 0d7fefe + 24fe983 commit 0e5aefa

File tree

2 files changed

+153
-0
lines changed
  • kernel/bpf
  • tools/testing/selftests/bpf/prog_tests

2 files changed

+153
-0
lines changed

kernel/bpf/btf.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4541,6 +4541,48 @@ static int btf_parse_hdr(struct btf_verifier_env *env)
45414541
return 0;
45424542
}
45434543

4544+
static int btf_check_type_tags(struct btf_verifier_env *env,
4545+
struct btf *btf, int start_id)
4546+
{
4547+
int i, n, good_id = start_id - 1;
4548+
bool in_tags;
4549+
4550+
n = btf_nr_types(btf);
4551+
for (i = start_id; i < n; i++) {
4552+
const struct btf_type *t;
4553+
u32 cur_id = i;
4554+
4555+
t = btf_type_by_id(btf, i);
4556+
if (!t)
4557+
return -EINVAL;
4558+
if (!btf_type_is_modifier(t))
4559+
continue;
4560+
4561+
cond_resched();
4562+
4563+
in_tags = btf_type_is_type_tag(t);
4564+
while (btf_type_is_modifier(t)) {
4565+
if (btf_type_is_type_tag(t)) {
4566+
if (!in_tags) {
4567+
btf_verifier_log(env, "Type tags don't precede modifiers");
4568+
return -EINVAL;
4569+
}
4570+
} else if (in_tags) {
4571+
in_tags = false;
4572+
}
4573+
if (cur_id <= good_id)
4574+
break;
4575+
/* Move to next type */
4576+
cur_id = t->type;
4577+
t = btf_type_by_id(btf, cur_id);
4578+
if (!t)
4579+
return -EINVAL;
4580+
}
4581+
good_id = i;
4582+
}
4583+
return 0;
4584+
}
4585+
45444586
static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
45454587
u32 log_level, char __user *log_ubuf, u32 log_size)
45464588
{
@@ -4608,6 +4650,10 @@ static struct btf *btf_parse(bpfptr_t btf_data, u32 btf_data_size,
46084650
if (err)
46094651
goto errout;
46104652

4653+
err = btf_check_type_tags(env, btf, 1);
4654+
if (err)
4655+
goto errout;
4656+
46114657
if (log->level && bpf_verifier_log_full(log)) {
46124658
err = -ENOSPC;
46134659
goto errout;
@@ -4809,6 +4855,10 @@ struct btf *btf_parse_vmlinux(void)
48094855
if (err)
48104856
goto errout;
48114857

4858+
err = btf_check_type_tags(env, btf, 1);
4859+
if (err)
4860+
goto errout;
4861+
48124862
/* btf_parse_vmlinux() runs under bpf_verifier_lock */
48134863
bpf_ctx_convert.t = btf_type_by_id(btf, bpf_ctx_convert_btf_id[0]);
48144864

@@ -4894,6 +4944,10 @@ static struct btf *btf_parse_module(const char *module_name, const void *data, u
48944944
if (err)
48954945
goto errout;
48964946

4947+
err = btf_check_type_tags(env, btf, btf_nr_types(base_btf));
4948+
if (err)
4949+
goto errout;
4950+
48974951
btf_verifier_env_free(env);
48984952
refcount_set(&btf->refcnt, 1);
48994953
return btf;

tools/testing/selftests/bpf/prog_tests/btf.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3973,6 +3973,105 @@ static struct btf_raw_test raw_tests[] = {
39733973
.value_type_id = 1,
39743974
.max_entries = 1,
39753975
},
3976+
{
3977+
.descr = "type_tag test #2, type tag order",
3978+
.raw_types = {
3979+
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3980+
BTF_CONST_ENC(3), /* [2] */
3981+
BTF_TYPE_TAG_ENC(NAME_TBD, 1), /* [3] */
3982+
BTF_END_RAW,
3983+
},
3984+
BTF_STR_SEC("\0tag"),
3985+
.map_type = BPF_MAP_TYPE_ARRAY,
3986+
.map_name = "tag_type_check_btf",
3987+
.key_size = sizeof(int),
3988+
.value_size = 4,
3989+
.key_type_id = 1,
3990+
.value_type_id = 1,
3991+
.max_entries = 1,
3992+
.btf_load_err = true,
3993+
.err_str = "Type tags don't precede modifiers",
3994+
},
3995+
{
3996+
.descr = "type_tag test #3, type tag order",
3997+
.raw_types = {
3998+
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3999+
BTF_TYPE_TAG_ENC(NAME_TBD, 3), /* [2] */
4000+
BTF_CONST_ENC(4), /* [3] */
4001+
BTF_TYPE_TAG_ENC(NAME_TBD, 1), /* [4] */
4002+
BTF_END_RAW,
4003+
},
4004+
BTF_STR_SEC("\0tag\0tag"),
4005+
.map_type = BPF_MAP_TYPE_ARRAY,
4006+
.map_name = "tag_type_check_btf",
4007+
.key_size = sizeof(int),
4008+
.value_size = 4,
4009+
.key_type_id = 1,
4010+
.value_type_id = 1,
4011+
.max_entries = 1,
4012+
.btf_load_err = true,
4013+
.err_str = "Type tags don't precede modifiers",
4014+
},
4015+
{
4016+
.descr = "type_tag test #4, type tag order",
4017+
.raw_types = {
4018+
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
4019+
BTF_TYPEDEF_ENC(NAME_TBD, 3), /* [2] */
4020+
BTF_CONST_ENC(4), /* [3] */
4021+
BTF_TYPE_TAG_ENC(NAME_TBD, 1), /* [4] */
4022+
BTF_END_RAW,
4023+
},
4024+
BTF_STR_SEC("\0tag\0tag"),
4025+
.map_type = BPF_MAP_TYPE_ARRAY,
4026+
.map_name = "tag_type_check_btf",
4027+
.key_size = sizeof(int),
4028+
.value_size = 4,
4029+
.key_type_id = 1,
4030+
.value_type_id = 1,
4031+
.max_entries = 1,
4032+
.btf_load_err = true,
4033+
.err_str = "Type tags don't precede modifiers",
4034+
},
4035+
{
4036+
.descr = "type_tag test #5, type tag order",
4037+
.raw_types = {
4038+
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
4039+
BTF_TYPE_TAG_ENC(NAME_TBD, 3), /* [2] */
4040+
BTF_CONST_ENC(1), /* [3] */
4041+
BTF_TYPE_TAG_ENC(NAME_TBD, 2), /* [4] */
4042+
BTF_END_RAW,
4043+
},
4044+
BTF_STR_SEC("\0tag\0tag"),
4045+
.map_type = BPF_MAP_TYPE_ARRAY,
4046+
.map_name = "tag_type_check_btf",
4047+
.key_size = sizeof(int),
4048+
.value_size = 4,
4049+
.key_type_id = 1,
4050+
.value_type_id = 1,
4051+
.max_entries = 1,
4052+
},
4053+
{
4054+
.descr = "type_tag test #6, type tag order",
4055+
.raw_types = {
4056+
BTF_PTR_ENC(2), /* [1] */
4057+
BTF_TYPE_TAG_ENC(NAME_TBD, 3), /* [2] */
4058+
BTF_CONST_ENC(4), /* [3] */
4059+
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [4] */
4060+
BTF_PTR_ENC(6), /* [5] */
4061+
BTF_CONST_ENC(2), /* [6] */
4062+
BTF_END_RAW,
4063+
},
4064+
BTF_STR_SEC("\0tag"),
4065+
.map_type = BPF_MAP_TYPE_ARRAY,
4066+
.map_name = "tag_type_check_btf",
4067+
.key_size = sizeof(int),
4068+
.value_size = 4,
4069+
.key_type_id = 1,
4070+
.value_type_id = 1,
4071+
.max_entries = 1,
4072+
.btf_load_err = true,
4073+
.err_str = "Type tags don't precede modifiers",
4074+
},
39764075

39774076
}; /* struct btf_raw_test raw_tests[] */
39784077

0 commit comments

Comments
 (0)