func()

in filter.go [202:258]


func (p *Policy) Assemble() ([]bpf.Instruction, error) {
	if err := p.Validate(); err != nil {
		return nil, err
	}

	// Ensure arch has been set for the policy.
	if p.arch == nil {
		arch, err := arch.GetInfo("")
		if err != nil {
			return nil, err
		}
		p.arch = arch
	}

	// Build the syscall filters.
	var instructions []bpf.Instruction
	for _, group := range p.Syscalls {
		if group.arch == nil {
			group.arch = p.arch
		}

		groupInsts, err := group.Assemble(p.DefaultAction)
		if err != nil {
			return nil, err
		}

		instructions = append(instructions, groupInsts...)
	}

	// Filter out x32 to prevent bypassing blacklists by using the 32-bit ABI.
	var x32Filter []bpf.Instruction
	if p.arch.ID == arch.X86_64.ID {
		x32Filter = []bpf.Instruction{
			bpf.JumpIf{Cond: bpf.JumpGreaterOrEqual, Val: uint32(arch.X32.SeccompMask), SkipFalse: 1},
			bpf.RetConstant{Val: uint32(ActionErrno) | uint32(errnoENOSYS)},
		}
	}

	program := make([]bpf.Instruction, 0, len(x32Filter)+len(instructions)+5)

	program = append(program, bpf.LoadAbsolute{Off: archOffset, Size: sizeOfUint32})

	// If the loaded arch ID is not equal p.arch.ID, jump to the final Ret instruction.
	jumpN := len(x32Filter) + len(instructions) - 1
	if jumpN <= 255 {
		program = append(program, bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: uint32(p.arch.ID), SkipTrue: uint8(jumpN)})
	} else {
		// JumpIf can not handle long jumps, so we switch to two instructions for this case.
		program = append(program, bpf.JumpIf{Cond: bpf.JumpEqual, Val: uint32(p.arch.ID), SkipTrue: 1})
		program = append(program, bpf.Jump{Skip: uint32(jumpN)})
	}

	program = append(program, bpf.LoadAbsolute{Off: syscallNumOffset, Size: sizeOfUint32})
	program = append(program, x32Filter...)
	program = append(program, instructions...)
	return program, nil
}