117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
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))
|
|
}
|