lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 30 Apr 2015 10:52:28 +0000
From:	Wang Nan <wangnan0@...wei.com>
To:	<ast@...mgrid.com>, <davem@...emloft.net>, <acme@...nel.org>,
	<mingo@...hat.com>, <a.p.zijlstra@...llo.nl>,
	<masami.hiramatsu.pt@...achi.com>, <jolsa@...nel.org>
CC:	<lizefan@...nel.org>, <linux-kernel@...r.kernel.org>,
	<pi3orama@....com>, <hekuang@...wei.com>
Subject: [RFC PATCH 05/22] perf bpf: open eBPF object file and do basic validation.

This patch adds basic 'struct bpf_obj' which will be used for eBPF
object files loading. eBPF object files are compiled by LLVM as ELF
format. In this patch, libelf is used to open those files, read EHDR
and do basic validation according to e_type and e_machine.

All elf related staffs are grouped together and reside in
'struct bpf_obj'. bpf_obj_clear_elf() is introduced to clear it.

Signed-off-by: Wang Nan <wangnan0@...wei.com>
---
 tools/perf/util/bpf-loader.c | 133 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-loader.h |  16 ++++++
 2 files changed, 149 insertions(+)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 84d3cc3..3eb7504 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -20,10 +20,143 @@
 #include <linux/types.h>
 #include <linux/bpf.h>
 
+static LIST_HEAD(bpf_obj_list);
+
+static struct bpf_obj *__bpf_obj_alloc(const char *path)
+{
+	struct bpf_obj *obj;
+
+	obj = calloc(1, sizeof(struct bpf_obj));
+	if (!obj) {
+		pr_err("bpf: alloc memory failed for %s\n", path);
+		return NULL;
+	}
+
+	obj->path = strdup(path);
+	if (!obj->path) {
+		pr_err("bpf: failed to strdup '%s'\n", path);
+		free(obj);
+		return NULL;
+	}
+	return obj;
+}
+
+static void bpf_obj_clear_elf(struct bpf_obj *obj)
+{
+	if (!obj_elf_valid(obj))
+		return;
+
+	if (obj->elf.elf) {
+		elf_end(obj->elf.elf);
+		obj->elf.elf = NULL;
+	}
+	if (obj->elf.fd >= 0) {
+		close(obj->elf.fd);
+		obj->elf.fd = -1;
+	}
+}
+
+static void bpf_obj_close(struct bpf_obj *obj)
+{
+	if (!obj)
+		return;
+
+	bpf_obj_clear_elf(obj);
+
+	if (obj->path)
+		free(obj->path);
+	free(obj);
+}
+
+static struct bpf_obj *bpf_obj_alloc(const char *path)
+{
+	struct bpf_obj *obj;
+
+	obj = __bpf_obj_alloc(path);
+	if (!obj)
+		goto out;
+
+	obj->elf.fd = -1;
+	return obj;
+out:
+	bpf_obj_close(obj);
+	return NULL;
+}
+
+static int bpf_obj_elf_init(struct bpf_obj *obj)
+{
+	int err = 0;
+	GElf_Ehdr *ep;
+
+	if (obj_elf_valid(obj)) {
+		pr_err("bpf: elf init: internal error\n");
+		return -EEXIST;
+	}
+	
+	obj->elf.fd = open(obj->path, O_RDONLY);
+	if (obj->elf.fd < 0) {
+		pr_err("bpf: failed to open %s: %s\n", obj->path,
+				strerror(errno));
+		return -errno;
+	}
+
+	obj->elf.elf = elf_begin(obj->elf.fd,
+				 PERF_ELF_C_READ_MMAP,
+				 NULL);
+	if (!obj->elf.elf) {
+		pr_err("bpf: failed to open %s as ELF file\n",
+				obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	if (!gelf_getehdr(obj->elf.elf, &obj->elf.ehdr)) {
+		pr_err("bpf: failed to get EHDR from %s\n",
+				obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+	ep = &obj->elf.ehdr;
+
+	if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
+		pr_err("bpf: %s is not an eBPF object file\n",
+			obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	return 0;
+errout:
+	bpf_obj_clear_elf(obj);
+	return err;
+}
+
 int bpf__load(const char *path)
 {
+	struct bpf_obj *obj;
+	int err;
+
 	pr_debug("bpf: loading %s\n", path);
+
+	if (elf_version(EV_CURRENT) == EV_NONE) {
+		pr_err("bpf: failed to init libelf for %s\n", path);
+		return -ENOTSUP;
+	}
+
+	obj = bpf_obj_alloc(path);
+	if (!obj) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if ((err = bpf_obj_elf_init(obj)))
+		goto out;
+
+	list_add(&obj->list, &bpf_obj_list);
 	return 0;
+out:
+	bpf_obj_close(obj);
+	return -1;
 }
 
 int bpf__run(void)
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 122b178..6a6651b 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -18,4 +18,20 @@
 int bpf__load(const char *path);
 int bpf__run(void);
 
+struct bpf_obj {
+	/* All bpf objs should be linked together. */
+	struct list_head list;
+	char *path;
+
+	/*
+	 * Information when doing elf related work. Only valid if fd
+	 * is valid.
+	 */
+	struct {
+		int fd;
+		Elf *elf;
+		GElf_Ehdr ehdr;
+	} elf;
+};
+#define obj_elf_valid(o)	((o)->elf.fd >= 0)
 #endif
-- 
1.8.3.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ