Przeglądaj źródła

bpf: disasm load extension to type LoadExtension

Load extension in BPF is an overload of the load absolute
instruction with a 'negative offset'. Disassemble load
absolute instructions to load extension, if the offset
is 'negative', respectively > (0xFFFFFFFF - 0x1000).

Fixes golang/go#18469

Change-Id: I13af8f5af89ce26b13a35d2b06879dd6e1c7434e
Reviewed-on: https://go-review.googlesource.com/34771
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Lucas Bremgartner 9 lat temu
rodzic
commit
ae05321a78
3 zmienionych plików z 22 dodań i 1 usunięć
  1. 3 0
      bpf/constants.go
  2. 4 1
      bpf/instructions.go
  3. 15 0
      bpf/instructions_test.go

+ 3 - 0
bpf/constants.go

@@ -70,6 +70,9 @@ type Extension int
 
 // Extension functions available in the Linux kernel.
 const (
+	// extOffset is the negative maximum number of instructions used
+	// to load instructions by overloading the K argument.
+	extOffset = -0x1000
 	// ExtLen returns the length of the packet.
 	ExtLen Extension = 1
 	// ExtProto returns the packet's L3 protocol type.

+ 4 - 1
bpf/instructions.go

@@ -57,6 +57,9 @@ func (ri RawInstruction) Disassemble() Instruction {
 			}
 			return LoadScratch{Dst: reg, N: int(ri.K)}
 		case opAddrModeAbsolute:
+			if ri.K > extOffset+0xffffffff {
+				return LoadExtension{Num: Extension(-extOffset + ri.K)}
+			}
 			return LoadAbsolute{Size: sz, Off: ri.K}
 		case opAddrModeIndirect:
 			return LoadIndirect{Size: sz, Off: ri.K}
@@ -259,7 +262,7 @@ func (a LoadExtension) Assemble() (RawInstruction, error) {
 	if a.Num == ExtLen {
 		return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
 	}
-	return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
+	return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
 }
 
 // StoreScratch stores register Src into scratch[N].

+ 15 - 0
bpf/instructions_test.go

@@ -197,3 +197,18 @@ func TestDisasmJumpIf(t *testing.T) {
 		}
 	}
 }
+
+func TestDisasmExtensions(t *testing.T) {
+	for _, instr := range allInstructions {
+		if extInstr, ok := instr.(LoadExtension); ok {
+			gotAsm, err := extInstr.Assemble()
+			if err != nil {
+				t.Fatalf("assembly of '%#v' failed: %s", extInstr, err)
+			}
+			got := gotAsm.Disassemble()
+			if !reflect.DeepEqual(extInstr, got) {
+				t.Errorf("program mutated by disassembly, expected: %#v, got: %#v", extInstr, got)
+			}
+		}
+	}
+}