diff options
Diffstat (limited to 'kernel')
| -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; |
