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: <20200722054314.2103880-1-irogers@google.com>
Date:   Tue, 21 Jul 2020 22:43:14 -0700
From:   Ian Rogers <irogers@...gle.com>
To:     Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        Martin KaFai Lau <kafai@...com>,
        Song Liu <songliubraving@...com>, Yonghong Song <yhs@...com>,
        Andrii Nakryiko <andriin@...com>,
        John Fastabend <john.fastabend@...il.com>,
        KP Singh <kpsingh@...omium.org>,
        Quentin Monnet <quentin@...valent.com>,
        Jakub Kicinski <kuba@...nel.org>, Jiri Olsa <jolsa@...nel.org>,
        "Toke Høiland-Jørgensen" <toke@...hat.com>,
        netdev@...r.kernel.org, bpf@...r.kernel.org,
        linux-kernel@...r.kernel.org
Cc:     Stanislav Fomichev <sdf@...gle.com>,
        Ian Rogers <irogers@...gle.com>
Subject: [RFC PATCH] bpftool btf: Add prefix option to dump C

When bpftool dumps types and enum members into a header file for
inclusion the names match those in the original source. If the same
header file needs to be included in the original source and the bpf
program, the names of structs, unions, typedefs and enum members will
have naming collisions.

To avoid these collisions an approach is to redeclare the header file
types and enum members, which leads to duplication and possible
inconsistencies. Another approach is to use preprocessor macros
to rename conflicting names, but this can be cumbersome if there are
many conflicts.

This patch adds a prefix option for the dumped names. Use of this option
can avoid name conflicts and compile time errors.

Signed-off-by: Ian Rogers <irogers@...gle.com>
---
 .../bpf/bpftool/Documentation/bpftool-btf.rst |  7 ++++++-
 tools/bpf/bpftool/btf.c                       | 18 ++++++++++++++---
 tools/lib/bpf/btf.h                           |  1 +
 tools/lib/bpf/btf_dump.c                      | 20 +++++++++++++------
 4 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-btf.rst b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
index 896f4c6c2870..85d66bc69634 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-btf.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-btf.rst
@@ -20,7 +20,7 @@ BTF COMMANDS
 =============
 
 |	**bpftool** **btf** { **show** | **list** } [**id** *BTF_ID*]
-|	**bpftool** **btf dump** *BTF_SRC* [**format** *FORMAT*]
+|	**bpftool** **btf dump** *BTF_SRC* [**format** *FORMAT*] [**prefix** *PREFIX*]
 |	**bpftool** **btf help**
 |
 |	*BTF_SRC* := { **id** *BTF_ID* | **prog** *PROG* | **map** *MAP* [{**key** | **value** | **kv** | **all**}] | **file** *FILE* }
@@ -66,6 +66,11 @@ DESCRIPTION
 		  output format. Raw (**raw**) or C-syntax (**c**) output
 		  formats are supported.
 
+		  With the C-syntax format the **prefix** option can
+                  be used to prefix all identifiers and enum members
+                  with *PREFIX*. This is useful to avoid naming
+                  collisions.
+
 	**bpftool btf help**
 		  Print short help message.
 
diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
index fc9bc7a23db6..6a428636fa6f 100644
--- a/tools/bpf/bpftool/btf.c
+++ b/tools/bpf/bpftool/btf.c
@@ -379,12 +379,15 @@ static void __printf(2, 0) btf_dump_printf(void *ctx,
 }
 
 static int dump_btf_c(const struct btf *btf,
-		      __u32 *root_type_ids, int root_type_cnt)
+		      __u32 *root_type_ids, int root_type_cnt, const char *name_prefix)
 {
 	struct btf_dump *d;
 	int err = 0, i;
+	struct btf_dump_opts opts = {
+		.name_prefix = name_prefix,
+	};
 
-	d = btf_dump__new(btf, NULL, NULL, btf_dump_printf);
+	d = btf_dump__new(btf, NULL, &opts, btf_dump_printf);
 	if (IS_ERR(d))
 		return PTR_ERR(d);
 
@@ -478,6 +481,7 @@ static int do_dump(int argc, char **argv)
 	bool dump_c = false;
 	__u32 btf_id = -1;
 	const char *src;
+	const char *c_prefix = NULL;
 	int fd = -1;
 	int err;
 
@@ -583,6 +587,14 @@ static int do_dump(int argc, char **argv)
 				goto done;
 			}
 			NEXT_ARG();
+		} else if (is_prefix(*argv, "prefix")) {
+			NEXT_ARG();
+			if (argc < 1 || !*argv) {
+				p_err("expecting value for 'prefix' option\n");
+				goto done;
+			}
+			c_prefix = *argv;
+			NEXT_ARG();
 		} else {
 			p_err("unrecognized option: '%s'", *argv);
 			goto done;
@@ -608,7 +620,7 @@ static int do_dump(int argc, char **argv)
 			err = -ENOTSUP;
 			goto done;
 		}
-		err = dump_btf_c(btf, root_type_ids, root_type_cnt);
+		err = dump_btf_c(btf, root_type_ids, root_type_cnt, c_prefix);
 	} else {
 		err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
 	}
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 491c7b41ffdc..fea4baab00bd 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -117,6 +117,7 @@ struct btf_dump;
 
 struct btf_dump_opts {
 	void *ctx;
+	const char *name_prefix;
 };
 
 typedef void (*btf_dump_printf_fn_t)(void *ctx, const char *fmt, va_list args);
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index e1c344504cae..baf2b4d82e1e 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -138,6 +138,7 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
 	d->btf_ext = btf_ext;
 	d->printf_fn = printf_fn;
 	d->opts.ctx = opts ? opts->ctx : NULL;
+	d->opts.name_prefix = opts ? opts->name_prefix : NULL;
 
 	d->type_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
 	if (IS_ERR(d->type_names)) {
@@ -903,6 +904,7 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
 	const struct btf_enum *v = btf_enum(t);
 	__u16 vlen = btf_vlen(t);
 	const char *name;
+	const char *name_prefix = d->opts.name_prefix;
 	size_t dup_cnt;
 	int i;
 
@@ -912,17 +914,19 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
 
 	if (vlen) {
 		btf_dump_printf(d, " {");
+		if (!name_prefix)
+			name_prefix = "";
 		for (i = 0; i < vlen; i++, v++) {
 			name = btf_name_of(d, v->name_off);
 			/* enumerators share namespace with typedef idents */
 			dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
 			if (dup_cnt > 1) {
-				btf_dump_printf(d, "\n%s%s___%zu = %u,",
-						pfx(lvl + 1), name, dup_cnt,
+				btf_dump_printf(d, "\n%s%s%s___%zu = %u,",
+						pfx(lvl + 1), name_prefix, name, dup_cnt,
 						(__u32)v->val);
 			} else {
-				btf_dump_printf(d, "\n%s%s = %u,",
-						pfx(lvl + 1), name,
+				btf_dump_printf(d, "\n%s%s%s = %u,",
+						pfx(lvl + 1), name_prefix, name,
 						(__u32)v->val);
 			}
 		}
@@ -1360,6 +1364,7 @@ static const char *btf_dump_resolve_name(struct btf_dump *d, __u32 id,
 	const struct btf_type *t = btf__type_by_id(d->btf, id);
 	const char *orig_name = btf_name_of(d, t->name_off);
 	const char **cached_name = &d->cached_names[id];
+	const char *prefix = d->opts.name_prefix;
 	size_t dup_cnt;
 
 	if (t->name_off == 0)
@@ -1369,11 +1374,14 @@ static const char *btf_dump_resolve_name(struct btf_dump *d, __u32 id,
 		return *cached_name ? *cached_name : orig_name;
 
 	dup_cnt = btf_dump_name_dups(d, name_map, orig_name);
-	if (dup_cnt > 1) {
+	if (dup_cnt > 1 || prefix) {
 		const size_t max_len = 256;
 		char new_name[max_len];
 
-		snprintf(new_name, max_len, "%s___%zu", orig_name, dup_cnt);
+		if (dup_cnt > 1)
+			snprintf(new_name, max_len, "%s%s___%zu", prefix, orig_name, dup_cnt);
+		else
+			snprintf(new_name, max_len, "%s%s", prefix, orig_name);
 		*cached_name = strdup(new_name);
 	}
 
-- 
2.28.0.rc0.105.gf9edc3c819-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ