in filter.go [375:457]
func (s SyscallWithConditions) Assemble(p *Program, action Label) {
if len(s.Conditions) == 0 {
// If no conditions are set, compare to the syscall number and jump to action if it matches.
p.JmpIfTrue(bpf.JumpEqual, s.Num, action)
return
}
nextSyscall := p.NewLabel()
p.JmpIfTrue(bpf.JumpNotEqual, s.Num, nextSyscall)
for _, conditions := range s.Conditions {
noMatch := p.NewLabel()
for i, c := range conditions {
nextArgument := p.NewLabel()
// All argument checks must match, so if this argument check matches, jump to the next argument
// or if it is the last check to the action.
match := nextArgument
isLast := i == len(conditions)-1
if isLast {
match = action
}
// Perform the 64-bit operation with multiple 32-bit operations.
if c.Operation == Equal {
// Arg_hi == Val_hi && Arg_lo == Val_lo
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpEqual, uint32(c.Value), match, noMatch)
} else if c.Operation == NotEqual {
// Arg_hi != Val_hi || Arg_lo != Val_lo
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), match)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpNotEqual, uint32(c.Value), match, noMatch)
} else if c.Operation == GreaterThan {
// Arg_hi > Val_hi || (Arg_hi == Val_hi && Arg_lo > Val_lo)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpGreaterThan, uint32(c.Value>>32), match)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpGreaterThan, uint32(c.Value), match, noMatch)
} else if c.Operation == GreaterOrEqual {
// Arg_hi >= Val_hi || (Arg_hi == Val_hi && Arg_lo >= Val_lo)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpGreaterThan, uint32(c.Value>>32), match)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpGreaterOrEqual, uint32(c.Value), match, noMatch)
} else if c.Operation == LessThan {
// Arg_hi < Val_hi || (Arg_hi == Val_hi && Arg_lo < Val_lo)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpLessThan, uint32(c.Value>>32), match)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpLessThan, uint32(c.Value), match, noMatch)
} else if c.Operation == LessOrEqual {
// Arg_hi <= Val_hi || (Arg_hi == Val_hi && Arg_lo <= Val_lo)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpLessThan, uint32(c.Value>>32), match)
p.JmpIfTrue(bpf.JumpNotEqual, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpLessOrEqual, uint32(c.Value), match, noMatch)
} else if c.Operation == BitsSet {
// (Arg_hi & Val_hi == 0) || (Arg_lo & Val_lo == 0)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpBitsSet, uint32(c.Value>>32), match)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpBitsSet, uint32(c.Value), match, noMatch)
} else if c.Operation == BitsNotSet {
// (Arg_hi & Val_hi != 0) && (Arg_lo & Val_lo != 0)
p.LdHi(c.Argument)
p.JmpIfTrue(bpf.JumpBitsSet, uint32(c.Value>>32), noMatch)
p.LdLo(c.Argument)
p.JmpIf(bpf.JumpBitsNotSet, uint32(c.Value), match, noMatch)
}
p.SetLabel(nextArgument)
}
p.SetLabel(noMatch)
}
p.SetLabel(nextSyscall)
}