diff options
Diffstat (limited to 'kernel/bpf/btf.c')
-rw-r--r-- | kernel/bpf/btf.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index ee4c82667d65..4da543d6bea2 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <uapi/linux/types.h> | 5 | #include <uapi/linux/types.h> |
6 | #include <linux/seq_file.h> | 6 | #include <linux/seq_file.h> |
7 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
8 | #include <linux/ctype.h> | ||
8 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
10 | #include <linux/anon_inodes.h> | 11 | #include <linux/anon_inodes.h> |
@@ -426,6 +427,30 @@ static bool btf_name_offset_valid(const struct btf *btf, u32 offset) | |||
426 | offset < btf->hdr.str_len; | 427 | offset < btf->hdr.str_len; |
427 | } | 428 | } |
428 | 429 | ||
430 | /* Only C-style identifier is permitted. This can be relaxed if | ||
431 | * necessary. | ||
432 | */ | ||
433 | static bool btf_name_valid_identifier(const struct btf *btf, u32 offset) | ||
434 | { | ||
435 | /* offset must be valid */ | ||
436 | const char *src = &btf->strings[offset]; | ||
437 | const char *src_limit; | ||
438 | |||
439 | if (!isalpha(*src) && *src != '_') | ||
440 | return false; | ||
441 | |||
442 | /* set a limit on identifier length */ | ||
443 | src_limit = src + KSYM_NAME_LEN; | ||
444 | src++; | ||
445 | while (*src && src < src_limit) { | ||
446 | if (!isalnum(*src) && *src != '_') | ||
447 | return false; | ||
448 | src++; | ||
449 | } | ||
450 | |||
451 | return !*src; | ||
452 | } | ||
453 | |||
429 | static const char *btf_name_by_offset(const struct btf *btf, u32 offset) | 454 | static const char *btf_name_by_offset(const struct btf *btf, u32 offset) |
430 | { | 455 | { |
431 | if (!offset) | 456 | if (!offset) |
@@ -1143,6 +1168,22 @@ static int btf_ref_type_check_meta(struct btf_verifier_env *env, | |||
1143 | return -EINVAL; | 1168 | return -EINVAL; |
1144 | } | 1169 | } |
1145 | 1170 | ||
1171 | /* typedef type must have a valid name, and other ref types, | ||
1172 | * volatile, const, restrict, should have a null name. | ||
1173 | */ | ||
1174 | if (BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF) { | ||
1175 | if (!t->name_off || | ||
1176 | !btf_name_valid_identifier(env->btf, t->name_off)) { | ||
1177 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1178 | return -EINVAL; | ||
1179 | } | ||
1180 | } else { | ||
1181 | if (t->name_off) { | ||
1182 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1183 | return -EINVAL; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1146 | btf_verifier_log_type(env, t, NULL); | 1187 | btf_verifier_log_type(env, t, NULL); |
1147 | 1188 | ||
1148 | return 0; | 1189 | return 0; |
@@ -1300,6 +1341,13 @@ static s32 btf_fwd_check_meta(struct btf_verifier_env *env, | |||
1300 | return -EINVAL; | 1341 | return -EINVAL; |
1301 | } | 1342 | } |
1302 | 1343 | ||
1344 | /* fwd type must have a valid name */ | ||
1345 | if (!t->name_off || | ||
1346 | !btf_name_valid_identifier(env->btf, t->name_off)) { | ||
1347 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1348 | return -EINVAL; | ||
1349 | } | ||
1350 | |||
1303 | btf_verifier_log_type(env, t, NULL); | 1351 | btf_verifier_log_type(env, t, NULL); |
1304 | 1352 | ||
1305 | return 0; | 1353 | return 0; |
@@ -1356,6 +1404,12 @@ static s32 btf_array_check_meta(struct btf_verifier_env *env, | |||
1356 | return -EINVAL; | 1404 | return -EINVAL; |
1357 | } | 1405 | } |
1358 | 1406 | ||
1407 | /* array type should not have a name */ | ||
1408 | if (t->name_off) { | ||
1409 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1410 | return -EINVAL; | ||
1411 | } | ||
1412 | |||
1359 | if (btf_type_vlen(t)) { | 1413 | if (btf_type_vlen(t)) { |
1360 | btf_verifier_log_type(env, t, "vlen != 0"); | 1414 | btf_verifier_log_type(env, t, "vlen != 0"); |
1361 | return -EINVAL; | 1415 | return -EINVAL; |
@@ -1532,6 +1586,13 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, | |||
1532 | return -EINVAL; | 1586 | return -EINVAL; |
1533 | } | 1587 | } |
1534 | 1588 | ||
1589 | /* struct type either no name or a valid one */ | ||
1590 | if (t->name_off && | ||
1591 | !btf_name_valid_identifier(env->btf, t->name_off)) { | ||
1592 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1593 | return -EINVAL; | ||
1594 | } | ||
1595 | |||
1535 | btf_verifier_log_type(env, t, NULL); | 1596 | btf_verifier_log_type(env, t, NULL); |
1536 | 1597 | ||
1537 | last_offset = 0; | 1598 | last_offset = 0; |
@@ -1543,6 +1604,12 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env, | |||
1543 | return -EINVAL; | 1604 | return -EINVAL; |
1544 | } | 1605 | } |
1545 | 1606 | ||
1607 | /* struct member either no name or a valid one */ | ||
1608 | if (member->name_off && | ||
1609 | !btf_name_valid_identifier(btf, member->name_off)) { | ||
1610 | btf_verifier_log_member(env, t, member, "Invalid name"); | ||
1611 | return -EINVAL; | ||
1612 | } | ||
1546 | /* A member cannot be in type void */ | 1613 | /* A member cannot be in type void */ |
1547 | if (!member->type || !BTF_TYPE_ID_VALID(member->type)) { | 1614 | if (!member->type || !BTF_TYPE_ID_VALID(member->type)) { |
1548 | btf_verifier_log_member(env, t, member, | 1615 | btf_verifier_log_member(env, t, member, |
@@ -1730,6 +1797,13 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env, | |||
1730 | return -EINVAL; | 1797 | return -EINVAL; |
1731 | } | 1798 | } |
1732 | 1799 | ||
1800 | /* enum type either no name or a valid one */ | ||
1801 | if (t->name_off && | ||
1802 | !btf_name_valid_identifier(env->btf, t->name_off)) { | ||
1803 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1804 | return -EINVAL; | ||
1805 | } | ||
1806 | |||
1733 | btf_verifier_log_type(env, t, NULL); | 1807 | btf_verifier_log_type(env, t, NULL); |
1734 | 1808 | ||
1735 | for (i = 0; i < nr_enums; i++) { | 1809 | for (i = 0; i < nr_enums; i++) { |
@@ -1739,6 +1813,14 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env, | |||
1739 | return -EINVAL; | 1813 | return -EINVAL; |
1740 | } | 1814 | } |
1741 | 1815 | ||
1816 | /* enum member must have a valid name */ | ||
1817 | if (!enums[i].name_off || | ||
1818 | !btf_name_valid_identifier(btf, enums[i].name_off)) { | ||
1819 | btf_verifier_log_type(env, t, "Invalid name"); | ||
1820 | return -EINVAL; | ||
1821 | } | ||
1822 | |||
1823 | |||
1742 | btf_verifier_log(env, "\t%s val=%d\n", | 1824 | btf_verifier_log(env, "\t%s val=%d\n", |
1743 | btf_name_by_offset(btf, enums[i].name_off), | 1825 | btf_name_by_offset(btf, enums[i].name_off), |
1744 | enums[i].val); | 1826 | enums[i].val); |