[DTrace-devel] okay to emit unlabeled BPF_NOP()?
Kris Van Hees
kris.van.hees at oracle.com
Thu Dec 10 20:31:00 PST 2020
On Thu, Dec 10, 2020 at 12:15:28PM -0800, Eugene Loh wrote:
> It appears that we can handle BPF_NOP() instructions only if they're
> labeled. Is that okay? Known limitation? Should we put a safeguard in
> for unlabeled BPF_NOP() instructions?
That's a bug...
> BPF_NOP() instructions are encoded as "jump 0" instructions. We
> (dt_cg.c) encode other jump instructions as "jump label", where label is
> a 1-based integer. Then, during the "second pass" of dt_as() we
> relocate jump targets, translating from labels to offsets (relative to
> the immediately following instruction). This means that a BPF_NOP() is
> interpreted as a jump to label 0, which does not exist, and bad code is
> produced, possibly causing the BPF verifier to fail.
>
> This is not a big problem right now since we only generate BPF_NOP()
> instructions when they are labeled, and there is special code to handle
> that case. But I'm wondering:
>
> *) Are we okay with that limitation? (We cannot emit unlabeled
> BPF_NOP() instructions.)
>
> *) Would it be okay to insert a safeguard -- say, in dt_irlist_append()
> or dt_as() -- against unlabeled BPF_NOP() instructions?
>
> Admittedly, it would seem ideal never to emit useless code.
> Nevertheless, it's easy enough to insert a safeguard against some
> unforeseen situation.
We should just make it work. The following patch will do that as far as I
can see. It ought to be correct because labels are always numbered from 1,
so a "jmp 0" instruction cannot be a valid jump to a label. Note that the
verifier will strip these NOPs from the instruction stream anyhow.
diff --git a/libdtrace/dt_as.c b/libdtrace/dt_as.c
index 437a2d86..c8ef0c17 100644
--- a/libdtrace/dt_as.c
+++ b/libdtrace/dt_as.c
@@ -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;
More information about the DTrace-devel
mailing list