mirror of
https://github.com/criyle/go-sandbox.git
synced 2025-11-04 14:49:53 +08:00
Refactor seccomp ptrace & improve container
This commit is contained in:
parent
3c77bf81d1
commit
7603109e33
@ -163,7 +163,7 @@ type Environment interface {
|
|||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
- config: defines arch & language specified trace condition for ptrace runner from UOJ
|
- cmd/runprog/config: defines arch & language specified trace condition for ptrace runner from UOJ
|
||||||
- container: creates pre-forked container to run programs inside
|
- container: creates pre-forked container to run programs inside
|
||||||
- runner: interface to run program
|
- runner: interface to run program
|
||||||
- ptrace: wrapper to call forkexec and ptracer
|
- ptrace: wrapper to call forkexec and ptracer
|
||||||
|
|||||||
@ -37,6 +37,8 @@ var (
|
|||||||
"ioctl",
|
"ioctl",
|
||||||
"fcntl",
|
"fcntl",
|
||||||
"fadvise64",
|
"fadvise64",
|
||||||
|
"pread64",
|
||||||
|
"pwrite64",
|
||||||
|
|
||||||
// memory action
|
// memory action
|
||||||
"mmap",
|
"mmap",
|
||||||
@ -13,14 +13,13 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/criyle/go-sandbox/config"
|
"github.com/criyle/go-sandbox/cmd/runprog/config"
|
||||||
"github.com/criyle/go-sandbox/container"
|
"github.com/criyle/go-sandbox/container"
|
||||||
"github.com/criyle/go-sandbox/pkg/cgroup"
|
"github.com/criyle/go-sandbox/pkg/cgroup"
|
||||||
"github.com/criyle/go-sandbox/pkg/forkexec"
|
"github.com/criyle/go-sandbox/pkg/forkexec"
|
||||||
"github.com/criyle/go-sandbox/pkg/memfd"
|
"github.com/criyle/go-sandbox/pkg/memfd"
|
||||||
"github.com/criyle/go-sandbox/pkg/mount"
|
"github.com/criyle/go-sandbox/pkg/mount"
|
||||||
"github.com/criyle/go-sandbox/pkg/rlimit"
|
"github.com/criyle/go-sandbox/pkg/rlimit"
|
||||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
|
||||||
"github.com/criyle/go-sandbox/pkg/seccomp/libseccomp"
|
"github.com/criyle/go-sandbox/pkg/seccomp/libseccomp"
|
||||||
"github.com/criyle/go-sandbox/runner"
|
"github.com/criyle/go-sandbox/runner"
|
||||||
"github.com/criyle/go-sandbox/runner/ptrace"
|
"github.com/criyle/go-sandbox/runner/ptrace"
|
||||||
@ -245,9 +244,9 @@ func start() (*runner.Result, error) {
|
|||||||
}
|
}
|
||||||
debug("rlimit: ", rlims)
|
debug("rlimit: ", rlims)
|
||||||
|
|
||||||
actionDefault := seccomp.ActionKill
|
actionDefault := libseccomp.ActionKill
|
||||||
if showDetails {
|
if showDetails {
|
||||||
actionDefault = seccomp.ActionTrace.WithReturnCode(seccomp.MsgDisallow)
|
actionDefault = libseccomp.ActionTrace
|
||||||
}
|
}
|
||||||
if runt != "ptrace" {
|
if runt != "ptrace" {
|
||||||
allow = append(allow, trace...)
|
allow = append(allow, trace...)
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
package container
|
package container
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cmdPing = "ping"
|
cmdPing cmdType = iota + 1
|
||||||
cmdCopyIn = "copyin"
|
cmdCopyIn
|
||||||
cmdOpen = "open"
|
cmdOpen
|
||||||
cmdDelete = "delete"
|
cmdDelete
|
||||||
cmdReset = "reset"
|
cmdReset
|
||||||
cmdExecve = "execve"
|
cmdExecve
|
||||||
cmdOk = "ok"
|
cmdOk
|
||||||
cmdKill = "kill"
|
cmdKill
|
||||||
cmdConf = "conf"
|
cmdConf
|
||||||
|
|
||||||
initArg = "container_init"
|
initArg = "container_init"
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,10 @@ func (c *containerServer) handleExecve(cmd *execCmd, msg *unixsocket.Msg) error
|
|||||||
// cannot exists now since host assumes the start will alway work
|
// cannot exists now since host assumes the start will alway work
|
||||||
err = fmt.Errorf("execve: start: %v", err)
|
err = fmt.Errorf("execve: start: %v", err)
|
||||||
}
|
}
|
||||||
|
return c.handleExecveStarted(pid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *containerServer) handleExecveStarted(pid int, err error) error {
|
||||||
// done is to signal kill goroutine exits
|
// done is to signal kill goroutine exits
|
||||||
killDone := make(chan struct{})
|
killDone := make(chan struct{})
|
||||||
// waitDone is to signal kill goroutine to collect zombies
|
// waitDone is to signal kill goroutine to collect zombies
|
||||||
|
|||||||
@ -90,7 +90,7 @@ func (c *containerServer) handleCmd(cmd *cmd, msg *unixsocket.Msg) error {
|
|||||||
case cmdExecve:
|
case cmdExecve:
|
||||||
return c.handleExecve(cmd.ExecCmd, msg)
|
return c.handleExecve(cmd.ExecCmd, msg)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unknown command: %s", cmd.Cmd)
|
return fmt.Errorf("unknown command: %v", cmd.Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initContainer(c containerConfig) error {
|
func initContainer(c containerConfig) error {
|
||||||
|
|||||||
@ -11,9 +11,11 @@ import (
|
|||||||
"github.com/criyle/go-sandbox/runner"
|
"github.com/criyle/go-sandbox/runner"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type cmdType int
|
||||||
|
|
||||||
// cmd is the control message send into container
|
// cmd is the control message send into container
|
||||||
type cmd struct {
|
type cmd struct {
|
||||||
Cmd string // type of the cmd
|
Cmd cmdType // type of the cmd
|
||||||
|
|
||||||
OpenCmd []OpenCmd // open argument
|
OpenCmd []OpenCmd // open argument
|
||||||
DeleteCmd *deleteCmd // delete argument
|
DeleteCmd *deleteCmd // delete argument
|
||||||
|
|||||||
7
go.mod
7
go.mod
@ -8,10 +8,9 @@ require (
|
|||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/stretchr/testify v1.6.1 // indirect
|
github.com/stretchr/testify v1.6.1 // indirect
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88
|
golang.org/x/net v0.0.0-20201216054612-986b41b23924
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/elastic/go-seccomp-bpf => ../go-seccomp-bpf
|
|
||||||
|
|||||||
13
go.sum
13
go.sum
@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/elastic/go-seccomp-bpf v1.1.0 h1:jUzzDc6LyCtdolZdvL/26dad6rZ9vsc7xZ2eadKECAU=
|
||||||
|
github.com/elastic/go-seccomp-bpf v1.1.0/go.mod h1:l+89Vy5BzjVcaX8USZRMOwmwwDScE+vxCFzzvQwN7T8=
|
||||||
github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo=
|
github.com/elastic/go-ucfg v0.7.0/go.mod h1:iaiY0NBIYeasNgycLyTvhJftQlQEUO2hpF+FX0JKxzo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
@ -17,6 +19,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
@ -24,16 +27,26 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
|
||||||
|
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
|
||||||
|
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
package seccomp
|
package libseccomp
|
||||||
|
|
||||||
// Action is seccomp trap action
|
// Action is seccomp trap action
|
||||||
type Action uint32
|
type Action uint32
|
||||||
@ -19,16 +19,6 @@ const (
|
|||||||
MsgHandle
|
MsgHandle
|
||||||
)
|
)
|
||||||
|
|
||||||
// WithReturnCode set the return code when action is trace or ban
|
|
||||||
func (a Action) WithReturnCode(code int16) Action {
|
|
||||||
return a.Action() | Action(code)<<16
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReturnCode get the return code
|
|
||||||
func (a Action) ReturnCode() int16 {
|
|
||||||
return int16(a >> 16)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Action get the basic action
|
// Action get the basic action
|
||||||
func (a Action) Action() Action {
|
func (a Action) Action() Action {
|
||||||
return Action(a & 0xffff)
|
return Action(a & 0xffff)
|
||||||
@ -1,25 +1,24 @@
|
|||||||
package libseccomp
|
package libseccomp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
|
||||||
libseccomp "github.com/elastic/go-seccomp-bpf"
|
libseccomp "github.com/elastic/go-seccomp-bpf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ToSeccompAction convert action to libseccomp compatible action
|
// ToSeccompAction convert action to libseccomp compatible action
|
||||||
func ToSeccompAction(a seccomp.Action) libseccomp.Action {
|
func ToSeccompAction(a Action) libseccomp.Action {
|
||||||
var action libseccomp.Action
|
var action libseccomp.Action
|
||||||
switch a.Action() {
|
switch a.Action() {
|
||||||
case seccomp.ActionAllow:
|
case ActionAllow:
|
||||||
action = libseccomp.ActionAllow
|
action = libseccomp.ActionAllow
|
||||||
case seccomp.ActionErrno:
|
case ActionErrno:
|
||||||
action = libseccomp.ActionErrno
|
action = libseccomp.ActionErrno
|
||||||
case seccomp.ActionTrace:
|
case ActionTrace:
|
||||||
action = libseccomp.ActionTrace
|
action = libseccomp.ActionTrace
|
||||||
default:
|
default:
|
||||||
action = libseccomp.ActionKillProcess
|
action = libseccomp.ActionKillProcess
|
||||||
}
|
}
|
||||||
// the least 16 bit of ret value is SECCOMP_RET_DATA
|
// the least 16 bit of ret value is SECCOMP_RET_DATA
|
||||||
// although it might not officially supported by go-seccomp-bpf
|
// although it might not officially supported by go-seccomp-bpf
|
||||||
action = action.WithReturnData(int(a.ReturnCode()))
|
// action = action.WithReturnData(int(a.ReturnCode()))
|
||||||
return action
|
return action
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,10 +11,10 @@ import (
|
|||||||
// Builder is used to build the filter
|
// Builder is used to build the filter
|
||||||
type Builder struct {
|
type Builder struct {
|
||||||
Allow, Trace []string
|
Allow, Trace []string
|
||||||
Default seccomp.Action
|
Default Action
|
||||||
}
|
}
|
||||||
|
|
||||||
var actTrace = libseccomp.ActionTrace | libseccomp.Action(seccomp.MsgHandle)
|
var actTrace = libseccomp.ActionTrace
|
||||||
|
|
||||||
// Build builds the filter
|
// Build builds the filter
|
||||||
func (b *Builder) Build() (seccomp.Filter, error) {
|
func (b *Builder) Build() (seccomp.Filter, error) {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func BenchmarkBuildDefaultFilter(b *testing.B) {
|
|||||||
builder := Builder{
|
builder := Builder{
|
||||||
Allow: defaultSyscallAllows,
|
Allow: defaultSyscallAllows,
|
||||||
Trace: defaultSyscallTraces,
|
Trace: defaultSyscallTraces,
|
||||||
Default: seccomp.ActionTrace,
|
Default: ActionTrace,
|
||||||
}
|
}
|
||||||
builder.Build()
|
builder.Build()
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ func buildFilterMock() (seccomp.Filter, error) {
|
|||||||
b := Builder{
|
b := Builder{
|
||||||
Allow: []string{"fork"},
|
Allow: []string{"fork"},
|
||||||
Trace: []string{"execve"},
|
Trace: []string{"execve"},
|
||||||
Default: seccomp.ActionTrace,
|
Default: ActionTrace,
|
||||||
}
|
}
|
||||||
return b.Build()
|
return b.Build()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ type TraceAction int
|
|||||||
const (
|
const (
|
||||||
// TraceAllow does not do anything
|
// TraceAllow does not do anything
|
||||||
TraceAllow TraceAction = iota
|
TraceAllow TraceAction = iota
|
||||||
// TraceBan blocked the syscall and set the return code specified by SetReturnCode
|
// TraceBan skippes the syscall and set the return code specified by SetReturnCode
|
||||||
TraceBan
|
TraceBan
|
||||||
// TraceKill referred as dangerous action have been detected
|
// TraceKill referred as dangerous action have been detected
|
||||||
TraceKill
|
TraceKill
|
||||||
@ -24,14 +24,15 @@ type Tracer struct {
|
|||||||
// Runner represents the process runner
|
// Runner represents the process runner
|
||||||
type Runner interface {
|
type Runner interface {
|
||||||
// Starts starts the child process and return pid and error if failed
|
// Starts starts the child process and return pid and error if failed
|
||||||
|
// the child process should enable ptrace and should stop before ptrace
|
||||||
Start() (int, error)
|
Start() (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler defines customized handler for traced syscall
|
// Handler defines customized handler for traced syscall
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
|
// Handle returns action take to the traced program
|
||||||
Handle(*Context) TraceAction
|
Handle(*Context) TraceAction
|
||||||
GetSyscallName(*Context) (string, error)
|
|
||||||
|
|
||||||
|
// Debug prints debug information when in debug mode
|
||||||
Debug(v ...interface{})
|
Debug(v ...interface{})
|
||||||
HandlerDisallow(string) error
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
unix "golang.org/x/sys/unix"
|
unix "golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/criyle/go-sandbox/pkg/seccomp"
|
|
||||||
"github.com/criyle/go-sandbox/runner"
|
"github.com/criyle/go-sandbox/runner"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,17 +23,6 @@ func (t *Tracer) Trace(c context.Context) <-chan runner.Result {
|
|||||||
// TraceRun start and traces all child process by runner in the calling goroutine
|
// TraceRun start and traces all child process by runner in the calling goroutine
|
||||||
// parameter done used to cancel work, start is used notify child starts
|
// parameter done used to cancel work, start is used notify child starts
|
||||||
func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
||||||
var (
|
|
||||||
status = runner.StatusNormal
|
|
||||||
wstatus unix.WaitStatus // wait4 wait status
|
|
||||||
rusage unix.Rusage // wait4 rusage
|
|
||||||
traced = make(map[int]bool) // store all process that have set ptrace options
|
|
||||||
execved = false // store whether the runner process have successfully execvd
|
|
||||||
pid int // store pid of wait4 result
|
|
||||||
sTime = time.Now() // records start time for trace process
|
|
||||||
fTime time.Time // records finish time for execve
|
|
||||||
)
|
|
||||||
|
|
||||||
// ptrace is thread based (kernel proc)
|
// ptrace is thread based (kernel proc)
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
defer runtime.UnlockOSThread()
|
defer runtime.UnlockOSThread()
|
||||||
@ -48,7 +36,10 @@ func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
|||||||
result.Error = err.Error()
|
result.Error = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
return t.trace(c, pgid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tracer) trace(c context.Context, pgid int) (result runner.Result) {
|
||||||
cc, cancel := context.WithCancel(c)
|
cc, cancel := context.WithCancel(c)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@ -58,6 +49,9 @@ func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
|||||||
killAll(pgid)
|
killAll(pgid)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
sTime := time.Now()
|
||||||
|
ph := newPtraceHandle(t, pgid)
|
||||||
|
|
||||||
// handler potential panic and tle
|
// handler potential panic and tle
|
||||||
// also ensure processes was well terminated
|
// also ensure processes was well terminated
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -69,13 +63,21 @@ func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
|||||||
// kill all tracee upon return
|
// kill all tracee upon return
|
||||||
killAll(pgid)
|
killAll(pgid)
|
||||||
collectZombie(pgid)
|
collectZombie(pgid)
|
||||||
result.SetUpTime = fTime.Sub(sTime)
|
if !ph.fTime.IsZero() {
|
||||||
result.RunningTime = time.Since(fTime)
|
result.SetUpTime = ph.fTime.Sub(sTime)
|
||||||
|
result.RunningTime = time.Since(ph.fTime)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// ptrace pool loop
|
// ptrace pool loop
|
||||||
for {
|
for {
|
||||||
if execved {
|
var (
|
||||||
|
wstatus unix.WaitStatus // wait4 wait status
|
||||||
|
rusage unix.Rusage // wait4 rusage
|
||||||
|
pid int // store pid of wait4 result
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if ph.execved {
|
||||||
// Wait for all child in the process group
|
// Wait for all child in the process group
|
||||||
pid, err = unix.Wait4(-pgid, &wstatus, unix.WALL, &rusage)
|
pid, err = unix.Wait4(-pgid, &wstatus, unix.WALL, &rusage)
|
||||||
} else {
|
} else {
|
||||||
@ -94,184 +96,194 @@ func (t *Tracer) TraceRun(c context.Context) (result runner.Result) {
|
|||||||
}
|
}
|
||||||
t.Handler.Debug("------ ", pid, " ------")
|
t.Handler.Debug("------ ", pid, " ------")
|
||||||
|
|
||||||
|
// update rusage
|
||||||
if pid == pgid {
|
if pid == pgid {
|
||||||
// update resource usage and check against limits
|
userTime, userMem, curStatus := t.checkUsage(rusage)
|
||||||
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
result.Status = curStatus
|
||||||
userMem := runner.Size(rusage.Maxrss << 10) // bytes
|
result.Time = userTime
|
||||||
|
result.Memory = userMem
|
||||||
// check tle / mle
|
if curStatus != runner.StatusNormal {
|
||||||
if userTime > t.Limit.TimeLimit {
|
|
||||||
status = runner.StatusTimeLimitExceeded
|
|
||||||
}
|
|
||||||
if userMem > t.Limit.MemoryLimit {
|
|
||||||
status = runner.StatusMemoryLimitExceeded
|
|
||||||
}
|
|
||||||
result = runner.Result{
|
|
||||||
Status: status,
|
|
||||||
Time: userTime,
|
|
||||||
Memory: userMem,
|
|
||||||
}
|
|
||||||
if status != runner.StatusNormal {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check process status
|
status, exitStatus, errStr, finished := ph.handle(pid, wstatus)
|
||||||
switch {
|
if finished || status != runner.StatusNormal {
|
||||||
case wstatus.Exited():
|
result.Status = status
|
||||||
delete(traced, pid)
|
result.ExitStatus = exitStatus
|
||||||
t.Handler.Debug("process exited: ", pid, wstatus.ExitStatus())
|
result.Error = errStr
|
||||||
if pid == pgid {
|
return
|
||||||
if execved {
|
|
||||||
result.ExitStatus = wstatus.ExitStatus()
|
|
||||||
if result.ExitStatus == 0 {
|
|
||||||
result.Status = runner.StatusNormal
|
|
||||||
} else {
|
|
||||||
result.Status = runner.StatusNonzeroExitStatus
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result.Status = runner.StatusRunnerError
|
|
||||||
result.Error = "child process exit before execve"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case wstatus.Signaled():
|
|
||||||
sig := wstatus.Signal()
|
|
||||||
t.Handler.Debug("ptrace signaled: ", sig)
|
|
||||||
if pid == pgid {
|
|
||||||
delete(traced, pid)
|
|
||||||
switch sig {
|
|
||||||
case unix.SIGXCPU, unix.SIGKILL:
|
|
||||||
status = runner.StatusTimeLimitExceeded
|
|
||||||
case unix.SIGXFSZ:
|
|
||||||
status = runner.StatusOutputLimitExceeded
|
|
||||||
case unix.SIGSYS:
|
|
||||||
status = runner.StatusDisallowedSyscall
|
|
||||||
default:
|
|
||||||
status = runner.StatusSignalled
|
|
||||||
}
|
|
||||||
result.Status = status
|
|
||||||
result.ExitStatus = int(sig)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
unix.PtraceCont(pid, int(sig))
|
|
||||||
|
|
||||||
case wstatus.Stopped():
|
|
||||||
// Set option if the process is newly forked
|
|
||||||
if !traced[pid] {
|
|
||||||
t.Handler.Debug("set ptrace option for", pid)
|
|
||||||
traced[pid] = true
|
|
||||||
// Ptrace set option valid if the tracee is stopped
|
|
||||||
err = setPtraceOption(pid)
|
|
||||||
if err != nil {
|
|
||||||
result.Status = runner.StatusRunnerError
|
|
||||||
result.Error = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check stop signal, if trap then check seccomp
|
|
||||||
if stopSig := wstatus.StopSignal(); stopSig == unix.SIGTRAP {
|
|
||||||
switch trapCause := wstatus.TrapCause(); trapCause {
|
|
||||||
case unix.PTRACE_EVENT_SECCOMP:
|
|
||||||
if execved {
|
|
||||||
// give the customized handle for syscall
|
|
||||||
err := t.handleTrap(pid)
|
|
||||||
if err != nil {
|
|
||||||
result.Status = runner.StatusDisallowedSyscall
|
|
||||||
result.Error = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.Handler.Debug("ptrace seccomp before execve (should be the execve syscall)")
|
|
||||||
}
|
|
||||||
|
|
||||||
case unix.PTRACE_EVENT_CLONE:
|
|
||||||
t.Handler.Debug("ptrace stop clone")
|
|
||||||
case unix.PTRACE_EVENT_VFORK:
|
|
||||||
t.Handler.Debug("ptrace stop vfork")
|
|
||||||
case unix.PTRACE_EVENT_FORK:
|
|
||||||
t.Handler.Debug("ptrace stop fork")
|
|
||||||
case unix.PTRACE_EVENT_EXEC:
|
|
||||||
// forked tracee have successfully called execve
|
|
||||||
if !execved {
|
|
||||||
fTime = time.Now()
|
|
||||||
execved = true
|
|
||||||
}
|
|
||||||
t.Handler.Debug("ptrace stop exec")
|
|
||||||
|
|
||||||
default:
|
|
||||||
t.Handler.Debug("ptrace unexpected trap cause: ", trapCause)
|
|
||||||
}
|
|
||||||
unix.PtraceCont(pid, 0)
|
|
||||||
} else {
|
|
||||||
// check if cpu rlimit hit
|
|
||||||
switch stopSig {
|
|
||||||
case unix.SIGXCPU:
|
|
||||||
status = runner.StatusTimeLimitExceeded
|
|
||||||
case unix.SIGXFSZ:
|
|
||||||
status = runner.StatusOutputLimitExceeded
|
|
||||||
}
|
|
||||||
if status != runner.StatusNormal {
|
|
||||||
result.Status = status
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Likely encountered SIGSEGV (segment violation)
|
|
||||||
// Or compiler child exited
|
|
||||||
if stopSig != unix.SIGSTOP {
|
|
||||||
t.Handler.Debug("ptrace unexpected stop signal: ", stopSig)
|
|
||||||
}
|
|
||||||
t.Handler.Debug("ptrace stopped")
|
|
||||||
unix.PtraceCont(pid, int(stopSig))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleTrap handles the seccomp trap including the custom handle
|
func (t *Tracer) checkUsage(rusage unix.Rusage) (time.Duration, runner.Size, runner.Status) {
|
||||||
func (t *Tracer) handleTrap(pid int) error {
|
status := runner.StatusNormal
|
||||||
t.Handler.Debug("seccomp traced")
|
// update resource usage and check against limits
|
||||||
msg, err := unix.PtraceGetEventMsg(pid)
|
userTime := time.Duration(rusage.Utime.Nano()) // ns
|
||||||
if err != nil {
|
userMem := runner.Size(rusage.Maxrss << 10) // bytes
|
||||||
t.Handler.Debug("PtraceGetEventMsg failed:", err)
|
|
||||||
return err
|
// check tle / mle
|
||||||
|
if userTime > t.Limit.TimeLimit {
|
||||||
|
status = runner.StatusTimeLimitExceeded
|
||||||
}
|
}
|
||||||
switch int16(msg) {
|
if userMem > t.Limit.MemoryLimit {
|
||||||
case seccomp.MsgDisallow:
|
status = runner.StatusMemoryLimitExceeded
|
||||||
|
}
|
||||||
|
return userTime, userMem, status
|
||||||
|
}
|
||||||
|
|
||||||
|
type ptraceHandle struct {
|
||||||
|
*Tracer
|
||||||
|
pgid int
|
||||||
|
traced map[int]bool
|
||||||
|
execved bool
|
||||||
|
fTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPtraceHandle(t *Tracer, pgid int) *ptraceHandle {
|
||||||
|
return &ptraceHandle{t, pgid, make(map[int]bool), false, time.Time{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ph *ptraceHandle) handle(pid int, wstatus unix.WaitStatus) (status runner.Status, exitStatus int, errStr string, finished bool) {
|
||||||
|
status = runner.StatusNormal
|
||||||
|
// check process status
|
||||||
|
switch {
|
||||||
|
case wstatus.Exited():
|
||||||
|
delete(ph.traced, pid)
|
||||||
|
ph.Handler.Debug("process exited: ", pid, wstatus.ExitStatus())
|
||||||
|
if pid == ph.pgid {
|
||||||
|
finished = true
|
||||||
|
if ph.execved {
|
||||||
|
exitStatus = wstatus.ExitStatus()
|
||||||
|
if exitStatus == 0 {
|
||||||
|
status = runner.StatusNormal
|
||||||
|
} else {
|
||||||
|
status = runner.StatusNonzeroExitStatus
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
status = runner.StatusRunnerError
|
||||||
|
errStr = "child process exit before execve"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
case wstatus.Signaled():
|
||||||
|
sig := wstatus.Signal()
|
||||||
|
ph.Handler.Debug("ptrace signaled: ", sig)
|
||||||
|
if pid == ph.pgid {
|
||||||
|
delete(ph.traced, pid)
|
||||||
|
switch sig {
|
||||||
|
case unix.SIGXCPU, unix.SIGKILL:
|
||||||
|
status = runner.StatusTimeLimitExceeded
|
||||||
|
case unix.SIGXFSZ:
|
||||||
|
status = runner.StatusOutputLimitExceeded
|
||||||
|
case unix.SIGSYS:
|
||||||
|
status = runner.StatusDisallowedSyscall
|
||||||
|
default:
|
||||||
|
status = runner.StatusSignalled
|
||||||
|
}
|
||||||
|
exitStatus = int(sig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
unix.PtraceCont(pid, int(sig))
|
||||||
|
|
||||||
|
case wstatus.Stopped():
|
||||||
|
// Set option if the process is newly forked
|
||||||
|
if !ph.traced[pid] {
|
||||||
|
ph.Handler.Debug("set ptrace option for", pid)
|
||||||
|
ph.traced[pid] = true
|
||||||
|
// Ptrace set option valid if the tracee is stopped
|
||||||
|
if err := setPtraceOption(pid); err != nil {
|
||||||
|
status = runner.StatusRunnerError
|
||||||
|
errStr = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopSig := wstatus.StopSignal()
|
||||||
|
// Check stop signal, if trap then check seccomp
|
||||||
|
switch stopSig {
|
||||||
|
case unix.SIGTRAP:
|
||||||
|
switch trapCause := wstatus.TrapCause(); trapCause {
|
||||||
|
case unix.PTRACE_EVENT_SECCOMP:
|
||||||
|
if ph.execved {
|
||||||
|
// give the customized handle for syscall
|
||||||
|
err := ph.handleTrap(pid)
|
||||||
|
if err != nil {
|
||||||
|
status = runner.StatusDisallowedSyscall
|
||||||
|
errStr = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ph.Handler.Debug("ptrace seccomp before execve (should be the execve syscall)")
|
||||||
|
}
|
||||||
|
|
||||||
|
case unix.PTRACE_EVENT_CLONE:
|
||||||
|
ph.Handler.Debug("ptrace stop clone")
|
||||||
|
case unix.PTRACE_EVENT_VFORK:
|
||||||
|
ph.Handler.Debug("ptrace stop vfork")
|
||||||
|
case unix.PTRACE_EVENT_FORK:
|
||||||
|
ph.Handler.Debug("ptrace stop fork")
|
||||||
|
case unix.PTRACE_EVENT_EXEC:
|
||||||
|
// forked tracee have successfully called execve
|
||||||
|
if !ph.execved {
|
||||||
|
ph.fTime = time.Now()
|
||||||
|
ph.execved = true
|
||||||
|
}
|
||||||
|
ph.Handler.Debug("ptrace stop exec")
|
||||||
|
|
||||||
|
default:
|
||||||
|
ph.Handler.Debug("ptrace unexpected trap cause: ", trapCause)
|
||||||
|
}
|
||||||
|
unix.PtraceCont(pid, 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
// check if cpu rlimit hit
|
||||||
|
case unix.SIGXCPU:
|
||||||
|
status = runner.StatusTimeLimitExceeded
|
||||||
|
case unix.SIGXFSZ:
|
||||||
|
status = runner.StatusOutputLimitExceeded
|
||||||
|
}
|
||||||
|
if status != runner.StatusNormal {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Likely encountered SIGSEGV (segment violation)
|
||||||
|
// Or compiler child exited
|
||||||
|
if stopSig != unix.SIGSTOP {
|
||||||
|
ph.Handler.Debug("ptrace unexpected stop signal: ", stopSig)
|
||||||
|
}
|
||||||
|
ph.Handler.Debug("ptrace stopped")
|
||||||
|
unix.PtraceCont(pid, int(stopSig))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleTrap handles the seccomp trap including the custom handle
|
||||||
|
func (ph *ptraceHandle) handleTrap(pid int) error {
|
||||||
|
ph.Handler.Debug("seccomp traced")
|
||||||
|
// msg, err := unix.PtraceGetEventMsg(pid)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Handler.Debug("PtraceGetEventMsg failed:", err)
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
if ph.Handler != nil {
|
||||||
ctx, err := getTrapContext(pid)
|
ctx, err := getTrapContext(pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Handler.Debug("getTrapContext failed:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
syscallName, err := t.Handler.GetSyscallName(ctx)
|
act := ph.Handler.Handle(ctx)
|
||||||
t.Handler.Debug("disallowed syscall: ", ctx.SyscallNo(), syscallName, err)
|
|
||||||
return t.Handler.HandlerDisallow(syscallName)
|
|
||||||
|
|
||||||
case seccomp.MsgHandle:
|
switch act {
|
||||||
if t.Handler != nil {
|
case TraceBan:
|
||||||
ctx, err := getTrapContext(pid)
|
// Set the syscallno to -1 and return value into register to skip syscall.
|
||||||
if err != nil {
|
// https://www.kernel.org/doc/Documentation/prctl/pkg/seccomp_filter.txt
|
||||||
return err
|
return ctx.skipSyscall()
|
||||||
}
|
|
||||||
act := t.Handler.Handle(ctx)
|
|
||||||
|
|
||||||
switch act {
|
case TraceKill:
|
||||||
case TraceBan:
|
return runner.StatusDisallowedSyscall
|
||||||
// Set the syscallno to -1 and return value into register to skip syscall.
|
|
||||||
// https://www.kernel.org/doc/Documentation/prctl/pkg/seccomp_filter.txt
|
|
||||||
return ctx.skipSyscall()
|
|
||||||
|
|
||||||
case TraceKill:
|
|
||||||
return runner.StatusDisallowedSyscall
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
// undefined seccomp message, possible set up filter wrong
|
|
||||||
t.Handler.Debug("unknown seccomp trap message: ", msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/criyle/go-sandbox/pkg/seccomp/libseccomp"
|
"github.com/criyle/go-sandbox/pkg/seccomp/libseccomp"
|
||||||
"github.com/criyle/go-sandbox/ptracer"
|
"github.com/criyle/go-sandbox/ptracer"
|
||||||
"github.com/criyle/go-sandbox/runner"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type tracerHandler struct {
|
type tracerHandler struct {
|
||||||
@ -59,17 +58,15 @@ func (h *tracerHandler) checkStat(ctx *ptracer.Context, addr uint) ptracer.Trace
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *tracerHandler) Handle(ctx *ptracer.Context) ptracer.TraceAction {
|
func (h *tracerHandler) Handle(ctx *ptracer.Context) ptracer.TraceAction {
|
||||||
var (
|
syscallNo := ctx.SyscallNo()
|
||||||
action ptracer.TraceAction
|
syscallName, err := libseccomp.ToSyscallName(syscallNo)
|
||||||
syscallNo = ctx.SyscallNo()
|
h.Debug("syscall:", syscallNo, syscallName, err)
|
||||||
syscallName, err = libseccomp.ToSyscallName(syscallNo)
|
|
||||||
)
|
|
||||||
h.Debug("syscall: ", syscallNo, syscallName, err)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Debug("invalid syscall no")
|
h.Debug("invalid syscall no")
|
||||||
return ptracer.TraceKill
|
return ptracer.TraceKill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action := ptracer.TraceKill
|
||||||
switch syscallName {
|
switch syscallName {
|
||||||
case "open":
|
case "open":
|
||||||
action = h.checkOpen(ctx, ctx.Arg0(), ctx.Arg1())
|
action = h.checkOpen(ctx, ctx.Arg0(), ctx.Arg1())
|
||||||
@ -105,8 +102,12 @@ func (h *tracerHandler) Handle(ctx *ptracer.Context) ptracer.TraceAction {
|
|||||||
action = h.checkWrite(ctx, ctx.Arg0())
|
action = h.checkWrite(ctx, ctx.Arg0())
|
||||||
case "rename":
|
case "rename":
|
||||||
action = h.checkWrite(ctx, ctx.Arg0())
|
action = h.checkWrite(ctx, ctx.Arg0())
|
||||||
|
|
||||||
default:
|
default:
|
||||||
action = h.Handler.CheckSyscall(syscallName)
|
action = h.Handler.CheckSyscall(syscallName)
|
||||||
|
if h.Unsafe && action == ptracer.TraceKill {
|
||||||
|
action = ptracer.TraceBan
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
@ -120,18 +121,6 @@ func (h *tracerHandler) Handle(ctx *ptracer.Context) ptracer.TraceAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tracerHandler) GetSyscallName(ctx *ptracer.Context) (string, error) {
|
|
||||||
syscallNo := ctx.SyscallNo()
|
|
||||||
return libseccomp.ToSyscallName(syscallNo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *tracerHandler) HandlerDisallow(name string) error {
|
|
||||||
if !h.Unsafe {
|
|
||||||
return runner.StatusDisallowedSyscall
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func softBanSyscall(ctx *ptracer.Context) ptracer.TraceAction {
|
func softBanSyscall(ctx *ptracer.Context) ptracer.TraceAction {
|
||||||
ctx.SetReturnValue(-int(BanRet))
|
ctx.SetReturnValue(-int(BanRet))
|
||||||
return ptracer.TraceBan
|
return ptracer.TraceBan
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user