aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c51
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 */
321static 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 */
317static int map_create(union bpf_attr *attr) 344static 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)
973EXPORT_SYMBOL_GPL(bpf_prog_get_type); 1000EXPORT_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
978static int bpf_prog_load(union bpf_attr *attr) 1005static 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;