Commit 92731504 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'CO-RE relocation selftests fixes'



Andrii Nakryiko says:

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

Lorenz Bauer noticed that core_reloc selftest has two inverted CHECK()
conditions, allowing failing tests to pass unnoticed. Fixing that opened up
few long-standing (field existence and direct memory bitfields) and one recent
failures (BTF_KIND_FLOAT relos).

This patch set fixes core_reloc selftest to capture such failures reliably in
the future. It also fixes all the newly failing tests. See individual patches
for details.

This patch set also completes a set of ASSERT_xxx() macros, so now there
should be a very little reason to use verbose and error-prone generic CHECK()
macro.

v1->v2:
  - updated bpf_core_fields_are_compat() comment to mention FLOAT (Lorenz).

Cc: Lorenz Bauer <lmb@cloudflare.com>
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 87bd9e60 bede0ebf
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -88,11 +88,19 @@ enum bpf_enum_value_kind {
	const void *p = (const void *)s + __CORE_RELO(s, field, BYTE_OFFSET); \
	unsigned long long val;						      \
									      \
	/* This is a so-called barrier_var() operation that makes specified   \
	 * variable "a black box" for optimizing compiler.		      \
	 * It forces compiler to perform BYTE_OFFSET relocation on p and use  \
	 * its calculated value in the switch below, instead of applying      \
	 * the same relocation 4 times for each individual memory load.       \
	 */								      \
	asm volatile("" : "=r"(p) : "0"(p));				      \
									      \
	switch (__CORE_RELO(s, field, BYTE_SIZE)) {			      \
	case 1: val = *(const unsigned char *)p;			      \
	case 2: val = *(const unsigned short *)p;			      \
	case 4: val = *(const unsigned int *)p;				      \
	case 8: val = *(const unsigned long long *)p;			      \
	case 1: val = *(const unsigned char *)p; break;			      \
	case 2: val = *(const unsigned short *)p; break;		      \
	case 4: val = *(const unsigned int *)p; break;			      \
	case 8: val = *(const unsigned long long *)p; break;		      \
	}								      \
	val <<= __CORE_RELO(s, field, LSHIFT_U64);			      \
	if (__CORE_RELO(s, field, SIGNED))				      \
+4 −2
Original line number Diff line number Diff line
@@ -5115,6 +5115,7 @@ bpf_core_find_cands(struct bpf_object *obj, const struct btf *local_btf, __u32 l
 *     least one of enums should be anonymous;
 *   - for ENUMs, check sizes, names are ignored;
 *   - for INT, size and signedness are ignored;
 *   - any two FLOATs are always compatible;
 *   - for ARRAY, dimensionality is ignored, element types are checked for
 *     compatibility recursively;
 *   - everything else shouldn't be ever a target of relocation.
@@ -5141,6 +5142,7 @@ static int bpf_core_fields_are_compat(const struct btf *local_btf,

	switch (btf_kind(local_type)) {
	case BTF_KIND_PTR:
	case BTF_KIND_FLOAT:
		return 1;
	case BTF_KIND_FWD:
	case BTF_KIND_ENUM: {
@@ -6245,8 +6247,8 @@ static int bpf_core_apply_relo(struct bpf_program *prog,
	/* bpf_core_patch_insn() should know how to handle missing targ_spec */
	err = bpf_core_patch_insn(prog, relo, relo_idx, &targ_res);
	if (err) {
		pr_warn("prog '%s': relo #%d: failed to patch insn at offset %d: %d\n",
			prog->name, relo_idx, relo->insn_off, err);
		pr_warn("prog '%s': relo #%d: failed to patch insn #%zu: %d\n",
			prog->name, relo_idx, relo->insn_off / BPF_INSN_SZ, err);
		return -EINVAL;
	}

+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static int test_btf_dump_case(int n, struct btf_dump_test_case *t)

	snprintf(out_file, sizeof(out_file), "/tmp/%s.output.XXXXXX", t->file);
	fd = mkstemp(out_file);
	if (CHECK(fd < 0, "create_tmp", "failed to create file: %d\n", fd)) {
	if (!ASSERT_GE(fd, 0, "create_tmp")) {
		err = fd;
		goto done;
	}
+1 −3
Original line number Diff line number Diff line
@@ -6,8 +6,6 @@
#include <test_progs.h>
#include <bpf/btf.h>

static int duration = 0;

void test_btf_endian() {
#if __BYTE_ORDER == __LITTLE_ENDIAN
	enum btf_endianness endian = BTF_LITTLE_ENDIAN;
@@ -71,7 +69,7 @@ void test_btf_endian() {

	/* now modify original BTF */
	var_id = btf__add_var(btf, "some_var", BTF_VAR_GLOBAL_ALLOCATED, 1);
	CHECK(var_id <= 0, "var_id", "failed %d\n", var_id);
	ASSERT_GT(var_id, 0, "var_id");

	btf__free(swap_btf);
	swap_btf = NULL;
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ void test_cgroup_link(void)

	for (i = 0; i < cg_nr; i++) {
		cgs[i].fd = create_and_get_cgroup(cgs[i].path);
		if (CHECK(cgs[i].fd < 0, "cg_create", "fail: %d\n", cgs[i].fd))
		if (!ASSERT_GE(cgs[i].fd, 0, "cg_create"))
			goto cleanup;
	}

Loading