Skip to content

Commit

Permalink
compile: Fix compiling skb != 0
Browse files Browse the repository at this point in the history
If there is no struct/union member access, the zeroing R0 insn is
missing.

So, add the missing `xor r0, r0`, then add label when necessary.

Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
  • Loading branch information
Asphaltt committed Mar 8, 2025
1 parent 4dc53e6 commit dd8e1a9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
6 changes: 3 additions & 3 deletions compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,12 @@ func compile(expr *cc.Expr, typ btf.Type) (asm.Instructions, error) {
return nil, fmt.Errorf("failed to convert operator to instructions: %w", err)
}

xorR0 := asm.Xor.Reg(asm.R0, asm.R0)
if labelUsed {
insns = append(insns,
asm.Mov.Imm(asm.R0, 0).WithSymbol(labelExitFail), // r0 = 0; __exit
)
xorR0 = xorR0.WithSymbol(labelExitFail)
}
insns = append(insns,
xorR0, // r0 = 0
asm.Return().WithSymbol(labelReturn), // return; __return
)

Expand Down
26 changes: 22 additions & 4 deletions compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ func getBpfProgTypeBtf(t *testing.T) *btf.Enum {
return enum.(*btf.Enum)
}

func getU64Btf(t *testing.T) btf.Type {
u64, err := testBtf.AnyTypeByName("u64")
test.AssertNoErr(t, err)
return u64
}

func TestIsMemberBitfield(t *testing.T) {
test.AssertFalse(t, isMemberBitfield(nil))
test.AssertTrue(t, isMemberBitfield(&btf.Member{Offset: 1, BitfieldSize: 1}))
Expand Down Expand Up @@ -135,6 +141,17 @@ func TestExpr2offset(t *testing.T) {
test.AssertFalse(t, ast.bigEndian)
})

t.Run("(u64)skb != 0", func(t *testing.T) {
expr, err := parse("skb != 0")
test.AssertNoErr(t, err)

u64 := getU64Btf(t)
ast, err := expr2offset(expr.Left, u64)
test.AssertNoErr(t, err)
test.AssertEmptySlice(t, ast.offsets)
test.AssertTrue(t, ast.lastField == u64)
})

t.Run("skb->len > 1024", func(t *testing.T) {
expr, err := parse("skb->len > 1024")
test.AssertNoErr(t, err)
Expand Down Expand Up @@ -661,6 +678,7 @@ func TestCompile(t *testing.T) {
asm.Mov.Reg(asm.R3, asm.R1),
asm.Mov.Imm(asm.R0, 1),
asm.JNE.Imm(asm.R3, 0, labelReturn),
asm.Xor.Reg(asm.R0, asm.R0),
asm.Return().WithSymbol(labelReturn),
})
})
Expand Down Expand Up @@ -701,7 +719,7 @@ func TestCompile(t *testing.T) {
asm.RSh.Imm(asm.R3, 32),
asm.Mov.Imm(asm.R0, 1),
asm.JEq.Imm(asm.R3, 9, labelReturn),
asm.Mov.Imm(asm.R0, 0).WithSymbol(labelExitFail),
asm.Xor.Reg(asm.R0, asm.R0).WithSymbol(labelExitFail),
asm.Return().WithSymbol(labelReturn),
})
})
Expand All @@ -719,12 +737,12 @@ var skbLen1024Insns = asm.Instructions{
asm.RSh.Imm(asm.R3, 32),
asm.Mov.Imm(asm.R0, 1),
asm.JGT.Imm(asm.R3, 1024, labelReturn),
asm.Mov.Imm(asm.R0, 0).WithSymbol(labelExitFail),
asm.Xor.Reg(asm.R0, asm.R0).WithSymbol(labelExitFail),
asm.Return().WithSymbol(labelReturn),
}

func cloneSkbLen1024InsnsWithoutExitLabel() asm.Instructions {
insns := slices.Clone(skbLen1024Insns)
insns[len(insns)-2] = insns[len(insns)-1]
return insns[:len(insns)-1]
insns[len(insns)-2] = insns[len(insns)-2].WithMetadata(asm.Metadata{})
return insns
}
16 changes: 15 additions & 1 deletion simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"testing"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"

"github.com/leonhwangprojects/bice/internal/test"
)

Expand All @@ -29,11 +31,23 @@ func TestSimpleCompile(t *testing.T) {
test.AssertStrPrefix(t, err.Error(), "failed to compile expression")
})

t.Run("success", func(t *testing.T) {
t.Run("(struct sk_buff *)skb->len > 1024", func(t *testing.T) {
insns, err := SimpleCompile("skb->len > 1024", getSkbBtf(t))
test.AssertNoErr(t, err)
test.AssertEqualSlice(t, insns, cloneSkbLen1024InsnsWithoutExitLabel())
})

t.Run("(u64)skb != 0", func(t *testing.T) {
insns, err := SimpleCompile("skb != 0", getU64Btf(t))
test.AssertNoErr(t, err)
test.AssertEqualSlice(t, insns, asm.Instructions{
asm.Mov.Reg(asm.R3, asm.R1),
asm.Mov.Imm(asm.R0, 1),
asm.JNE.Imm(asm.R3, 0, labelReturn),
asm.Xor.Reg(asm.R0, asm.R0),
asm.Return().WithSymbol(labelReturn),
})
})
}

func TestSimpleInjectFilter(t *testing.T) {
Expand Down

0 comments on commit dd8e1a9

Please sign in to comment.