Skip to content

Commit b402d84

Browse files
AsphalttKernel Patches Daemon
authored andcommitted
bpf: Add common attr support for map_create
Currently, many 'BPF_MAP_CREATE' failures return '-EINVAL' without providing any explanation to user space. With the extended BPF syscall support, detailed error messages can now be reported. This allows users to understand the specific reason for a failed map creation, rather than just receiving a generic '-EINVAL'. Signed-off-by: Leon Hwang <[email protected]>
1 parent 77fba26 commit b402d84

File tree

1 file changed

+87
-9
lines changed

1 file changed

+87
-9
lines changed

kernel/bpf/syscall.c

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,55 +1355,116 @@ static bool bpf_net_capable(void)
13551355
return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
13561356
}
13571357

1358+
struct bpf_vlog_wrapper {
1359+
struct bpf_common_attr *attr;
1360+
struct bpf_verifier_log *log;
1361+
};
1362+
1363+
static void bpf_vlog_wrapper_destructor(struct bpf_vlog_wrapper *w)
1364+
{
1365+
if (!w->log)
1366+
return;
1367+
1368+
(void) bpf_vlog_finalize(w->log, &w->attr->log_true_size);
1369+
kfree(w->log);
1370+
}
1371+
1372+
#define DEFINE_BPF_VLOG_WRAPPER(name, common_attrs) \
1373+
struct bpf_vlog_wrapper name __cleanup(bpf_vlog_wrapper_destructor) = { \
1374+
.attr = common_attrs, \
1375+
}
1376+
1377+
static int bpf_vlog_wrapper_init(struct bpf_vlog_wrapper *w)
1378+
{
1379+
struct bpf_common_attr *attr = w->attr;
1380+
struct bpf_verifier_log *log;
1381+
int err;
1382+
1383+
if (!attr->log_buf)
1384+
return 0;
1385+
1386+
log = kzalloc(sizeof(*log), GFP_KERNEL);
1387+
if (!log)
1388+
return -ENOMEM;
1389+
1390+
err = bpf_vlog_init(log, attr->log_level, u64_to_user_ptr(attr->log_buf), attr->log_size);
1391+
if (err) {
1392+
kfree(log);
1393+
return err;
1394+
}
1395+
1396+
w->log = log;
1397+
return 0;
1398+
}
1399+
13581400
#define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
13591401
/* called via syscall */
1360-
static int map_create(union bpf_attr *attr, bpfptr_t uattr)
1402+
static int map_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_attr *common_attrs)
13611403
{
13621404
const struct bpf_map_ops *ops;
13631405
struct bpf_token *token = NULL;
13641406
int numa_node = bpf_map_attr_numa_node(attr);
13651407
u32 map_type = attr->map_type;
1408+
struct bpf_verifier_log *log;
13661409
struct bpf_map *map;
13671410
bool token_flag;
13681411
int f_flags;
13691412
int err;
1413+
DEFINE_BPF_VLOG_WRAPPER(log_wrapper, common_attrs);
13701414

13711415
err = CHECK_ATTR(BPF_MAP_CREATE);
13721416
if (err)
13731417
return -EINVAL;
13741418

1419+
err = bpf_vlog_wrapper_init(&log_wrapper);
1420+
if (err)
1421+
return err;
1422+
log = log_wrapper.log;
1423+
13751424
/* check BPF_F_TOKEN_FD flag, remember if it's set, and then clear it
13761425
* to avoid per-map type checks tripping on unknown flag
13771426
*/
13781427
token_flag = attr->map_flags & BPF_F_TOKEN_FD;
13791428
attr->map_flags &= ~BPF_F_TOKEN_FD;
13801429

13811430
if (attr->btf_vmlinux_value_type_id) {
1382-
if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
1383-
attr->btf_key_type_id || attr->btf_value_type_id)
1431+
if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS) {
1432+
bpf_log(log, "btf_vmlinux_value_type_id can only be used with struct_ops maps.\n");
1433+
return -EINVAL;
1434+
}
1435+
if (attr->btf_key_type_id || attr->btf_value_type_id) {
1436+
bpf_log(log, "btf_vmlinux_value_type_id is mutually exclusive with btf_key_type_id and btf_value_type_id.\n");
13841437
return -EINVAL;
1438+
}
13851439
} else if (attr->btf_key_type_id && !attr->btf_value_type_id) {
1440+
bpf_log(log, "Invalid btf_value_type_id.\n");
13861441
return -EINVAL;
13871442
}
13881443

13891444
if (attr->map_type != BPF_MAP_TYPE_BLOOM_FILTER &&
13901445
attr->map_type != BPF_MAP_TYPE_ARENA &&
1391-
attr->map_extra != 0)
1446+
attr->map_extra != 0) {
1447+
bpf_log(log, "Invalid map_extra.\n");
13921448
return -EINVAL;
1449+
}
13931450

13941451
f_flags = bpf_get_file_flag(attr->map_flags);
13951452
if (f_flags < 0)
13961453
return f_flags;
13971454

13981455
if (numa_node != NUMA_NO_NODE &&
13991456
((unsigned int)numa_node >= nr_node_ids ||
1400-
!node_online(numa_node)))
1457+
!node_online(numa_node))) {
1458+
bpf_log(log, "Invalid numa_node.\n");
14011459
return -EINVAL;
1460+
}
14021461

14031462
/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
14041463
map_type = attr->map_type;
1405-
if (map_type >= ARRAY_SIZE(bpf_map_types))
1464+
if (map_type >= ARRAY_SIZE(bpf_map_types)) {
1465+
bpf_log(log, "Invalid map_type.\n");
14061466
return -EINVAL;
1467+
}
14071468
map_type = array_index_nospec(map_type, ARRAY_SIZE(bpf_map_types));
14081469
ops = bpf_map_types[map_type];
14091470
if (WARN_ON_ONCE(!ops))
@@ -1421,8 +1482,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
14211482

14221483
if (token_flag) {
14231484
token = bpf_token_get_from_fd(attr->map_token_fd);
1424-
if (IS_ERR(token))
1485+
if (IS_ERR(token)) {
1486+
bpf_log(log, "Invalid map_token_fd.\n");
14251487
return PTR_ERR(token);
1488+
}
14261489

14271490
/* if current token doesn't grant map creation permissions,
14281491
* then we can't use this token, so ignore it and rely on
@@ -1504,8 +1567,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
15041567

15051568
err = bpf_obj_name_cpy(map->name, attr->map_name,
15061569
sizeof(attr->map_name));
1507-
if (err < 0)
1570+
if (err < 0) {
1571+
bpf_log(log, "Invalid map_name.\n");
15081572
goto free_map;
1573+
}
15091574

15101575
preempt_disable();
15111576
map->cookie = gen_cookie_next(&bpf_map_cookie);
@@ -1528,6 +1593,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
15281593

15291594
btf = btf_get_by_fd(attr->btf_fd);
15301595
if (IS_ERR(btf)) {
1596+
bpf_log(log, "Invalid btf_fd.\n");
15311597
err = PTR_ERR(btf);
15321598
goto free_map;
15331599
}
@@ -6132,6 +6198,15 @@ static int __copy_common_attr_log_true_size(bpfptr_t uattr, unsigned int size, u
61326198
return 0;
61336199
}
61346200

6201+
static int copy_common_attr_log_true_size(bpfptr_t uattr, unsigned int size,
6202+
struct bpf_common_attr *attr)
6203+
{
6204+
if (!attr->log_true_size)
6205+
return 0;
6206+
6207+
return __copy_common_attr_log_true_size(uattr, size, &attr->log_true_size);
6208+
}
6209+
61356210
static int copy_prog_load_log_true_size(union bpf_attr *attr, bpfptr_t uattr, unsigned int size,
61366211
struct bpf_common_attr *common_attrs, bpfptr_t uattr_common,
61376212
unsigned int size_common, bool log_common_attrs)
@@ -6226,7 +6301,10 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
62266301

62276302
switch (cmd) {
62286303
case BPF_MAP_CREATE:
6229-
err = map_create(&attr, uattr);
6304+
common_attrs.log_true_size = 0;
6305+
err = map_create(&attr, uattr, &common_attrs);
6306+
ret = copy_common_attr_log_true_size(uattr_common, size_common, &common_attrs);
6307+
err = ret ? ret : err;
62306308
break;
62316309
case BPF_MAP_LOOKUP_ELEM:
62326310
err = map_lookup_elem(&attr);

0 commit comments

Comments
 (0)