Commit 4e874b11 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'libbpf: stricter BPF program section name handling'

Andrii Nakryiko says:

====================

Implement opt-in stricter BPF program section name (SEC()) handling logic. For
a lot of supported ELF section names, enforce exact section name match with no
arbitrary characters added at the end. See patch #9 for more details.

To allow this, patches #2 through #4 clean up and preventively fix selftests,
normalizing existing SEC() usage across multiple selftests. While at it, those
patches also reduce the amount of remaining bpf_object__find_program_by_title()
uses, which should be completely removed soon, given it's an API with
ambiguous semantics and will be deprecated and eventually removed in libbpf 1.0.

Patch #1 also introduces SEC("tc") as an alias for SEC("classifier"). "tc" is
a better and less misleading name, so patch #3 replaces all classifier* uses
with nice and short SEC("tc").

Last patch is also fixing "sk_lookup/" definition to not require and not allow
extra "/blah" parts after it, which serve no meaning.

All the other patches are gradual internal libbpf changes to:
  - allow this optional strict logic for ELF section name handling;
  - allow new use case (for now for "struct_ops", but that could be extended
    to, say, freplace definitions), in which it can be used stand-alone to
    specify just type (SEC("struct_ops")), or also accept extra parameters
    which can be utilized by libbpf to either get more data or double-check
    valid use (e.g., SEC("struct_ops/dctcp_init") to specify desired
    struct_ops operation that is supposed to be implemented);
  - get libbpf's internal logic ready to allow other libraries and
    applications to specify their custom handlers for ELF section name for BPF
    programs. All the pieces are in place, the only thing preventing making
    this as public libbpf API is reliance on internal type for specifying BPF
    program load attributes. The work is planned to revamp related low-level
    libbpf APIs, at which point it will be possible to just re-use such new
    types for coordination between libbpf and custom handlers.

These changes are a part of libbpf 1.0 effort ([0]). They are also intended to
be applied on top of the previous preparatory series [1], so currently CI will
be failing to apply them to bpf-next until that patch set is landed. Once it
is landed, kernel-patches daemon will automatically retest this patch set.

  [0] https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0#stricter-and-more-uniform-bpf-program-section-name-sec-handling
  [1] https://patchwork.kernel.org/project/netdevbpf/list/?series=547675&state=*



v3->v4:
  - replace SEC("classifier*") with SEC("tc") (Daniel);
v2->v3:
  - applied acks, addressed most feedback, added comments to new flags (Dave);
v1->v2:
  - rebase onto latest bpf-next and resolve merge conflicts w/ Dave's changes.
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 29eef85b 7c80c87a
Loading
Loading
Loading
Loading
+260 −258

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Diff line number Diff line
@@ -89,6 +89,13 @@
	(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
#endif

/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is
 * a string literal known at compilation time or char * pointer known only at
 * runtime.
 */
#define str_has_pfx(str, pfx) \
	(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)

/* Symbol versioning is different between static and shared library.
 * Properly versioned symbols are needed for shared library, but
 * only the symbol of the new version is needed for static library.
+9 −0
Original line number Diff line number Diff line
@@ -46,6 +46,15 @@ enum libbpf_strict_mode {
	 */
	LIBBPF_STRICT_DIRECT_ERRS = 0x02,

	/*
	 * Enforce strict BPF program section (SEC()) names.
	 * E.g., while prefiously SEC("xdp_whatever") or SEC("perf_event_blah") were
	 * allowed, with LIBBPF_STRICT_SEC_PREFIX this will become
	 * unrecognized by libbpf and would have to be just SEC("xdp") and
	 * SEC("xdp") and SEC("perf_event").
	 */
	LIBBPF_STRICT_SEC_NAME = 0x04,

	__LIBBPF_STRICT_LAST,
};

+2 −2
Original line number Diff line number Diff line
@@ -458,9 +458,9 @@ static int init_prog_array(struct bpf_object *obj, struct bpf_map *prog_array)
		return -1;

	for (i = 0; i < bpf_map__def(prog_array)->max_entries; i++) {
		snprintf(prog_name, sizeof(prog_name), "flow_dissector/%i", i);
		snprintf(prog_name, sizeof(prog_name), "flow_dissector_%d", i);

		prog = bpf_object__find_program_by_title(obj, prog_name);
		prog = bpf_object__find_program_by_name(obj, prog_name);
		if (!prog)
			return -1;

+10 −13
Original line number Diff line number Diff line
@@ -2,14 +2,14 @@
#include <test_progs.h>

static void toggle_object_autoload_progs(const struct bpf_object *obj,
					 const char *title_load)
					 const char *name_load)
{
	struct bpf_program *prog;

	bpf_object__for_each_program(prog, obj) {
		const char *title = bpf_program__section_name(prog);
		const char *name = bpf_program__name(prog);

		if (!strcmp(title_load, title))
		if (!strcmp(name_load, name))
			bpf_program__set_autoload(prog, true);
		else
			bpf_program__set_autoload(prog, false);
@@ -39,23 +39,19 @@ void test_reference_tracking(void)
		goto cleanup;

	bpf_object__for_each_program(prog, obj_iter) {
		const char *title;
		const char *name;

		/* Ignore .text sections */
		title = bpf_program__section_name(prog);
		if (strstr(title, ".text") != NULL)
			continue;

		if (!test__start_subtest(title))
		name = bpf_program__name(prog);
		if (!test__start_subtest(name))
			continue;

		obj = bpf_object__open_file(file, &open_opts);
		if (!ASSERT_OK_PTR(obj, "obj_open_file"))
			goto cleanup;

		toggle_object_autoload_progs(obj, title);
		toggle_object_autoload_progs(obj, name);
		/* Expect verifier failure if test name has 'err' */
		if (strstr(title, "err_") != NULL) {
		if (strncmp(name, "err_", sizeof("err_") - 1) == 0) {
			libbpf_print_fn_t old_print_fn;

			old_print_fn = libbpf_set_print(NULL);
@@ -64,7 +60,8 @@ void test_reference_tracking(void)
		} else {
			err = bpf_object__load(obj);
		}
		CHECK(err, title, "\n");
		ASSERT_OK(err, name);

		bpf_object__close(obj);
		obj = NULL;
	}
Loading