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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 15 May 2015 07:51:01 +0000
From:	Wang Nan <wangnan0@...wei.com>
To:	<paulus@...ba.org>, <a.p.zijlstra@...llo.nl>, <mingo@...hat.com>,
	<acme@...nel.org>, <namhyung@...nel.org>, <jolsa@...nel.org>,
	<adrian.hunter@...el.com>, <dsahern@...il.com>, <ast@...mgrid.com>,
	<daniel@...earbox.net>, <brendan.d.gregg@...il.com>,
	<masami.hiramatsu.pt@...achi.com>
CC:	<linux-kernel@...r.kernel.org>, <lizefan@...wei.com>,
	<pi3orama@....com>, <wangnan0@...wei.com>
Subject: [RFC PATCH v2 08/37] tools lib bpf: open eBPF object file and do basic validation.

This patch adds basic 'struct bpf_object' which will be used for eBPF
object file 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 elf field of
'struct bpf_object'. bpf_obj_clear_elf() is introduced to clear it.

Signed-off-by: Wang Nan <wangnan0@...wei.com>
---
 tools/lib/bpf/libbpf.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 154 insertions(+), 2 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index f8decff..43c16bc 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -12,9 +12,12 @@
 #include <stdarg.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
 #include <linux/bpf.h>
+#include <libelf.h>
+#include <gelf.h>
 
 #include "libbpf.h"
 
@@ -58,12 +61,161 @@ void libbpf_set_print(int (*warn)(const char *format, ...),
 	__pr_debug = debug;
 }
 
-struct bpf_object *bpf_open_object(const char *path)
+#ifdef HAVE_LIBELF_MMAP_SUPPORT
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#else
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
+#endif
+
+struct bpf_object {
+	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)
+
+static struct bpf_object *__bpf_obj_alloc(const char *path)
+{
+	struct bpf_object *obj;
+
+	obj = calloc(1, sizeof(struct bpf_object));
+	if (!obj) {
+		pr_warning("alloc memory failed for %s\n", path);
+		return NULL;
+	}
+
+	obj->path = strdup(path);
+	if (!obj->path) {
+		pr_warning("failed to strdup '%s'\n", path);
+		free(obj);
+		return NULL;
+	}
+	return obj;
+}
+
+static struct bpf_object *bpf_obj_alloc(const char *path)
 {
+	struct bpf_object *obj;
+
+	obj = __bpf_obj_alloc(path);
+	if (!obj)
+		goto out;
+
+	obj->elf.fd = -1;
+	return obj;
+out:
+	bpf_close_object(obj);
 	return NULL;
 }
 
-void bpf_close_object(struct bpf_object *object)
+static void bpf_obj_clear_elf(struct bpf_object *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 int bpf_obj_elf_init(struct bpf_object *obj)
 {
+	int err = 0;
+	GElf_Ehdr *ep;
+
+	if (obj_elf_valid(obj)) {
+		pr_warning("elf init: internal error\n");
+		return -EEXIST;
+	}
+	
+	obj->elf.fd = open(obj->path, O_RDONLY);
+	if (obj->elf.fd < 0) {
+		pr_warning("failed to open %s: %s\n", obj->path,
+				strerror(errno));
+		return -errno;
+	}
+
+	obj->elf.elf = elf_begin(obj->elf.fd,
+				 LIBBPF_ELF_C_READ_MMAP,
+				 NULL);
+	if (!obj->elf.elf) {
+		pr_warning("failed to open %s as ELF file\n",
+				obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
+	if (!gelf_getehdr(obj->elf.elf, &obj->elf.ehdr)) {
+		pr_warning("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_warning("%s is not an eBPF object file\n",
+			obj->path);
+		err = -EINVAL;
+		goto errout;
+	}
+
 	return 0;
+errout:
+	bpf_obj_clear_elf(obj);
+	return err;
+}
+
+struct bpf_object *bpf_open_object(const char *path)
+{
+	struct bpf_object *obj;
+
+	/* param validation */
+	if (!path)
+		return NULL;
+
+ 	pr_debug("loading %s\n", path);
+
+	if (elf_version(EV_CURRENT) == EV_NONE) {
+		pr_warning("failed to init libelf for %s\n", path);
+		return NULL;
+	}
+
+	obj = bpf_obj_alloc(path);
+	if (!obj)
+		return NULL;
+
+	if (bpf_obj_elf_init(obj))
+		goto out;
+
+	return obj;
+
+out:
+	bpf_close_object(obj);
+	return NULL;
+}
+
+void bpf_close_object(struct bpf_object *obj)
+{
+	if (!obj)
+		return;
+
+	bpf_obj_clear_elf(obj);
+
+	if (obj->path)
+		free(obj->path);
+	free(obj);
 }
-- 
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