浏览代码

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: Matt Layher <mdlayher@gmail.com>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Lucas Bremgartner 9 年之前
父节点
当前提交
279e808814
共有 2 个文件被更改,包括 39 次插入0 次删除
  1. 24 0
      bpf/instructions.go
  2. 15 0
      bpf/instructions_test.go

+ 24 - 0
bpf/instructions.go

@@ -104,6 +104,14 @@ func (ri RawInstruction) Disassemble() Instruction {
 		case opJumpAlways:
 			return Jump{Skip: ri.K}
 		case opJumpEqual:
+			if ri.Jt == 0 {
+				return JumpIf{
+					Cond:      JumpNotEqual,
+					Val:       ri.K,
+					SkipTrue:  ri.Jf,
+					SkipFalse: 0,
+				}
+			}
 			return JumpIf{
 				Cond:      JumpEqual,
 				Val:       ri.K,
@@ -111,6 +119,14 @@ func (ri RawInstruction) Disassemble() Instruction {
 				SkipFalse: ri.Jf,
 			}
 		case opJumpGT:
+			if ri.Jt == 0 {
+				return JumpIf{
+					Cond:      JumpLessOrEqual,
+					Val:       ri.K,
+					SkipTrue:  ri.Jf,
+					SkipFalse: 0,
+				}
+			}
 			return JumpIf{
 				Cond:      JumpGreaterThan,
 				Val:       ri.K,
@@ -118,6 +134,14 @@ func (ri RawInstruction) Disassemble() Instruction {
 				SkipFalse: ri.Jf,
 			}
 		case opJumpGE:
+			if ri.Jt == 0 {
+				return JumpIf{
+					Cond:      JumpLessThan,
+					Val:       ri.K,
+					SkipTrue:  ri.Jf,
+					SkipFalse: 0,
+				}
+			}
 			return JumpIf{
 				Cond:      JumpGreaterOrEqual,
 				Val:       ri.K,

+ 15 - 0
bpf/instructions_test.go

@@ -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)
+			}
+		}
+	}
+}