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]
Message-ID: <1466940078-65581-14-git-send-email-hekuang@huawei.com>
Date:	Sun, 26 Jun 2016 11:21:05 +0000
From:	He Kuang <hekuang@...wei.com>
To:	<acme@...nel.org>, <peterz@...radead.org>, <mingo@...hat.com>,
	<jolsa@...hat.com>, <brendan.d.gregg@...il.com>, <ast@...nel.org>,
	<alexander.shishkin@...ux.intel.com>, <wangnan0@...wei.com>,
	<hekuang@...wei.com>
CC:	<linux-kernel@...r.kernel.org>
Subject: [RFC PATCH v2 13/26] perf bpf: Add abstraction for bpf program methods

Supporting different bpf program types loaded into kernel and
userspace, this patch abstracts the operations to related to bpf
program into bpf_engine. The methods set for bpf loaded into kernel
are included in engine-kbpf.c, which is used as the default value.

Signed-off-by: He Kuang <hekuang@...wei.com>
Signed-off-by: Wang Nan <wangnan0@...wei.com>
---
 tools/lib/bpf/Build             |   1 +
 tools/lib/bpf/engine-kbpf.c     | 131 ++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf-internal.h |  11 ++++
 tools/lib/bpf/libbpf.c          | 115 ++++-------------------------------
 4 files changed, 156 insertions(+), 102 deletions(-)
 create mode 100644 tools/lib/bpf/engine-kbpf.c

diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index d874975..567dcfd 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1,2 @@
 libbpf-y := libbpf.o bpf.o
+libbpf-y += engine-kbpf.o
diff --git a/tools/lib/bpf/engine-kbpf.c b/tools/lib/bpf/engine-kbpf.c
new file mode 100644
index 0000000..7d81e16
--- /dev/null
+++ b/tools/lib/bpf/engine-kbpf.c
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/bpf.h>
+
+#include "bpf.h"
+#include "libbpf-internal.h"
+
+static int engine__init(struct bpf_program *prog)
+{
+	int *instances_entries;
+	int nr_instances = prog->instances.nr;
+
+	instances_entries = malloc(sizeof(int) * nr_instances);
+	if (!instances_entries) {
+		pr_warning("alloc memory failed for instances\n");
+		return -ENOMEM;
+	}
+
+	/* fill all fd with -1 */
+	memset(instances_entries, -1, sizeof(int) * nr_instances);
+
+	prog->instances.entries = instances_entries;
+
+	return 0;
+}
+
+static int engine__get_nth(struct bpf_program *prog, int n, void *ret)
+{
+	int *pfd = (int *)ret;
+
+	if (n >= prog->instances.nr || n < 0) {
+		pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
+			   n, prog->section_name, prog->instances.nr);
+		return -EINVAL;
+	}
+
+	*pfd = ((int *)prog->instances.entries)[n];
+	if (*pfd < 0) {
+		pr_warning("%dth instance of program '%s' is invalid\n",
+			   n, prog->section_name);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static void engine__unload(struct bpf_program *prog, int index)
+{
+	zclose(((int *)prog->instances.entries)[index]);
+}
+
+static int
+load_program(struct bpf_insn *insns, int insns_cnt,
+	     char *license, u32 kern_version, int *pfd)
+{
+	int ret;
+	char *log_buf;
+
+	if (!insns || !insns_cnt)
+		return -EINVAL;
+
+	log_buf = malloc(BPF_LOG_BUF_SIZE);
+	if (!log_buf)
+		pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
+
+	ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
+			       insns_cnt, license, kern_version,
+			       log_buf, BPF_LOG_BUF_SIZE);
+
+	if (ret >= 0) {
+		*pfd = ret;
+		ret = 0;
+		goto out;
+	}
+
+	ret = -LIBBPF_ERRNO__LOAD;
+	pr_warning("load bpf program failed: %s\n", strerror(errno));
+
+	if (log_buf && log_buf[0] != '\0') {
+		ret = -LIBBPF_ERRNO__VERIFY;
+		pr_warning("-- BEGIN DUMP LOG ---\n");
+		pr_warning("\n%s\n", log_buf);
+		pr_warning("-- END LOG --\n");
+	} else {
+		if (insns_cnt >= BPF_MAXINSNS) {
+			pr_warning("Program too large (%d insns), at most %d insns\n",
+				   insns_cnt, BPF_MAXINSNS);
+			ret = -LIBBPF_ERRNO__PROG2BIG;
+		} else if (log_buf) {
+			pr_warning("log buffer is empty\n");
+			ret = -LIBBPF_ERRNO__KVER;
+		}
+	}
+
+out:
+	free(log_buf);
+	return ret;
+}
+
+static int engine__load(struct bpf_program *prog, struct bpf_insn *insns,
+			int insns_cnt, char *license,
+			u32 kern_version, int index)
+{
+	int err = 0;
+	int fd;
+
+	if (!insns || !insns_cnt) {
+		((int *)prog->instances.entries)[index] = -1;
+		pr_debug("Skip loading the %dth instance of program '%s'\n",
+			 index, prog->section_name);
+		return err;
+	}
+
+	err = load_program(insns, insns_cnt, license, kern_version, &fd);
+	if (!err)
+		((int *)prog->instances.entries)[index] = fd;
+	else
+		pr_warning("Loading the %dth instance of program '%s' failed\n",
+			   index, prog->section_name);
+
+	return err;
+}
+
+struct bpf_engine kengine = {
+	.init		= engine__init,
+	.load		= engine__load,
+	.unload		= engine__unload,
+	.get_nth	= engine__get_nth,
+};
diff --git a/tools/lib/bpf/libbpf-internal.h b/tools/lib/bpf/libbpf-internal.h
index 1c1619c..60b2f68 100644
--- a/tools/lib/bpf/libbpf-internal.h
+++ b/tools/lib/bpf/libbpf-internal.h
@@ -62,4 +62,15 @@ struct bpf_program {
 	bpf_program_clear_priv_t clear_priv;
 };
 
+struct bpf_engine {
+	int (*init)(struct bpf_program *prog);
+	int (*load)(struct bpf_program *prog, struct bpf_insn *insns,
+		    int insns_cnt, char *license,
+		    u32 kern_version, int index);
+	void (*unload)(struct bpf_program *prog, int index);
+	int (*get_nth)(struct bpf_program *prog, int index, void *ret);
+};
+
+extern struct bpf_engine kengine;
+
 #endif /* _LIBBPF_INTERNAL_H */
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0ad6c9e..a53cb579 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -172,7 +172,7 @@ static void bpf_program__unload(struct bpf_program *prog)
 	 */
 	if (prog->instances.nr > 0) {
 		for (i = 0; i < prog->instances.nr; i++)
-			zclose(((int *)prog->instances.entries)[i]);
+			prog->engine->unload(prog, i);
 	} else if (prog->instances.nr != -1) {
 		pr_warning("Internal error: instances.nr is %d\n",
 			   prog->instances.nr);
@@ -230,6 +230,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
 	memcpy(prog->insns, data,
 	       prog->insns_cnt * sizeof(struct bpf_insn));
 	prog->idx = idx;
+	prog->engine = &kengine;
 	prog->instances.entries = NULL;
 	prog->instances.nr = -1;
 
@@ -827,58 +828,10 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 }
 
 static int
-load_program(struct bpf_insn *insns, int insns_cnt,
-	     char *license, u32 kern_version, int *pfd)
-{
-	int ret;
-	char *log_buf;
-
-	if (!insns || !insns_cnt)
-		return -EINVAL;
-
-	log_buf = malloc(BPF_LOG_BUF_SIZE);
-	if (!log_buf)
-		pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
-
-	ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
-			       insns_cnt, license, kern_version,
-			       log_buf, BPF_LOG_BUF_SIZE);
-
-	if (ret >= 0) {
-		*pfd = ret;
-		ret = 0;
-		goto out;
-	}
-
-	ret = -LIBBPF_ERRNO__LOAD;
-	pr_warning("load bpf program failed: %s\n", strerror(errno));
-
-	if (log_buf && log_buf[0] != '\0') {
-		ret = -LIBBPF_ERRNO__VERIFY;
-		pr_warning("-- BEGIN DUMP LOG ---\n");
-		pr_warning("\n%s\n", log_buf);
-		pr_warning("-- END LOG --\n");
-	} else {
-		if (insns_cnt >= BPF_MAXINSNS) {
-			pr_warning("Program too large (%d insns), at most %d insns\n",
-				   insns_cnt, BPF_MAXINSNS);
-			ret = -LIBBPF_ERRNO__PROG2BIG;
-		} else if (log_buf) {
-			pr_warning("log buffer is empty\n");
-			ret = -LIBBPF_ERRNO__KVER;
-		}
-	}
-
-out:
-	free(log_buf);
-	return ret;
-}
-
-static int
 bpf_program__load(struct bpf_program *prog,
 		  char *license, u32 kern_version)
 {
-	int err = 0, fd, i;
+	int err = 0, i;
 
 	if (prog->instances.nr < 0 || !prog->instances.entries) {
 		if (prog->preprocessor) {
@@ -887,14 +840,8 @@ bpf_program__load(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__INTERNAL;
 		}
 
-		prog->instances.entries = malloc(sizeof(int));
-		if (!prog->instances.entries) {
-			pr_warning("Not enough memory for BPF entries\n");
-			return -ENOMEM;
-		}
-
 		prog->instances.nr = 1;
-		((int *)prog->instances.entries)[0] = -1;
+		prog->engine->init(prog);
 	}
 
 	if (!prog->preprocessor) {
@@ -902,10 +849,8 @@ bpf_program__load(struct bpf_program *prog,
 			pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
 				   prog->section_name, prog->instances.nr);
 		}
-		err = load_program(prog->insns, prog->insns_cnt,
-				   license, kern_version, &fd);
-		if (!err)
-			((int *)prog->instances.entries)[0] = fd;
+		prog->engine->load(prog, prog->insns, prog->insns_cnt,
+				   license, kern_version, 0);
 		goto out;
 	}
 
@@ -922,24 +867,11 @@ bpf_program__load(struct bpf_program *prog,
 			goto out;
 		}
 
-		if (!result.new_insn_ptr || !result.new_insn_cnt) {
-			pr_debug("Skip loading the %dth instance of program '%s'\n",
-				 i, prog->section_name);
-			((int *)prog->instances.entries)[i] = -1;
-			continue;
-		}
-
-		err = load_program(result.new_insn_ptr,
-				   result.new_insn_cnt,
-				   license, kern_version, &fd);
-
-		if (err) {
-			pr_warning("Loading the %dth instance of program '%s' failed\n",
-					i, prog->section_name);
+		err = prog->engine->load(prog, result.new_insn_ptr,
+					 result.new_insn_cnt, license,
+					 kern_version, i);
+		if (err)
 			goto out;
-		}
-
-		((int *)prog->instances.entries)[i] = fd;
 	}
 out:
 	if (err)
@@ -1201,8 +1133,6 @@ int bpf_program__fd(struct bpf_program *prog)
 int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 			  bpf_program_prep_t prep)
 {
-	int *instances_entries;
-
 	if (nr_instances <= 0 || !prep)
 		return -EINVAL;
 
@@ -1211,17 +1141,9 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 		return -EINVAL;
 	}
 
-	instances_entries = malloc(sizeof(int) * nr_instances);
-	if (!instances_entries) {
-		pr_warning("alloc memory failed for entries\n");
-		return -ENOMEM;
-	}
-
-	/* fill all fd with -1 */
-	memset(instances_entries, -1, sizeof(int) * nr_instances);
-
 	prog->instances.nr = nr_instances;
-	prog->instances.entries = instances_entries;
+	prog->engine->init(prog);
+
 	prog->preprocessor = prep;
 	return 0;
 }
@@ -1230,18 +1152,7 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
 {
 	int fd;
 
-	if (n >= prog->instances.nr || n < 0) {
-		pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
-			   n, prog->section_name, prog->instances.nr);
-		return -EINVAL;
-	}
-
-	fd = ((int *)prog->instances.entries)[n];
-	if (fd < 0) {
-		pr_warning("%dth instance of program '%s' is invalid\n",
-			   n, prog->section_name);
-		return -ENOENT;
-	}
+	prog->engine->get_nth(prog, n, &fd);
 
 	return fd;
 }
-- 
1.8.5.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ