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-next>] [day] [month] [year] [list]
Message-Id: <1529225321-15429-1-git-send-email-ophirmu@mellanox.com>
Date:   Sun, 17 Jun 2018 08:48:41 +0000
From:   Ophir Munk <ophirmu@...lanox.com>
To:     netdev@...r.kernel.org,
        Stephen Hemminger <stephen@...workplumber.org>,
        David Ahern <dsahern@...il.com>
Cc:     Thomas Monjalon <thomas@...jalon.net>,
        Olga Shern <olgas@...lanox.com>,
        Ophir Munk <ophirmu@...lanox.com>
Subject: [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment

Similar to cbpf used within tcpdump utility with a "-d" option to dump
the compiled packet-matching code in a human readable form - tc has the
"verbose" option to dump ebpf verifier output.
Another useful option of cbpf using tcpdump "-dd" option is to dump
packet-matching code a C program fragment. Similar to this - this commit
adds a new tc ebpf option named "code" to dump ebpf verifier as C program
fragment.

Existing "verbose" option sample output:

Verifier analysis:
0: (61) r2 = *(u32 *)(r1 +52)
1: (18) r3 = 0xdeadbeef
3: (63) *(u32 *)(r10 -4) = r3
.
.
11: (63) *(u32 *)(r1 +52) = r2
12: (18) r0 = 0xffffffff
14: (95) exit

New "code" option sample output:

/* struct bpf_insn cls_q_code[] = { */
{0x61,    2,    1,       52, 0x00000000},
{0x18,    3,    0,        0, 0xdeadbeef},
{0x00,    0,    0,        0, 0x00000000},
.
.
{0x63,    1,    2,       52, 0x00000000},
{0x18,    0,    0,        0, 0xffffffff},
{0x00,    0,    0,        0, 0x00000000},
{0x95,    0,    0,        0, 0x00000000},

Signed-off-by: Ophir Munk <ophirmu@...lanox.com>
---
 include/bpf_util.h |  1 +
 lib/bpf.c          | 35 +++++++++++++++++++++++++++++------
 tc/m_bpf.c         |  3 ++-
 3 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/include/bpf_util.h b/include/bpf_util.h
index 219beb4..cf611c5 100644
--- a/include/bpf_util.h
+++ b/include/bpf_util.h
@@ -72,6 +72,7 @@ struct bpf_cfg_in {
 	enum bpf_mode mode;
 	__u32 ifindex;
 	bool verbose;
+	bool code;	
 	int argc;
 	char **argv;
 	struct sock_filter opcodes[BPF_MAXINSNS];
diff --git a/lib/bpf.c b/lib/bpf.c
index c38d92d..b13ec3f 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -113,10 +113,10 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type)
 
 #ifdef HAVE_ELF
 static int bpf_obj_open(const char *path, enum bpf_prog_type type,
-			const char *sec, __u32 ifindex, bool verbose);
+			const char *sec, __u32 ifindex, bool verbose, bool code);
 #else
 static int bpf_obj_open(const char *path, enum bpf_prog_type type,
-			const char *sec, __u32 ifindex, bool verbose)
+			const char *sec, __u32 ifindex, bool verbose, bool code)
 {
 	fprintf(stderr, "No ELF library support compiled in.\n");
 	errno = ENOSYS;
@@ -809,6 +809,7 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 {
 	const char *file, *section, *uds_name;
 	bool verbose = false;
+	bool code = false;	
 	int i, ret, argc;
 	char **argv;
 
@@ -890,6 +891,11 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 			NEXT_ARG_FWD();
 		}
 
+		if (argc > 0 && matches(*argv, "code") == 0) {
+			code = true;
+			NEXT_ARG_FWD();
+		}
+
 		PREV_ARG();
 	}
 
@@ -911,6 +917,7 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 	cfg->uds     = uds_name;
 	cfg->argc    = argc;
 	cfg->argv    = argv;
+	cfg->code    = code;
 	cfg->verbose = verbose;
 
 	return ret;
@@ -921,7 +928,7 @@ static int bpf_do_load(struct bpf_cfg_in *cfg)
 	if (cfg->mode == EBPF_OBJECT) {
 		cfg->prog_fd = bpf_obj_open(cfg->object, cfg->type,
 					    cfg->section, cfg->ifindex,
-					    cfg->verbose);
+					    cfg->verbose, cfg->code);
 		return cfg->prog_fd;
 	}
 	return 0;
@@ -1133,6 +1140,7 @@ struct bpf_elf_ctx {
 	enum bpf_prog_type	type;
 	__u32			ifindex;
 	bool			verbose;
+	bool			code;
 	struct bpf_elf_st	stat;
 	struct bpf_hash_entry	*ht[256];
 	char			*log;
@@ -1179,6 +1187,17 @@ bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...)
 	}
 }
 
+static void bpf_dump_code(const char *section, const struct bpf_insn *insns, unsigned int cnt)
+{
+	int i;
+	fprintf(stderr, "/* struct bpf_insn %s_code[] = { */\n", section);
+	for (i=0; i < cnt; i++) {
+		fprintf(stderr, "\t{0x%.2x, %4u, %4u, %8d, 0x%.8x},\n",
+		insns[i].code, insns[i].dst_reg, insns[i].src_reg, insns[i].off, insns[i].imm);
+	}
+	fprintf(stderr, "\n");
+}
+
 static int bpf_log_realloc(struct bpf_elf_ctx *ctx)
 {
 	const size_t log_max = UINT_MAX >> 8;
@@ -1526,6 +1545,9 @@ retry:
 		bpf_prog_report(fd, section, prog, ctx);
 	}
 
+	if (ctx->code)
+		bpf_dump_code(section, prog->insns, prog->size / sizeof(struct bpf_insn));
+
 	return fd;
 }
 
@@ -2439,7 +2461,7 @@ static void bpf_get_cfg(struct bpf_elf_ctx *ctx)
 
 static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
 			    enum bpf_prog_type type, __u32 ifindex,
-			    bool verbose)
+			    bool verbose, bool code)
 {
 	int ret = -EINVAL;
 
@@ -2450,6 +2472,7 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
 	memset(ctx, 0, sizeof(*ctx));
 	bpf_get_cfg(ctx);
 	ctx->verbose = verbose;
+	ctx->code    = code;
 	ctx->type    = type;
 	ctx->ifindex = ifindex;
 
@@ -2543,12 +2566,12 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
 static struct bpf_elf_ctx __ctx;
 
 static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
-			const char *section, __u32 ifindex, bool verbose)
+			const char *section, __u32 ifindex, bool verbose, bool code)
 {
 	struct bpf_elf_ctx *ctx = &__ctx;
 	int fd = 0, ret;
 
-	ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose);
+	ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose, code);
 	if (ret < 0) {
 		fprintf(stderr, "Cannot initialize ELF context!\n");
 		return ret;
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
index 1c1f71c..9947113 100644
--- a/tc/m_bpf.c
+++ b/tc/m_bpf.c
@@ -33,7 +33,8 @@ static void explain(void)
 	fprintf(stderr, "\n");
 	fprintf(stderr, "eBPF use case:\n");
 	fprintf(stderr, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
-	fprintf(stderr, " [ verbose ]\n");
+	fprintf(stderr, " [ verbose ]");
+	fprintf(stderr, " [ code ]\n");
 	fprintf(stderr, " object-pinned FILE\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
-- 
1.8.3.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ