[DTrace-devel] [PATCH] Handle unlabeled BPF_NOP instructions

eugene.loh at oracle.com eugene.loh at oracle.com
Fri Dec 11 15:41:04 PST 2020


From: Eugene Loh <eugene.loh at oracle.com>

Although BPF jump instructions take a relative distance, we emit BPF
code that jumps to 1-based labels, which are relocated to relative
distances later, during dt_as()'s second pass.

A special case is BPF_NOP instructions, which are jumps of 0 distance.
These targets are interpreted by dt_as() as "label 0", which does not
exist, which leads to incorrect code and possibly BPF verifier failures.

The problem has not been an issue so far since we have only emitted
BPF_NOP instructions that are themselves labeled, and that particular
case has been handled specially (by eliminating these NOPs during
dt_as's first pass).

Add code to exclude BPF_NOP (jump 0) from jump-target relocation.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_as.c  | 6 +++++-
 libdtrace/dt_dis.c | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/libdtrace/dt_as.c b/libdtrace/dt_as.c
index 437a2d86..e33d40a5 100644
--- a/libdtrace/dt_as.c
+++ b/libdtrace/dt_as.c
@@ -330,7 +330,7 @@ fail:
 
 	/*
 	 * Make a second pass through the instructions, relocating each branch
-	 * label to the index of the final instruction in the buffer and noting
+	 * label to be a jump relative to the following instruction and noting
 	 * any other instruction-specific DIFO flags such as dtdo_destructive.
 	 */
 	for (i = 0; i < dp->dtdo_len; i++) {
@@ -341,6 +341,10 @@ fail:
 		if (BPF_CLASS(instr.code) != BPF_JMP)
 			continue;
 
+		/* We ignore NOP (jmp 0). */
+		if (BPF_IS_NOP(instr))
+			continue;
+
 		/* We ignore function calls and function exits. */
 		if (op == BPF_CALL || op == BPF_EXIT)
 			continue;
diff --git a/libdtrace/dt_dis.c b/libdtrace/dt_dis.c
index d047bde3..27e98c30 100644
--- a/libdtrace/dt_dis.c
+++ b/libdtrace/dt_dis.c
@@ -346,7 +346,7 @@ dt_dis_jump(const dtrace_difo_t *dp, const char *name, uint_t addr,
 	    const struct bpf_insn *in, const char *rname, FILE *fp)
 {
 	if (in->off == 0)
-		fprintf(fp, "nop");
+		fprintf(fp, "nop\n");
 	else {
 		int	n;
 
-- 
2.18.4




More information about the DTrace-devel mailing list