]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/bpf/syscall.c
bpf: Fix compiler warning on info.map_ids for 32bit platform
[linux.git] / kernel / bpf / syscall.c
index cb17e1cd1d434dc2e052a2a9fb0aea967fcf4417..b927da66f653f47e3193fbf430577a072bc6b606 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/idr.h>
+#include <linux/cred.h>
+#include <linux/timekeeping.h>
+#include <linux/ctype.h>
 
 #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \
                           (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
@@ -186,15 +189,17 @@ static int bpf_map_alloc_id(struct bpf_map *map)
 
 static void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
 {
+       unsigned long flags;
+
        if (do_idr_lock)
-               spin_lock_bh(&map_idr_lock);
+               spin_lock_irqsave(&map_idr_lock, flags);
        else
                __acquire(&map_idr_lock);
 
        idr_remove(&map_idr, map->id);
 
        if (do_idr_lock)
-               spin_unlock_bh(&map_idr_lock);
+               spin_unlock_irqrestore(&map_idr_lock, flags);
        else
                __release(&map_idr_lock);
 }
@@ -310,7 +315,31 @@ int bpf_map_new_fd(struct bpf_map *map)
                   offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
                   sizeof(attr->CMD##_LAST_FIELD)) != NULL
 
-#define BPF_MAP_CREATE_LAST_FIELD numa_node
+/* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes.
+ * Return 0 on success and < 0 on error.
+ */
+static int bpf_obj_name_cpy(char *dst, const char *src)
+{
+       const char *end = src + BPF_OBJ_NAME_LEN;
+
+       /* Copy all isalnum() and '_' char */
+       while (src < end && *src) {
+               if (!isalnum(*src) && *src != '_')
+                       return -EINVAL;
+               *dst++ = *src++;
+       }
+
+       /* No '\0' found in BPF_OBJ_NAME_LEN number of bytes */
+       if (src == end)
+               return -EINVAL;
+
+       /* '\0' terminates dst */
+       *dst = 0;
+
+       return 0;
+}
+
+#define BPF_MAP_CREATE_LAST_FIELD map_name
 /* called via syscall */
 static int map_create(union bpf_attr *attr)
 {
@@ -332,6 +361,10 @@ static int map_create(union bpf_attr *attr)
        if (IS_ERR(map))
                return PTR_ERR(map);
 
+       err = bpf_obj_name_cpy(map->name, attr->map_name);
+       if (err)
+               goto free_map_nouncharge;
+
        atomic_set(&map->refcnt, 1);
        atomic_set(&map->usercnt, 1);
 
@@ -971,7 +1004,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
 EXPORT_SYMBOL_GPL(bpf_prog_get_type);
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD prog_flags
+#define        BPF_PROG_LOAD_LAST_FIELD prog_name
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -1035,6 +1068,11 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (err < 0)
                goto free_prog;
 
+       prog->aux->load_time = ktime_get_boot_ns();
+       err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name);
+       if (err)
+               goto free_prog;
+
        /* run eBPF verifier */
        err = bpf_check(&prog, attr);
        if (err < 0)
@@ -1356,8 +1394,25 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
 
        info.type = prog->type;
        info.id = prog->aux->id;
+       info.load_time = prog->aux->load_time;
+       info.created_by_uid = from_kuid_munged(current_user_ns(),
+                                              prog->aux->user->uid);
 
        memcpy(info.tag, prog->tag, sizeof(prog->tag));
+       memcpy(info.name, prog->aux->name, sizeof(prog->aux->name));
+
+       ulen = info.nr_map_ids;
+       info.nr_map_ids = prog->aux->used_map_cnt;
+       ulen = min_t(u32, info.nr_map_ids, ulen);
+       if (ulen) {
+               u32 __user *user_map_ids = u64_to_user_ptr(info.map_ids);
+               u32 i;
+
+               for (i = 0; i < ulen; i++)
+                       if (put_user(prog->aux->used_maps[i]->id,
+                                    &user_map_ids[i]))
+                               return -EFAULT;
+       }
 
        if (!capable(CAP_SYS_ADMIN)) {
                info.jited_prog_len = 0;
@@ -1411,6 +1466,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
        info.value_size = map->value_size;
        info.max_entries = map->max_entries;
        info.map_flags = map->map_flags;
+       memcpy(info.name, map->name, sizeof(map->name));
 
        if (copy_to_user(uinfo, &info, info_len) ||
            put_user(info_len, &uattr->info.info_len))