|
@@ -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 || \
|
|
@@ -312,6 +315,30 @@ int bpf_map_new_fd(struct bpf_map *map)
|
|
|
offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
|
|
|
sizeof(attr->CMD##_LAST_FIELD)) != NULL
|
|
|
|
|
|
+/* 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 numa_node
|
|
|
/* called via syscall */
|
|
|
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)
|
|
|
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)
|
|
|
{
|
|
@@ -1037,6 +1064,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)
|
|
@@ -1358,8 +1390,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_map_ids = (u32 *)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;
|