diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 25d074920a00..45970df3f820 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <linux/version.h> | 23 | #include <linux/version.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/idr.h> | 25 | #include <linux/idr.h> |
26 | #include <linux/cred.h> | ||
27 | #include <linux/timekeeping.h> | ||
28 | #include <linux/ctype.h> | ||
26 | 29 | ||
27 | #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \ | 30 | #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \ |
28 | (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ | 31 | (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ |
@@ -312,6 +315,30 @@ int bpf_map_new_fd(struct bpf_map *map) | |||
312 | offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ | 315 | offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ |
313 | sizeof(attr->CMD##_LAST_FIELD)) != NULL | 316 | sizeof(attr->CMD##_LAST_FIELD)) != NULL |
314 | 317 | ||
318 | /* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes. | ||
319 | * Return 0 on success and < 0 on error. | ||
320 | */ | ||
321 | static int bpf_obj_name_cpy(char *dst, const char *src) | ||
322 | { | ||
323 | const char *end = src + BPF_OBJ_NAME_LEN; | ||
324 | |||
325 | /* Copy all isalnum() and '_' char */ | ||
326 | while (src < end && *src) { | ||
327 | if (!isalnum(*src) && *src != '_') | ||
328 | return -EINVAL; | ||
329 | *dst++ = *src++; | ||
330 | } | ||
331 | |||
332 | /* No '\0' found in BPF_OBJ_NAME_LEN number of bytes */ | ||
333 | if (src == end) | ||
334 | return -EINVAL; | ||
335 | |||
336 | /* '\0' terminates dst */ | ||
337 | *dst = 0; | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
315 | #define BPF_MAP_CREATE_LAST_FIELD numa_node | 342 | #define BPF_MAP_CREATE_LAST_FIELD numa_node |
316 | /* called via syscall */ | 343 | /* called via syscall */ |
317 | static int map_create(union bpf_attr *attr) | 344 | static int map_create(union bpf_attr *attr) |
@@ -973,7 +1000,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type) | |||
973 | EXPORT_SYMBOL_GPL(bpf_prog_get_type); | 1000 | EXPORT_SYMBOL_GPL(bpf_prog_get_type); |
974 | 1001 | ||
975 | /* last field in 'union bpf_attr' used by this command */ | 1002 | /* last field in 'union bpf_attr' used by this command */ |
976 | #define BPF_PROG_LOAD_LAST_FIELD prog_flags | 1003 | #define BPF_PROG_LOAD_LAST_FIELD prog_name |
977 | 1004 | ||
978 | static int bpf_prog_load(union bpf_attr *attr) | 1005 | static int bpf_prog_load(union bpf_attr *attr) |
979 | { | 1006 | { |
@@ -1037,6 +1064,11 @@ static int bpf_prog_load(union bpf_attr *attr) | |||
1037 | if (err < 0) | 1064 | if (err < 0) |
1038 | goto free_prog; | 1065 | goto free_prog; |
1039 | 1066 | ||
1067 | prog->aux->load_time = ktime_get_boot_ns(); | ||
1068 | err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name); | ||
1069 | if (err) | ||
1070 | goto free_prog; | ||
1071 | |||
1040 | /* run eBPF verifier */ | 1072 | /* run eBPF verifier */ |
1041 | err = bpf_check(&prog, attr); | 1073 | err = bpf_check(&prog, attr); |
1042 | if (err < 0) | 1074 | if (err < 0) |
@@ -1358,8 +1390,25 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, | |||
1358 | 1390 | ||
1359 | info.type = prog->type; | 1391 | info.type = prog->type; |
1360 | info.id = prog->aux->id; | 1392 | info.id = prog->aux->id; |
1393 | info.load_time = prog->aux->load_time; | ||
1394 | info.created_by_uid = from_kuid_munged(current_user_ns(), | ||
1395 | prog->aux->user->uid); | ||
1361 | 1396 | ||
1362 | memcpy(info.tag, prog->tag, sizeof(prog->tag)); | 1397 | memcpy(info.tag, prog->tag, sizeof(prog->tag)); |
1398 | memcpy(info.name, prog->aux->name, sizeof(prog->aux->name)); | ||
1399 | |||
1400 | ulen = info.nr_map_ids; | ||
1401 | info.nr_map_ids = prog->aux->used_map_cnt; | ||
1402 | ulen = min_t(u32, info.nr_map_ids, ulen); | ||
1403 | if (ulen) { | ||
1404 | u32 *user_map_ids = (u32 *)info.map_ids; | ||
1405 | u32 i; | ||
1406 | |||
1407 | for (i = 0; i < ulen; i++) | ||
1408 | if (put_user(prog->aux->used_maps[i]->id, | ||
1409 | &user_map_ids[i])) | ||
1410 | return -EFAULT; | ||
1411 | } | ||
1363 | 1412 | ||
1364 | if (!capable(CAP_SYS_ADMIN)) { | 1413 | if (!capable(CAP_SYS_ADMIN)) { |
1365 | info.jited_prog_len = 0; | 1414 | info.jited_prog_len = 0; |