func()

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