aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2018-07-26 12:57:59 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-07-26 21:45:49 -0400
commit5f300e8004cb80182a24c0fa488218a4a43e6aac (patch)
treee426308d24c517904c0e7117aa2878964d3b02e0
parent36e0f12bbfd3016f495904b35e41c5711707509f (diff)
bpf: btf: Use exact btf value_size match in map_check_btf()
The current map_check_btf() in BPF_MAP_TYPE_ARRAY rejects '> map->value_size' to ensure map_seq_show_elem() will not access things beyond an array element. Yonghong suggested that using '!=' is a more correct check. The 8 bytes round_up on value_size is stored in array->elem_size. Hence, using '!=' on map->value_size is a proper check. This patch also adds new tests to check the btf array key type and value type. Two of these new tests verify the btf's value_size (the change in this patch). It also fixes two existing tests that wrongly encoded a btf's type size (pprint_test) and the value_type_id (in one of the raw_tests[]). However, that do not affect these two BTF verification tests before or after this test changes. These two tests mainly failed at array creation time after this patch. Fixes: a26ca7c982cb ("bpf: btf: Add pretty print support to the basic arraymap") Suggested-by: Yonghong Song <yhs@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--kernel/bpf/arraymap.c2
-rw-r--r--tools/testing/selftests/bpf/test_btf.c86
2 files changed, 85 insertions, 3 deletions
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 544e58f5f642..2aa55d030c77 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -378,7 +378,7 @@ static int array_map_check_btf(const struct bpf_map *map, const struct btf *btf,
378 return -EINVAL; 378 return -EINVAL;
379 379
380 value_type = btf_type_id_size(btf, &btf_value_id, &value_size); 380 value_type = btf_type_id_size(btf, &btf_value_id, &value_size);
381 if (!value_type || value_size > map->value_size) 381 if (!value_type || value_size != map->value_size)
382 return -EINVAL; 382 return -EINVAL;
383 383
384 return 0; 384 return 0;
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index 402c0f7cc418..ffdd27737c9e 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -507,7 +507,7 @@ static struct btf_raw_test raw_tests[] = {
507 .key_size = sizeof(int), 507 .key_size = sizeof(int),
508 .value_size = sizeof(void *) * 4, 508 .value_size = sizeof(void *) * 4,
509 .key_type_id = 1, 509 .key_type_id = 1,
510 .value_type_id = 4, 510 .value_type_id = 5,
511 .max_entries = 4, 511 .max_entries = 4,
512}, 512},
513 513
@@ -1292,6 +1292,88 @@ static struct btf_raw_test raw_tests[] = {
1292 .err_str = "type != 0", 1292 .err_str = "type != 0",
1293}, 1293},
1294 1294
1295{
1296 .descr = "arraymap invalid btf key (a bit field)",
1297 .raw_types = {
1298 /* int */ /* [1] */
1299 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1300 /* 32 bit int with 32 bit offset */ /* [2] */
1301 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
1302 BTF_END_RAW,
1303 },
1304 .str_sec = "",
1305 .str_sec_size = sizeof(""),
1306 .map_type = BPF_MAP_TYPE_ARRAY,
1307 .map_name = "array_map_check_btf",
1308 .key_size = sizeof(int),
1309 .value_size = sizeof(int),
1310 .key_type_id = 2,
1311 .value_type_id = 1,
1312 .max_entries = 4,
1313 .map_create_err = true,
1314},
1315
1316{
1317 .descr = "arraymap invalid btf key (!= 32 bits)",
1318 .raw_types = {
1319 /* int */ /* [1] */
1320 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1321 /* 16 bit int with 0 bit offset */ /* [2] */
1322 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
1323 BTF_END_RAW,
1324 },
1325 .str_sec = "",
1326 .str_sec_size = sizeof(""),
1327 .map_type = BPF_MAP_TYPE_ARRAY,
1328 .map_name = "array_map_check_btf",
1329 .key_size = sizeof(int),
1330 .value_size = sizeof(int),
1331 .key_type_id = 2,
1332 .value_type_id = 1,
1333 .max_entries = 4,
1334 .map_create_err = true,
1335},
1336
1337{
1338 .descr = "arraymap invalid btf value (too small)",
1339 .raw_types = {
1340 /* int */ /* [1] */
1341 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1342 BTF_END_RAW,
1343 },
1344 .str_sec = "",
1345 .str_sec_size = sizeof(""),
1346 .map_type = BPF_MAP_TYPE_ARRAY,
1347 .map_name = "array_map_check_btf",
1348 .key_size = sizeof(int),
1349 /* btf_value_size < map->value_size */
1350 .value_size = sizeof(__u64),
1351 .key_type_id = 1,
1352 .value_type_id = 1,
1353 .max_entries = 4,
1354 .map_create_err = true,
1355},
1356
1357{
1358 .descr = "arraymap invalid btf value (too big)",
1359 .raw_types = {
1360 /* int */ /* [1] */
1361 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1362 BTF_END_RAW,
1363 },
1364 .str_sec = "",
1365 .str_sec_size = sizeof(""),
1366 .map_type = BPF_MAP_TYPE_ARRAY,
1367 .map_name = "array_map_check_btf",
1368 .key_size = sizeof(int),
1369 /* btf_value_size > map->value_size */
1370 .value_size = sizeof(__u16),
1371 .key_type_id = 1,
1372 .value_type_id = 1,
1373 .max_entries = 4,
1374 .map_create_err = true,
1375},
1376
1295}; /* struct btf_raw_test raw_tests[] */ 1377}; /* struct btf_raw_test raw_tests[] */
1296 1378
1297static const char *get_next_str(const char *start, const char *end) 1379static const char *get_next_str(const char *start, const char *end)
@@ -2051,7 +2133,7 @@ static struct btf_raw_test pprint_test = {
2051 BTF_ENUM_ENC(NAME_TBD, 2), 2133 BTF_ENUM_ENC(NAME_TBD, 2),
2052 BTF_ENUM_ENC(NAME_TBD, 3), 2134 BTF_ENUM_ENC(NAME_TBD, 3),
2053 /* struct pprint_mapv */ /* [16] */ 2135 /* struct pprint_mapv */ /* [16] */
2054 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 28), 2136 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
2055 BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */ 2137 BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */
2056 BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */ 2138 BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */
2057 BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */ 2139 BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */