Commit 279e8088 authored by Lucas Bremgartner's avatar Lucas Bremgartner Committed by Mikio Hara

bpf: disasm "fake" jump conditions

JumpNotEqual, JumpLessThan and JumpLessOrEqual are "fake" jump
conditions that don't appear in the machine code. Nevertheless
these instructions (jneq/jne, jlt, jle) are listed in the
specification and therefore they should be reconstructed from the
machine code.

Fixes golang/go#18470

Specification: https://www.kernel.org/doc/Documentation/networking/filter.txt

Change-Id: I9116b99056e379d89e71adc90516c6747d388e5d
Reviewed-on: https://go-review.googlesource.com/34772
Run-TryBot: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarMatt Layher <mdlayher@gmail.com>
Reviewed-by: 's avatarMikio Hara <mikioh.mikioh@gmail.com>
parent 905989bd
...@@ -104,6 +104,14 @@ func (ri RawInstruction) Disassemble() Instruction { ...@@ -104,6 +104,14 @@ func (ri RawInstruction) Disassemble() Instruction {
case opJumpAlways: case opJumpAlways:
return Jump{Skip: ri.K} return Jump{Skip: ri.K}
case opJumpEqual: case opJumpEqual:
if ri.Jt == 0 {
return JumpIf{
Cond: JumpNotEqual,
Val: ri.K,
SkipTrue: ri.Jf,
SkipFalse: 0,
}
}
return JumpIf{ return JumpIf{
Cond: JumpEqual, Cond: JumpEqual,
Val: ri.K, Val: ri.K,
...@@ -111,6 +119,14 @@ func (ri RawInstruction) Disassemble() Instruction { ...@@ -111,6 +119,14 @@ func (ri RawInstruction) Disassemble() Instruction {
SkipFalse: ri.Jf, SkipFalse: ri.Jf,
} }
case opJumpGT: case opJumpGT:
if ri.Jt == 0 {
return JumpIf{
Cond: JumpLessOrEqual,
Val: ri.K,
SkipTrue: ri.Jf,
SkipFalse: 0,
}
}
return JumpIf{ return JumpIf{
Cond: JumpGreaterThan, Cond: JumpGreaterThan,
Val: ri.K, Val: ri.K,
...@@ -118,6 +134,14 @@ func (ri RawInstruction) Disassemble() Instruction { ...@@ -118,6 +134,14 @@ func (ri RawInstruction) Disassemble() Instruction {
SkipFalse: ri.Jf, SkipFalse: ri.Jf,
} }
case opJumpGE: case opJumpGE:
if ri.Jt == 0 {
return JumpIf{
Cond: JumpLessThan,
Val: ri.K,
SkipTrue: ri.Jf,
SkipFalse: 0,
}
}
return JumpIf{ return JumpIf{
Cond: JumpGreaterOrEqual, Cond: JumpGreaterOrEqual,
Val: ri.K, Val: ri.K,
......
...@@ -182,3 +182,18 @@ func TestAsmDisasm(t *testing.T) { ...@@ -182,3 +182,18 @@ func TestAsmDisasm(t *testing.T) {
} }
} }
} }
func TestDisasmJumpIf(t *testing.T) {
for _, instr := range allInstructions {
if jumpIfInstr, ok := instr.(JumpIf); ok {
gotAsm, err := jumpIfInstr.Assemble()
if err != nil {
t.Fatalf("assembly of '%#v' failed: %s", jumpIfInstr, err)
}
got := gotAsm.Disassemble()
if !reflect.DeepEqual(jumpIfInstr, got) {
t.Errorf("program mutated by disassembly, expected: %#v, got: %#v", jumpIfInstr, got)
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment