package seccomp import ( "fmt" "syscall" "unsafe" ) type sockFilter struct { code uint16 jt uint8 jf uint8 k uint32 } func newFilter() *filter { var f filter f = append(f, sockFilter{ pfLD + syscall.BPF_W + syscall.BPF_ABS, 0, 0, uint32(unsafe.Offsetof(secData.nr)), }) return &f } type filter []sockFilter func (f *filter) addSyscall(s *Syscall, labels *bpfLabels) { if len(s.Args) == 0 { f.call(s.Value, scmpBpfStmt(syscall.BPF_RET+syscall.BPF_K, s.scmpAction())) } else { if len(s.Args[0]) > 0 { lb := fmt.Sprintf(labelTemplate, s.Value, s.Args[0][0].Index) f.call(s.Value, scmpBpfJump(syscall.BPF_JMP+syscall.BPF_JA, labelIndex(labels, lb), jumpJT, jumpJF)) } } } func (f *filter) addArguments(s *Syscall, labels *bpfLabels) error { for i := 0; len(s.Args) > i; i++ { if len(s.Args[i]) > 0 { lb := fmt.Sprintf(labelTemplate, s.Value, s.Args[i][0].Index) f.label(labels, lb) f.arg(s.Args[i][0].Index) } for j := 0; j < len(s.Args[i]); j++ { var jf sockFilter if len(s.Args)-1 > i && len(s.Args[i+1]) > 0 { lbj := fmt.Sprintf(labelTemplate, s.Value, s.Args[i+1][0].Index) jf = scmpBpfJump(syscall.BPF_JMP+syscall.BPF_JA, labelIndex(labels, lbj), jumpJT, jumpJF) } else { jf = scmpBpfStmt(syscall.BPF_RET+syscall.BPF_K, s.scmpAction()) } if err := f.op(s.Args[i][j].Op, s.Args[i][j].Value, jf); err != nil { return err } } f.allow() } return nil } func (f *filter) label(labels *bpfLabels, lb string) { *f = append(*f, scmpBpfJump(syscall.BPF_JMP+syscall.BPF_JA, labelIndex(labels, lb), labelJT, labelJF)) } func (f *filter) call(nr uint32, jt sockFilter) { *f = append(*f, scmpBpfJump(syscall.BPF_JMP+syscall.BPF_JEQ+syscall.BPF_K, nr, 0, 1)) *f = append(*f, jt) } func (f *filter) allow() { *f = append(*f, scmpBpfStmt(syscall.BPF_RET+syscall.BPF_K, retAllow)) } func (f *filter) deny() { *f = append(*f, scmpBpfStmt(syscall.BPF_RET+syscall.BPF_K, retTrap)) } func (f *filter) arg(index uint32) { arg(f, index) } func (f *filter) op(operation Operator, v uint, jf sockFilter) error { switch operation { case EqualTo: jumpEqualTo(f, v, jf) case NotEqualTo: jumpNotEqualTo(f, v, jf) case GreatherThan: jumpGreaterThan(f, v, jf) case LessThan: jumpLessThan(f, v, jf) case MaskEqualTo: jumpMaskEqualTo(f, v, jf) default: return ErrUnsupportedOperation } return nil } func arg(f *filter, idx uint32) { *f = append(*f, scmpBpfStmt(syscall.BPF_LD+syscall.BPF_W+syscall.BPF_ABS, endian.low(idx))) *f = append(*f, scmpBpfStmt(syscall.BPF_ST, 0)) *f = append(*f, scmpBpfStmt(syscall.BPF_LD+syscall.BPF_W+syscall.BPF_ABS, endian.hi(idx))) *f = append(*f, scmpBpfStmt(syscall.BPF_ST, 1)) } func jump(f *filter, labels *bpfLabels, lb string) { *f = append(*f, scmpBpfJump(syscall.BPF_JMP+syscall.BPF_JA, labelIndex(labels, lb), jumpJT, jumpJF)) }