bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test
@ 2020-03-13  7:54 Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 1/4] selftests/bpf: ensure consistent test failure output Andrii Nakryiko
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13  7:54 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

This patch set fixes bug in CO-RE relocation candidate finding logic, which
currently allows matching against forward declarations, functions, and other
named types, even though it makes no sense to even attempt. As part of
verifying the fix, add test using vmlinux.h with preserve_access_index
attribute and utilizing struct pt_regs heavily to trace nanosleep syscall
using 5 different types of tracing BPF programs.

This test also demonstrated problems using struct pt_regs in syscall
tracepoints and required a new set of macro, which were added in patch #3 into
bpf_tracing.h.

Patch #1 fixes annoying issue with selftest failure messages being out of
sync.

Andrii Nakryiko (4):
  selftests/bpf: ensure consistent test failure output
  libbpf: ignore incompatible types with matching name during CO-RE
    relocation
  libbpf: provide CO-RE variants of PT_REGS macros
  selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls

 tools/lib/bpf/bpf_tracing.h                   | 103 ++++++++++++++++++
 tools/lib/bpf/libbpf.c                        |   4 +
 tools/testing/selftests/bpf/Makefile          |   7 +-
 .../selftests/bpf/prog_tests/vmlinux.c        |  43 ++++++++
 .../selftests/bpf/progs/test_vmlinux.c        |  98 +++++++++++++++++
 tools/testing/selftests/bpf/test_progs.c      |  10 +-
 tools/testing/selftests/bpf/test_progs.h      |   8 +-
 7 files changed, 263 insertions(+), 10 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/vmlinux.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_vmlinux.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 1/4] selftests/bpf: ensure consistent test failure output
  2020-03-13  7:54 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
@ 2020-03-13  7:54 ` Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation Andrii Nakryiko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13  7:54 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

printf() doesn't seem to honor using overwritten stdout/stderr (as part of
stdio hijacking), so ensure all "standard" invocations of printf() do
fprintf(stdout, ...) instead.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/testing/selftests/bpf/test_progs.c | 10 +++++-----
 tools/testing/selftests/bpf/test_progs.h |  8 ++++----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index b6201dd82edf..f85a06512541 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -216,7 +216,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
 
 	map = bpf_object__find_map_by_name(obj, name);
 	if (!map) {
-		printf("%s:FAIL:map '%s' not found\n", test, name);
+		fprintf(stdout, "%s:FAIL:map '%s' not found\n", test, name);
 		test__fail();
 		return -1;
 	}
@@ -387,7 +387,7 @@ static int libbpf_print_fn(enum libbpf_print_level level,
 {
 	if (env.verbosity < VERBOSE_VERY && level == LIBBPF_DEBUG)
 		return 0;
-	vprintf(format, args);
+	vfprintf(stdout, format, args);
 	return 0;
 }
 
@@ -633,7 +633,7 @@ int cd_flavor_subdir(const char *exec_name)
 	if (!flavor)
 		return 0;
 	flavor++;
-	printf("Switching to flavor '%s' subdirectory...\n", flavor);
+	fprintf(stdout, "Switching to flavor '%s' subdirectory...\n", flavor);
 	return chdir(flavor);
 }
 
@@ -716,8 +716,8 @@ int main(int argc, char **argv)
 			cleanup_cgroup_environment();
 	}
 	stdio_restore();
-	printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
-	       env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
+	fprintf(stdout, "Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
+		env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
 
 	free(env.test_selector.blacklist.strs);
 	free(env.test_selector.whitelist.strs);
diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h
index bcfa9ef23fda..fd85fa61dbf7 100644
--- a/tools/testing/selftests/bpf/test_progs.h
+++ b/tools/testing/selftests/bpf/test_progs.h
@@ -109,10 +109,10 @@ extern struct ipv6_packet pkt_v6;
 	int __save_errno = errno;					\
 	if (__ret) {							\
 		test__fail();						\
-		printf("%s:FAIL:%s ", __func__, tag);			\
-		printf(format);						\
+		fprintf(stdout, "%s:FAIL:%s ", __func__, tag);		\
+		fprintf(stdout, ##format);				\
 	} else {							\
-		printf("%s:PASS:%s %d nsec\n",				\
+		fprintf(stdout, "%s:PASS:%s %d nsec\n",			\
 		       __func__, tag, duration);			\
 	}								\
 	errno = __save_errno;						\
@@ -124,7 +124,7 @@ extern struct ipv6_packet pkt_v6;
 	int __save_errno = errno;					\
 	if (__ret) {							\
 		test__fail();						\
-		printf("%s:FAIL:%d\n", __func__, __LINE__);		\
+		fprintf(stdout, "%s:FAIL:%d\n", __func__, __LINE__);	\
 	}								\
 	errno = __save_errno;						\
 	__ret;								\
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation
  2020-03-13  7:54 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 1/4] selftests/bpf: ensure consistent test failure output Andrii Nakryiko
@ 2020-03-13  7:54 ` Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 3/4] libbpf: provide CO-RE variants of PT_REGS macros Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls Andrii Nakryiko
  3 siblings, 0 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13  7:54 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

When finding target type candidates, ignore forward declarations, functions,
and other named types of incompatible kind. Not doing this can cause false
errors.  See [0] for one such case (due to struct pt_regs forward
declaration).

  [0] https://github.com/iovisor/bcc/pull/2806#issuecomment-598543645

Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm")
Reported-by: Wenbo Zhang <ethercflow@gmail.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/lib/bpf/libbpf.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1a787a2faf58..085e41f9b68e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3873,6 +3873,10 @@ static struct ids_vec *bpf_core_find_cands(const struct btf *local_btf,
 		if (str_is_empty(targ_name))
 			continue;
 
+		t = skip_mods_and_typedefs(targ_btf, i, NULL);
+		if (!btf_is_composite(t) && !btf_is_array(t))
+			continue;
+
 		targ_essent_len = bpf_core_essential_name_len(targ_name);
 		if (targ_essent_len != local_essent_len)
 			continue;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 3/4] libbpf: provide CO-RE variants of PT_REGS macros
  2020-03-13  7:54 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 1/4] selftests/bpf: ensure consistent test failure output Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation Andrii Nakryiko
@ 2020-03-13  7:54 ` Andrii Nakryiko
  2020-03-13  7:54 ` [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls Andrii Nakryiko
  3 siblings, 0 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13  7:54 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

Syscall raw tracepoints have struct pt_regs pointer as tracepoint's first
argument. After that, reading any of pt_regs fields requires bpf_probe_read(),
even for tp_btf programs. Due to that, PT_REGS_PARMx macros are not usable as
is. This patch adds CO-RE variants of those macros that use BPF_CORE_READ() to
read necessary fields. This provides relocatable architecture-agnostic pt_regs
field accesses.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/lib/bpf/bpf_tracing.h | 103 ++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h
index 379d03b211ea..b0c9ae5c73b5 100644
--- a/tools/lib/bpf/bpf_tracing.h
+++ b/tools/lib/bpf/bpf_tracing.h
@@ -50,6 +50,7 @@
 #if defined(bpf_target_x86)
 
 #if defined(__KERNEL__) || defined(__VMLINUX_H__)
+
 #define PT_REGS_PARM1(x) ((x)->di)
 #define PT_REGS_PARM2(x) ((x)->si)
 #define PT_REGS_PARM3(x) ((x)->dx)
@@ -60,7 +61,20 @@
 #define PT_REGS_RC(x) ((x)->ax)
 #define PT_REGS_SP(x) ((x)->sp)
 #define PT_REGS_IP(x) ((x)->ip)
+
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), di)
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), si)
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), dx)
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), cx)
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), sp)
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), bp)
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), ax)
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), ip)
+
 #else
+
 #ifdef __i386__
 /* i386 kernel is built with -mregparm=3 */
 #define PT_REGS_PARM1(x) ((x)->eax)
@@ -73,7 +87,20 @@
 #define PT_REGS_RC(x) ((x)->eax)
 #define PT_REGS_SP(x) ((x)->esp)
 #define PT_REGS_IP(x) ((x)->eip)
+
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), eax)
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), edx)
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), ecx)
+#define PT_REGS_PARM4_CORE(x) 0
+#define PT_REGS_PARM5_CORE(x) 0
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), esp)
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), ebp)
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), eax)
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), esp)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), eip)
+
 #else
+
 #define PT_REGS_PARM1(x) ((x)->rdi)
 #define PT_REGS_PARM2(x) ((x)->rsi)
 #define PT_REGS_PARM3(x) ((x)->rdx)
@@ -84,6 +111,18 @@
 #define PT_REGS_RC(x) ((x)->rax)
 #define PT_REGS_SP(x) ((x)->rsp)
 #define PT_REGS_IP(x) ((x)->rip)
+
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), rdi)
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), rsi)
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), rdx)
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), rcx)
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), r8)
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), rsp)
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), rbp)
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), rax)
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), rsp)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), rip)
+
 #endif
 #endif
 
@@ -104,6 +143,17 @@ struct pt_regs;
 #define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15])
 #define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr)
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[3])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[4])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[5])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[6])
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), grps[14])
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[11])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[2])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), gprs[15])
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_S390 *)(x), pdw.addr)
+
 #elif defined(bpf_target_arm)
 
 #define PT_REGS_PARM1(x) ((x)->uregs[0])
@@ -117,6 +167,17 @@ struct pt_regs;
 #define PT_REGS_SP(x) ((x)->uregs[13])
 #define PT_REGS_IP(x) ((x)->uregs[12])
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), uregs[0])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), uregs[1])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), uregs[2])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), uregs[3])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), uregs[4])
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), uregs[14])
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), uregs[11])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), uregs[0])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), uregs[13])
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), uregs[12])
+
 #elif defined(bpf_target_arm64)
 
 /* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
@@ -134,6 +195,17 @@ struct pt_regs;
 #define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp)
 #define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc)
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[1])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[2])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[3])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[4])
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[30])
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[29])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), regs[0])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), sp)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_ARM64 *)(x), pc)
+
 #elif defined(bpf_target_mips)
 
 #define PT_REGS_PARM1(x) ((x)->regs[4])
@@ -147,6 +219,17 @@ struct pt_regs;
 #define PT_REGS_SP(x) ((x)->regs[29])
 #define PT_REGS_IP(x) ((x)->cp0_epc)
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), regs[4])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), regs[5])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), regs[6])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), regs[7])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), regs[8])
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), regs[31])
+#define PT_REGS_FP_CORE(x) BPF_CORE_READ((x), regs[30])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), regs[1])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), regs[29])
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), cp0_epc)
+
 #elif defined(bpf_target_powerpc)
 
 #define PT_REGS_PARM1(x) ((x)->gpr[3])
@@ -158,6 +241,15 @@ struct pt_regs;
 #define PT_REGS_SP(x) ((x)->sp)
 #define PT_REGS_IP(x) ((x)->nip)
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), gpr[3])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), gpr[4])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), gpr[5])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), gpr[6])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), gpr[7])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), gpr[3])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), sp)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), nip)
+
 #elif defined(bpf_target_sparc)
 
 #define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0])
@@ -169,11 +261,22 @@ struct pt_regs;
 #define PT_REGS_RC(x) ((x)->u_regs[UREG_I0])
 #define PT_REGS_SP(x) ((x)->u_regs[UREG_FP])
 
+#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
+#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I1])
+#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I2])
+#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I3])
+#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I4])
+#define PT_REGS_RET_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I7])
+#define PT_REGS_RC_CORE(x) BPF_CORE_READ((x), u_regs[UREG_I0])
+#define PT_REGS_SP_CORE(x) BPF_CORE_READ((x), u_regs[UREG_FP])
+
 /* Should this also be a bpf_target check for the sparc case? */
 #if defined(__arch64__)
 #define PT_REGS_IP(x) ((x)->tpc)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), tpc)
 #else
 #define PT_REGS_IP(x) ((x)->pc)
+#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
 #endif
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls
  2020-03-13  7:54 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
                   ` (2 preceding siblings ...)
  2020-03-13  7:54 ` [PATCH bpf-next 3/4] libbpf: provide CO-RE variants of PT_REGS macros Andrii Nakryiko
@ 2020-03-13  7:54 ` Andrii Nakryiko
  2020-03-13 17:02   ` [Potential Spoof] " Martin KaFai Lau
  3 siblings, 1 reply; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13  7:54 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

Add vmlinux.h generation to selftest/bpf's Makefile. Use it from newly added
test_vmlinux to trace nanosleep syscall using 5 different types of programs:
  - tracepoint;
  - raw tracepoint;
  - raw tracepoint w/ direct memory reads (tp_btf);
  - kprobe;
  - fentry.

These programs are realistic variants of real-life tracing programs,
excercising vmlinux.h's usage with tracing applications.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/testing/selftests/bpf/Makefile          |  7 +-
 .../selftests/bpf/prog_tests/vmlinux.c        | 43 ++++++++
 .../selftests/bpf/progs/test_vmlinux.c        | 98 +++++++++++++++++++
 3 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/vmlinux.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_vmlinux.c

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index da4389dde9f7..3bbda8eb57aa 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -135,7 +135,7 @@ VMLINUX_BTF_PATHS := $(if $(O),$(O)/vmlinux)				\
 		     ../../../../vmlinux				\
 		     /sys/kernel/btf/vmlinux				\
 		     /boot/vmlinux-$(shell uname -r)
-VMLINUX_BTF:= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
+VMLINUX_BTF := $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
 
 $(OUTPUT)/runqslower: $(BPFOBJ)
 	$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower	\
@@ -176,6 +176,10 @@ $(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(INCLUDE_DIR):
 	$(call msg,MKDIR,,$@)
 	mkdir -p $@
 
+$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) | $(BPFTOOL) $(INCLUDE_DIR)
+	$(call msg,GEN,,$@)
+	$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
+
 # Get Clang's default includes on this system, as opposed to those seen by
 # '-target bpf'. This fixes "missing" files on some architectures/distros,
 # such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
@@ -284,6 +288,7 @@ $(TRUNNER_BPF_PROGS_DIR)$(if $2,-)$2-bpfobjs := y
 $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.o:				\
 		     $(TRUNNER_BPF_PROGS_DIR)/%.c			\
 		     $(TRUNNER_BPF_PROGS_DIR)/*.h			\
+		     $$(INCLUDE_DIR)/vmlinux.h				\
 		     $$(BPFOBJ) | $(TRUNNER_OUTPUT)
 	$$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@,			\
 					  $(TRUNNER_BPF_CFLAGS),	\
diff --git a/tools/testing/selftests/bpf/prog_tests/vmlinux.c b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
new file mode 100644
index 000000000000..04939eda1325
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Facebook */
+
+#include <test_progs.h>
+#include <time.h>
+#include "test_vmlinux.skel.h"
+
+#define MY_TV_NSEC 1337
+
+static void nsleep()
+{
+	struct timespec ts = { .tv_nsec = MY_TV_NSEC };
+
+	(void)nanosleep(&ts, NULL);
+}
+
+void test_vmlinux(void)
+{
+	int duration = 0, err;
+	struct test_vmlinux* skel;
+	struct test_vmlinux__bss *bss;
+
+	skel = test_vmlinux__open_and_load();
+	if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
+		return;
+	bss = skel->bss;
+
+	err = test_vmlinux__attach(skel);
+	if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
+		goto cleanup;
+
+	/* trigger everything */
+	nsleep();
+
+	CHECK(!bss->tp_called, "tp", "not called\n");
+	CHECK(!bss->raw_tp_called, "raw_tp", "not called\n");
+	CHECK(!bss->tp_btf_called, "tp_btf", "not called\n");
+	CHECK(!bss->kprobe_called, "kprobe", "not called\n");
+	CHECK(!bss->fentry_called, "fentry", "not called\n");
+
+cleanup:
+	test_vmlinux__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_vmlinux.c b/tools/testing/selftests/bpf/progs/test_vmlinux.c
new file mode 100644
index 000000000000..5cc2bf8011b0
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_vmlinux.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2020 Facebook */
+
+#include "vmlinux.h"
+#include <asm/unistd.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+
+#define MY_TV_NSEC 1337
+
+bool tp_called = false;
+bool raw_tp_called = false;
+bool tp_btf_called = false;
+bool kprobe_called = false;
+bool fentry_called = false;
+
+SEC("tp/syscalls/sys_enter_nanosleep")
+int handle__tp(struct trace_event_raw_sys_enter *args)
+{
+	struct __kernel_timespec *ts;
+
+	if (args->id != __NR_nanosleep)
+		return 0;
+
+	ts = (void *)args->args[0];
+	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
+		return 0;
+
+	tp_called = true;
+	return 0;
+}
+
+static bool __always_inline handle_probed(struct pt_regs *regs, long id)
+{
+	struct __kernel_timespec *ts;
+
+	if (id != __NR_nanosleep)
+		return false;
+
+	ts = (void *)PT_REGS_PARM1_CORE(regs);
+	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
+		return false;
+
+	return true;
+}
+
+SEC("raw_tp/sys_enter")
+int BPF_PROG(handle__raw_tp, struct pt_regs *regs, long id)
+{
+	struct __kernel_timespec *ts;
+
+	if (id != __NR_nanosleep)
+		return 0;
+
+	ts = (void *)PT_REGS_PARM1_CORE(regs);
+	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
+		return 0;
+
+	raw_tp_called = true;
+	return 0;
+}
+
+SEC("tp_btf/sys_enter")
+int BPF_PROG(handle__tp_btf, struct pt_regs *regs, long id)
+{
+	struct __kernel_timespec *ts;
+
+	if (id != __NR_nanosleep)
+		return 0;
+
+	ts = (void *)PT_REGS_PARM1_CORE(regs);
+	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
+		return 0;
+
+	tp_btf_called = true;
+	return 0;
+}
+
+SEC("kprobe/hrtimer_nanosleep")
+int BPF_KPROBE(handle__kprobe,
+	       ktime_t rqtp, enum hrtimer_mode mode, clockid_t clockid)
+{
+	if (rqtp == MY_TV_NSEC)
+		kprobe_called = true;
+	return 0;
+}
+
+SEC("fentry/hrtimer_nanosleep")
+int BPF_PROG(handle__fentry,
+	       ktime_t rqtp, enum hrtimer_mode mode, clockid_t clockid)
+{
+	if (rqtp == MY_TV_NSEC)
+		fentry_called = true;
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [Potential Spoof] [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls
  2020-03-13  7:54 ` [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls Andrii Nakryiko
@ 2020-03-13 17:02   ` Martin KaFai Lau
  2020-03-13 17:16     ` Andrii Nakryiko
  0 siblings, 1 reply; 8+ messages in thread
From: Martin KaFai Lau @ 2020-03-13 17:02 UTC (permalink / raw)
  To: Andrii Nakryiko; +Cc: bpf, netdev, ast, daniel, andrii.nakryiko, kernel-team

On Fri, Mar 13, 2020 at 12:54:41AM -0700, Andrii Nakryiko wrote:
> Add vmlinux.h generation to selftest/bpf's Makefile. Use it from newly added
> test_vmlinux to trace nanosleep syscall using 5 different types of programs:
>   - tracepoint;
>   - raw tracepoint;
>   - raw tracepoint w/ direct memory reads (tp_btf);
>   - kprobe;
>   - fentry.
> 
> These programs are realistic variants of real-life tracing programs,
> excercising vmlinux.h's usage with tracing applications.
> 
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
[ ... ]

> diff --git a/tools/testing/selftests/bpf/prog_tests/vmlinux.c b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
> new file mode 100644
> index 000000000000..04939eda1325
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
> @@ -0,0 +1,43 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2020 Facebook */
> +
> +#include <test_progs.h>
> +#include <time.h>
> +#include "test_vmlinux.skel.h"
> +
> +#define MY_TV_NSEC 1337
> +
> +static void nsleep()
> +{
> +	struct timespec ts = { .tv_nsec = MY_TV_NSEC };
> +
> +	(void)nanosleep(&ts, NULL);
> +}
> +
> +void test_vmlinux(void)
> +{
> +	int duration = 0, err;
> +	struct test_vmlinux* skel;
> +	struct test_vmlinux__bss *bss;
> +
> +	skel = test_vmlinux__open_and_load();
> +	if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
> +		return;
> +	bss = skel->bss;
> +
> +	err = test_vmlinux__attach(skel);
> +	if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
> +		goto cleanup;
> +
> +	/* trigger everything */
> +	nsleep();
> +
> +	CHECK(!bss->tp_called, "tp", "not called\n");
> +	CHECK(!bss->raw_tp_called, "raw_tp", "not called\n");
> +	CHECK(!bss->tp_btf_called, "tp_btf", "not called\n");
> +	CHECK(!bss->kprobe_called, "kprobe", "not called\n");
> +	CHECK(!bss->fentry_called, "fentry", "not called\n");
> +
> +cleanup:
> +	test_vmlinux__destroy(skel);
> +}
> diff --git a/tools/testing/selftests/bpf/progs/test_vmlinux.c b/tools/testing/selftests/bpf/progs/test_vmlinux.c
> new file mode 100644
> index 000000000000..5cc2bf8011b0
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/test_vmlinux.c
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2020 Facebook */
> +
> +#include "vmlinux.h"
> +#include <asm/unistd.h>
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +#include <bpf/bpf_core_read.h>
> +
> +#define MY_TV_NSEC 1337
> +
> +bool tp_called = false;
> +bool raw_tp_called = false;
> +bool tp_btf_called = false;
> +bool kprobe_called = false;
> +bool fentry_called = false;
> +
> +SEC("tp/syscalls/sys_enter_nanosleep")
> +int handle__tp(struct trace_event_raw_sys_enter *args)
> +{
> +	struct __kernel_timespec *ts;
> +
> +	if (args->id != __NR_nanosleep)
> +		return 0;
> +
> +	ts = (void *)args->args[0];
> +	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
> +		return 0;
> +
> +	tp_called = true;
> +	return 0;
> +}
> +
> +static bool __always_inline handle_probed(struct pt_regs *regs, long id)
It is not used, may be removing it?

> +{
> +	struct __kernel_timespec *ts;
> +
> +	if (id != __NR_nanosleep)
> +		return false;
> +
> +	ts = (void *)PT_REGS_PARM1_CORE(regs);
> +	if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
> +		return false;
> +
> +	return true;
> +}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Potential Spoof] [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls
  2020-03-13 17:02   ` [Potential Spoof] " Martin KaFai Lau
@ 2020-03-13 17:16     ` Andrii Nakryiko
  0 siblings, 0 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13 17:16 UTC (permalink / raw)
  To: Martin KaFai Lau
  Cc: Andrii Nakryiko, bpf, Networking, Alexei Starovoitov,
	Daniel Borkmann, Kernel Team

On Fri, Mar 13, 2020 at 10:02 AM Martin KaFai Lau <kafai@fb.com> wrote:
>
> On Fri, Mar 13, 2020 at 12:54:41AM -0700, Andrii Nakryiko wrote:
> > Add vmlinux.h generation to selftest/bpf's Makefile. Use it from newly added
> > test_vmlinux to trace nanosleep syscall using 5 different types of programs:
> >   - tracepoint;
> >   - raw tracepoint;
> >   - raw tracepoint w/ direct memory reads (tp_btf);
> >   - kprobe;
> >   - fentry.
> >
> > These programs are realistic variants of real-life tracing programs,
> > excercising vmlinux.h's usage with tracing applications.
> >
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
> [ ... ]
>
> > diff --git a/tools/testing/selftests/bpf/prog_tests/vmlinux.c b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
> > new file mode 100644
> > index 000000000000..04939eda1325
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/prog_tests/vmlinux.c
> > @@ -0,0 +1,43 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (c) 2020 Facebook */
> > +
> > +#include <test_progs.h>
> > +#include <time.h>
> > +#include "test_vmlinux.skel.h"
> > +
> > +#define MY_TV_NSEC 1337
> > +
> > +static void nsleep()
> > +{
> > +     struct timespec ts = { .tv_nsec = MY_TV_NSEC };
> > +
> > +     (void)nanosleep(&ts, NULL);
> > +}
> > +
> > +void test_vmlinux(void)
> > +{
> > +     int duration = 0, err;
> > +     struct test_vmlinux* skel;
> > +     struct test_vmlinux__bss *bss;
> > +
> > +     skel = test_vmlinux__open_and_load();
> > +     if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
> > +             return;
> > +     bss = skel->bss;
> > +
> > +     err = test_vmlinux__attach(skel);
> > +     if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
> > +             goto cleanup;
> > +
> > +     /* trigger everything */
> > +     nsleep();
> > +
> > +     CHECK(!bss->tp_called, "tp", "not called\n");
> > +     CHECK(!bss->raw_tp_called, "raw_tp", "not called\n");
> > +     CHECK(!bss->tp_btf_called, "tp_btf", "not called\n");
> > +     CHECK(!bss->kprobe_called, "kprobe", "not called\n");
> > +     CHECK(!bss->fentry_called, "fentry", "not called\n");
> > +
> > +cleanup:
> > +     test_vmlinux__destroy(skel);
> > +}
> > diff --git a/tools/testing/selftests/bpf/progs/test_vmlinux.c b/tools/testing/selftests/bpf/progs/test_vmlinux.c
> > new file mode 100644
> > index 000000000000..5cc2bf8011b0
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/progs/test_vmlinux.c
> > @@ -0,0 +1,98 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (c) 2020 Facebook */
> > +
> > +#include "vmlinux.h"
> > +#include <asm/unistd.h>
> > +#include <bpf/bpf_helpers.h>
> > +#include <bpf/bpf_tracing.h>
> > +#include <bpf/bpf_core_read.h>
> > +
> > +#define MY_TV_NSEC 1337
> > +
> > +bool tp_called = false;
> > +bool raw_tp_called = false;
> > +bool tp_btf_called = false;
> > +bool kprobe_called = false;
> > +bool fentry_called = false;
> > +
> > +SEC("tp/syscalls/sys_enter_nanosleep")
> > +int handle__tp(struct trace_event_raw_sys_enter *args)
> > +{
> > +     struct __kernel_timespec *ts;
> > +
> > +     if (args->id != __NR_nanosleep)
> > +             return 0;
> > +
> > +     ts = (void *)args->args[0];
> > +     if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
> > +             return 0;
> > +
> > +     tp_called = true;
> > +     return 0;
> > +}
> > +
> > +static bool __always_inline handle_probed(struct pt_regs *regs, long id)
> It is not used, may be removing it?
>

Oh, did I really leave it around?... Sigh, will post v2 without it.


> > +{
> > +     struct __kernel_timespec *ts;
> > +
> > +     if (id != __NR_nanosleep)
> > +             return false;
> > +
> > +     ts = (void *)PT_REGS_PARM1_CORE(regs);
> > +     if (BPF_CORE_READ(ts, tv_nsec) != MY_TV_NSEC)
> > +             return false;
> > +
> > +     return true;
> > +}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation
  2020-03-13 17:23 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
@ 2020-03-13 17:23 ` Andrii Nakryiko
  0 siblings, 0 replies; 8+ messages in thread
From: Andrii Nakryiko @ 2020-03-13 17:23 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel; +Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

When finding target type candidates, ignore forward declarations, functions,
and other named types of incompatible kind. Not doing this can cause false
errors.  See [0] for one such case (due to struct pt_regs forward
declaration).

  [0] https://github.com/iovisor/bcc/pull/2806#issuecomment-598543645

Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm")
Reported-by: Wenbo Zhang <ethercflow@gmail.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/lib/bpf/libbpf.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1a787a2faf58..085e41f9b68e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3873,6 +3873,10 @@ static struct ids_vec *bpf_core_find_cands(const struct btf *local_btf,
 		if (str_is_empty(targ_name))
 			continue;
 
+		t = skip_mods_and_typedefs(targ_btf, i, NULL);
+		if (!btf_is_composite(t) && !btf_is_array(t))
+			continue;
+
 		targ_essent_len = bpf_core_essential_name_len(targ_name);
 		if (targ_essent_len != local_essent_len)
 			continue;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-03-13 17:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-13  7:54 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
2020-03-13  7:54 ` [PATCH bpf-next 1/4] selftests/bpf: ensure consistent test failure output Andrii Nakryiko
2020-03-13  7:54 ` [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation Andrii Nakryiko
2020-03-13  7:54 ` [PATCH bpf-next 3/4] libbpf: provide CO-RE variants of PT_REGS macros Andrii Nakryiko
2020-03-13  7:54 ` [PATCH bpf-next 4/4] selftests/bpf: add vmlinux.h selftest exercising tracing of syscalls Andrii Nakryiko
2020-03-13 17:02   ` [Potential Spoof] " Martin KaFai Lau
2020-03-13 17:16     ` Andrii Nakryiko
2020-03-13 17:23 [PATCH bpf-next 0/4] CO-RE candidate matching fix and tracing test Andrii Nakryiko
2020-03-13 17:23 ` [PATCH bpf-next 2/4] libbpf: ignore incompatible types with matching name during CO-RE relocation Andrii Nakryiko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).