misc: small fix or general refactoring i did not bother commenting

This commit is contained in:
evilsocket 2018-10-12 17:51:38 +02:00
commit 5be3fcbf20
No known key found for this signature in database
GPG key ID: 82E42E7F3B34C97E
8 changed files with 421 additions and 117 deletions

12
Gopkg.lock generated
View file

@ -59,7 +59,6 @@
revision = "f58a169a71a51037728990b2d3597a14f56b525b" revision = "f58a169a71a51037728990b2d3597a14f56b525b"
[[projects]] [[projects]]
branch = "master"
digest = "1:32d8e0c62dc075d198abf73428828689f4e9473cadb8ef270be45fb78ae8648b" digest = "1:32d8e0c62dc075d198abf73428828689f4e9473cadb8ef270be45fb78ae8648b"
name = "github.com/evilsocket/islazy" name = "github.com/evilsocket/islazy"
packages = [ packages = [
@ -70,7 +69,8 @@
"zip", "zip",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "fd12757cd7fd9e544ea374582c7015587d9ac534" revision = "72e580f7bbdfb45d1332e06653248bc609bf0d50"
version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -252,19 +252,19 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:ed32e5b8c2cb13ea42eaca9f9dda1233ee78e9e5aa9a9839afd7911c52f121fa" digest = "1:b45576bdf553b4c64ff798345b3256e49a157f8b480d29c8c0a89f09119d6c5a"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = ["bpf"] packages = ["bpf"]
pruneopts = "UT" pruneopts = "UT"
revision = "146acd28ed5894421fb5aac80ca93bc1b1f46f87" revision = "49bb7cea24b1df9410e1712aa6433dae904ff66a"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:c2789211d4035eb0843b85958ecf7cb4a5ea91c2d4decee652c94ce898e433cb" digest = "1:0a40b0bdd57a93e741d8557465be3a2edeec408e9b6399586ad65bbe8e355796"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = ["unix"]
pruneopts = "UT" pruneopts = "UT"
revision = "4497e2df6f9e69048a54498c7affbbec3294ad47" revision = "fa43e7bc11baaae89f3f902b2b4d832b68234844"
[[projects]] [[projects]]
digest = "1:9935525a8c49b8434a0b0a54e1980e94a6fae73aaff45c5d33ba8dff69de123e" digest = "1:9935525a8c49b8434a0b0a54e1980e94a6fae73aaff45c5d33ba8dff69de123e"

View file

@ -55,7 +55,7 @@
[[constraint]] [[constraint]]
name = "github.com/google/gopacket" name = "github.com/google/gopacket"
version = "1.1.14" version = "1.1.15"
[[constraint]] [[constraint]]
name = "github.com/gorilla/mux" name = "github.com/gorilla/mux"

View file

@ -38,6 +38,7 @@ const (
type JumpTest uint16 type JumpTest uint16
// Supported operators for conditional jumps. // Supported operators for conditional jumps.
// K can be RegX for JumpIfX
const ( const (
// K == A // K == A
JumpEqual JumpTest = iota JumpEqual JumpTest = iota
@ -134,12 +135,9 @@ const (
opMaskLoadDest = 0x01 opMaskLoadDest = 0x01
opMaskLoadWidth = 0x18 opMaskLoadWidth = 0x18
opMaskLoadMode = 0xe0 opMaskLoadMode = 0xe0
// opClsALU // opClsALU & opClsJump
opMaskOperandSrc = 0x08 opMaskOperand = 0x08
opMaskOperator = 0xf0 opMaskOperator = 0xf0
// opClsJump
opMaskJumpConst = 0x0f
opMaskJumpCond = 0xf0
) )
const ( const (
@ -192,15 +190,21 @@ const (
opLoadWidth1 opLoadWidth1
) )
// Operator defined by ALUOp* // Operand for ALU and Jump instructions
type opOperand uint16
// Supported operand sources.
const ( const (
opALUSrcConstant uint16 = iota << 3 opOperandConstant opOperand = iota << 3
opALUSrcX opOperandX
) )
// An jumpOp is a conditional jump condition.
type jumpOp uint16
// Supported jump conditions.
const ( const (
opJumpAlways = iota << 4 opJumpAlways jumpOp = iota << 4
opJumpEqual opJumpEqual
opJumpGT opJumpGT
opJumpGE opJumpGE

View file

@ -89,10 +89,14 @@ func (ri RawInstruction) Disassemble() Instruction {
case opClsALU: case opClsALU:
switch op := ALUOp(ri.Op & opMaskOperator); op { switch op := ALUOp(ri.Op & opMaskOperator); op {
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor: case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
if ri.Op&opMaskOperandSrc != 0 { switch operand := opOperand(ri.Op & opMaskOperand); operand {
case opOperandX:
return ALUOpX{Op: op} return ALUOpX{Op: op}
} case opOperandConstant:
return ALUOpConstant{Op: op, Val: ri.K} return ALUOpConstant{Op: op, Val: ri.K}
default:
return ri
}
case aluOpNeg: case aluOpNeg:
return NegateA{} return NegateA{}
default: default:
@ -100,63 +104,18 @@ func (ri RawInstruction) Disassemble() Instruction {
} }
case opClsJump: case opClsJump:
if ri.Op&opMaskJumpConst != opClsJump { switch op := jumpOp(ri.Op & opMaskOperator); op {
return ri
}
switch ri.Op & opMaskJumpCond {
case opJumpAlways: case opJumpAlways:
return Jump{Skip: ri.K} return Jump{Skip: ri.K}
case opJumpEqual: case opJumpEqual, opJumpGT, opJumpGE, opJumpSet:
if ri.Jt == 0 { cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf)
return JumpIf{ switch operand := opOperand(ri.Op & opMaskOperand); operand {
Cond: JumpNotEqual, case opOperandX:
Val: ri.K, return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse}
SkipTrue: ri.Jf, case opOperandConstant:
SkipFalse: 0, return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse}
} default:
} return ri
return JumpIf{
Cond: JumpEqual,
Val: ri.K,
SkipTrue: ri.Jt,
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,
SkipTrue: ri.Jt,
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,
SkipTrue: ri.Jt,
SkipFalse: ri.Jf,
}
case opJumpSet:
return JumpIf{
Cond: JumpBitsSet,
Val: ri.K,
SkipTrue: ri.Jt,
SkipFalse: ri.Jf,
} }
default: default:
return ri return ri
@ -187,6 +146,41 @@ func (ri RawInstruction) Disassemble() Instruction {
} }
} }
func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) {
var test JumpTest
// Decode "fake" jump conditions that don't appear in machine code
// Ensures the Assemble -> Disassemble stage recreates the same instructions
// See https://github.com/golang/go/issues/18470
if skipTrue == 0 {
switch op {
case opJumpEqual:
test = JumpNotEqual
case opJumpGT:
test = JumpLessOrEqual
case opJumpGE:
test = JumpLessThan
case opJumpSet:
test = JumpBitsNotSet
}
return test, skipFalse, 0
}
switch op {
case opJumpEqual:
test = JumpEqual
case opJumpGT:
test = JumpGreaterThan
case opJumpGE:
test = JumpGreaterOrEqual
case opJumpSet:
test = JumpBitsSet
}
return test, skipTrue, skipFalse
}
// LoadConstant loads Val into register Dst. // LoadConstant loads Val into register Dst.
type LoadConstant struct { type LoadConstant struct {
Dst Register Dst Register
@ -413,7 +407,7 @@ type ALUOpConstant struct {
// Assemble implements the Instruction Assemble method. // Assemble implements the Instruction Assemble method.
func (a ALUOpConstant) Assemble() (RawInstruction, error) { func (a ALUOpConstant) Assemble() (RawInstruction, error) {
return RawInstruction{ return RawInstruction{
Op: opClsALU | opALUSrcConstant | uint16(a.Op), Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op),
K: a.Val, K: a.Val,
}, nil }, nil
} }
@ -454,7 +448,7 @@ type ALUOpX struct {
// Assemble implements the Instruction Assemble method. // Assemble implements the Instruction Assemble method.
func (a ALUOpX) Assemble() (RawInstruction, error) { func (a ALUOpX) Assemble() (RawInstruction, error) {
return RawInstruction{ return RawInstruction{
Op: opClsALU | opALUSrcX | uint16(a.Op), Op: opClsALU | uint16(opOperandX) | uint16(a.Op),
}, nil }, nil
} }
@ -509,7 +503,7 @@ type Jump struct {
// Assemble implements the Instruction Assemble method. // Assemble implements the Instruction Assemble method.
func (a Jump) Assemble() (RawInstruction, error) { func (a Jump) Assemble() (RawInstruction, error) {
return RawInstruction{ return RawInstruction{
Op: opClsJump | opJumpAlways, Op: opClsJump | uint16(opJumpAlways),
K: a.Skip, K: a.Skip,
}, nil }, nil
} }
@ -530,11 +524,39 @@ type JumpIf struct {
// Assemble implements the Instruction Assemble method. // Assemble implements the Instruction Assemble method.
func (a JumpIf) Assemble() (RawInstruction, error) { func (a JumpIf) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIf) String() string {
return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse)
}
// JumpIfX skips the following Skip instructions in the program if A
// <Cond> X is true.
type JumpIfX struct {
Cond JumpTest
SkipTrue uint8
SkipFalse uint8
}
// Assemble implements the Instruction Assemble method.
func (a JumpIfX) Assemble() (RawInstruction, error) {
return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse)
}
// String returns the instruction in assembler notation.
func (a JumpIfX) String() string {
return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse)
}
// jumpToRaw assembles a jump instruction into a RawInstruction
func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) {
var ( var (
cond uint16 cond jumpOp
flip bool flip bool
) )
switch a.Cond { switch test {
case JumpEqual: case JumpEqual:
cond = opJumpEqual cond = opJumpEqual
case JumpNotEqual: case JumpNotEqual:
@ -552,63 +574,63 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
case JumpBitsNotSet: case JumpBitsNotSet:
cond, flip = opJumpSet, true cond, flip = opJumpSet, true
default: default:
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond) return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test)
} }
jt, jf := a.SkipTrue, a.SkipFalse jt, jf := skipTrue, skipFalse
if flip { if flip {
jt, jf = jf, jt jt, jf = jf, jt
} }
return RawInstruction{ return RawInstruction{
Op: opClsJump | cond, Op: opClsJump | uint16(cond) | uint16(operand),
Jt: jt, Jt: jt,
Jf: jf, Jf: jf,
K: a.Val, K: k,
}, nil }, nil
} }
// String returns the instruction in assembler notation. // jumpToString converts a jump instruction to assembler notation
func (a JumpIf) String() string { func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string {
switch a.Cond { switch cond {
// K == A // K == A
case JumpEqual: case JumpEqual:
return conditionalJump(a, "jeq", "jneq") return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq")
// K != A // K != A
case JumpNotEqual: case JumpNotEqual:
return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue) return fmt.Sprintf("jneq %s,%d", operand, skipTrue)
// K > A // K > A
case JumpGreaterThan: case JumpGreaterThan:
return conditionalJump(a, "jgt", "jle") return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle")
// K < A // K < A
case JumpLessThan: case JumpLessThan:
return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue) return fmt.Sprintf("jlt %s,%d", operand, skipTrue)
// K >= A // K >= A
case JumpGreaterOrEqual: case JumpGreaterOrEqual:
return conditionalJump(a, "jge", "jlt") return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt")
// K <= A // K <= A
case JumpLessOrEqual: case JumpLessOrEqual:
return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue) return fmt.Sprintf("jle %s,%d", operand, skipTrue)
// K & A != 0 // K & A != 0
case JumpBitsSet: case JumpBitsSet:
if a.SkipFalse > 0 { if skipFalse > 0 {
return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse) return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse)
} }
return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue) return fmt.Sprintf("jset %s,%d", operand, skipTrue)
// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
case JumpBitsNotSet: case JumpBitsNotSet:
return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String() return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue)
default: default:
return fmt.Sprintf("unknown instruction: %#v", a) return fmt.Sprintf("unknown JumpTest %#v", cond)
} }
} }
func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string { func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string {
if inst.SkipTrue > 0 { if skipTrue > 0 {
if inst.SkipFalse > 0 { if skipFalse > 0 {
return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse) return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse)
} }
return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue) return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue)
} }
return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse) return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse)
} }
// RetA exits the BPF program, returning the value of register A. // RetA exits the BPF program, returning the value of register A.

10
vendor/golang.org/x/net/bpf/vm.go generated vendored
View file

@ -35,6 +35,13 @@ func NewVM(filter []Instruction) (*VM, error) {
if check <= int(ins.SkipFalse) { if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
} }
case JumpIfX:
if check <= int(ins.SkipTrue) {
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
}
if check <= int(ins.SkipFalse) {
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
}
// Check for division or modulus by zero // Check for division or modulus by zero
case ALUOpConstant: case ALUOpConstant:
if ins.Val != 0 { if ins.Val != 0 {
@ -109,6 +116,9 @@ func (v *VM) Run(in []byte) (int, error) {
case JumpIf: case JumpIf:
jump := jumpIf(ins, regA) jump := jumpIf(ins, regA)
i += jump i += jump
case JumpIfX:
jump := jumpIfX(ins, regA, regX)
i += jump
case LoadAbsolute: case LoadAbsolute:
regA, ok = loadAbsolute(ins, in) regA, ok = loadAbsolute(ins, in)
case LoadConstant: case LoadConstant:

View file

@ -55,34 +55,41 @@ func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
} }
} }
func jumpIf(ins JumpIf, value uint32) int { func jumpIf(ins JumpIf, regA uint32) int {
var ok bool return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val)
inV := uint32(ins.Val) }
switch ins.Cond { func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX)
}
func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int {
var ok bool
switch cond {
case JumpEqual: case JumpEqual:
ok = value == inV ok = regA == value
case JumpNotEqual: case JumpNotEqual:
ok = value != inV ok = regA != value
case JumpGreaterThan: case JumpGreaterThan:
ok = value > inV ok = regA > value
case JumpLessThan: case JumpLessThan:
ok = value < inV ok = regA < value
case JumpGreaterOrEqual: case JumpGreaterOrEqual:
ok = value >= inV ok = regA >= value
case JumpLessOrEqual: case JumpLessOrEqual:
ok = value <= inV ok = regA <= value
case JumpBitsSet: case JumpBitsSet:
ok = (value & inV) != 0 ok = (regA & value) != 0
case JumpBitsNotSet: case JumpBitsNotSet:
ok = (value & inV) == 0 ok = (regA & value) == 0
} }
if ok { if ok {
return int(ins.SkipTrue) return int(skipTrue)
} }
return int(ins.SkipFalse) return int(skipFalse)
} }
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) { func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {

View file

@ -92,6 +92,11 @@ while(<>) {
my @in = parseparamlist($in); my @in = parseparamlist($in);
my @out = parseparamlist($out); my @out = parseparamlist($out);
# Try in vain to keep people from editing this file.
# The theory is that they jump into the middle of the file
# without reading the header.
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
# So file name. # So file name.
if($modname eq "") { if($modname eq "") {
$modname = "libc"; $modname = "libc";

File diff suppressed because it is too large Load diff