Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Commit

Permalink
Merge pull request #613 from crosbymichael/seccomp-args
Browse files Browse the repository at this point in the history
Golang seccomp package
  • Loading branch information
Mrunal Patel committed Jun 9, 2015
2 parents ce1f2f1 + 5edcda9 commit 2045026
Show file tree
Hide file tree
Showing 13 changed files with 920 additions and 26 deletions.
39 changes: 39 additions & 0 deletions configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,40 @@ type IDMap struct {
Size int `json:"size"`
}

type Seccomp struct {
Syscalls []*Syscall `json:"syscalls"`
}

type Action int

const (
Kill Action = iota - 3
Trap
Allow
)

type Operator int

const (
EqualTo Operator = iota
NotEqualTo
GreatherThan
LessThan
MaskEqualTo
)

type Arg struct {
Index int `json:"index"`
Value uint32 `json:"value"`
Op Operator `json:"op"`
}

type Syscall struct {
Value int `json:"value"`
Action Action `json:"action"`
Args []*Arg `json:"args"`
}

// TODO Windows. Many of these fields should be factored out into those parts
// which are common across platforms, and those which are platform specific.

Expand Down Expand Up @@ -104,4 +138,9 @@ type Config struct {
// SystemProperties is a map of properties and their values. It is the equivalent of using
// sysctl -w my.property.name value in Linux.
SystemProperties map[string]string `json:"system_properties"`

// Seccomp allows actions to be taken whenever a syscall is made within the container.
// By default, all syscalls are allowed with actions to allow, trap, kill, or return an errno
// can be specified on a per syscall basis.
Seccomp *Seccomp `json:"seccomp"`
}
59 changes: 59 additions & 0 deletions init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/docker/libcontainer/cgroups"
"github.com/docker/libcontainer/configs"
"github.com/docker/libcontainer/netlink"
"github.com/docker/libcontainer/seccomp"
"github.com/docker/libcontainer/system"
"github.com/docker/libcontainer/user"
"github.com/docker/libcontainer/utils"
Expand Down Expand Up @@ -259,3 +260,61 @@ func killCgroupProcesses(m cgroups.Manager) error {
}
return nil
}

func finalizeSeccomp(config *initConfig) error {
if config.Config.Seccomp == nil {
return nil
}
context := seccomp.New()
for _, s := range config.Config.Seccomp.Syscalls {
ss := &seccomp.Syscall{
Value: uint32(s.Value),
Action: seccompAction(s.Action),
}
if len(s.Args) > 0 {
ss.Args = seccompArgs(s.Args)
}
context.Add(ss)
}
return context.Load()
}

func seccompAction(a configs.Action) seccomp.Action {
switch a {
case configs.Kill:
return seccomp.Kill
case configs.Trap:
return seccomp.Trap
case configs.Allow:
return seccomp.Allow
}
return seccomp.Error(syscall.Errno(int(a)))
}

func seccompArgs(args []*configs.Arg) seccomp.Args {
var sa []seccomp.Arg
for _, a := range args {
sa = append(sa, seccomp.Arg{
Index: uint32(a.Index),
Op: seccompOperator(a.Op),
Value: uint(a.Value),
})
}
return seccomp.Args{sa}
}

func seccompOperator(o configs.Operator) seccomp.Operator {
switch o {
case configs.EqualTo:
return seccomp.EqualTo
case configs.NotEqualTo:
return seccomp.NotEqualTo
case configs.GreatherThan:
return seccomp.GreatherThan
case configs.LessThan:
return seccomp.LessThan
case configs.MaskEqualTo:
return seccomp.MaskEqualTo
}
return 0
}
24 changes: 24 additions & 0 deletions integration/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -714,3 +714,27 @@ func TestSystemProperties(t *testing.T) {
t.Fatalf("kernel.shmmni property expected to be 8192, but is %s", shmmniOutput)
}
}

func TestSeccompNoChown(t *testing.T) {
if testing.Short() {
return
}
rootfs, err := newRootfs()
if err != nil {
t.Fatal(err)
}
defer remove(rootfs)
config := newTemplateConfig(rootfs)
config.Seccomp = &configs.Seccomp{}
config.Seccomp.Syscalls = append(config.Seccomp.Syscalls, &configs.Syscall{
Value: syscall.SYS_CHOWN,
Action: configs.Action(syscall.EPERM),
})
buffers, _, err := runContainer(config, "", "/bin/sh", "-c", "chown 1:1 /tmp")
if err == nil {
t.Fatal("running chown in a container should fail")
}
if s := buffers.String(); !strings.Contains(s, "not permitted") {
t.Fatalf("running chown should result in an EPERM but got %q", s)
}
}
6 changes: 3 additions & 3 deletions integration/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,19 @@ func runContainer(config *configs.Config, console string, args ...string) (buffe

err = container.Start(process)
if err != nil {
return nil, -1, err
return buffers, -1, err
}
ps, err := process.Wait()
if err != nil {
return nil, -1, err
return buffers, -1, err
}
status := ps.Sys().(syscall.WaitStatus)
if status.Exited() {
exitCode = status.ExitStatus()
} else if status.Signaled() {
exitCode = -int(status.Signal())
} else {
return nil, -1, err
return buffers, -1, err
}
return
}
53 changes: 32 additions & 21 deletions nsinit/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,33 @@ import (
const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV

var createFlags = []cli.Flag{
cli.IntFlag{Name: "parent-death-signal", Usage: "set the signal that will be delivered to the process in case the parent dies"},
cli.BoolFlag{Name: "cgroup", Usage: "mount the cgroup data for the container"},
cli.BoolFlag{Name: "read-only", Usage: "set the container's rootfs as read-only"},
cli.StringSliceFlag{Name: "bind", Value: &cli.StringSlice{}, Usage: "add bind mounts to the container"},
cli.StringSliceFlag{Name: "tmpfs", Value: &cli.StringSlice{}, Usage: "add tmpfs mounts to the container"},
cli.IntFlag{Name: "cpushares", Usage: "set the cpushares for the container"},
cli.IntFlag{Name: "memory-limit", Usage: "set the memory limit for the container"},
cli.IntFlag{Name: "memory-swap", Usage: "set the memory swap limit for the container"},
cli.IntFlag{Name: "parent-death-signal", Usage: "set the signal that will be delivered to the process in case the parent dies"},
cli.IntFlag{Name: "userns-root-uid", Usage: "set the user namespace root uid"},
cli.IntFlag{Name: "veth-mtu", Usage: "veth mtu"},
cli.StringFlag{Name: "apparmor-profile", Usage: "set the apparmor profile"},
cli.StringFlag{Name: "cpuset-cpus", Usage: "set the cpuset cpus"},
cli.StringFlag{Name: "cpuset-mems", Usage: "set the cpuset mems"},
cli.StringFlag{Name: "apparmor-profile", Usage: "set the apparmor profile"},
cli.StringFlag{Name: "process-label", Usage: "set the process label"},
cli.StringFlag{Name: "mount-label", Usage: "set the mount label"},
cli.StringFlag{Name: "rootfs", Usage: "set the rootfs"},
cli.IntFlag{Name: "userns-root-uid", Usage: "set the user namespace root uid"},
cli.StringFlag{Name: "hostname", Value: "nsinit", Usage: "hostname value for the container"},
cli.StringFlag{Name: "net", Value: "", Usage: "network namespace"},
cli.StringFlag{Name: "ipc", Value: "", Usage: "ipc namespace"},
cli.StringFlag{Name: "mnt", Value: "", Usage: "mount namespace"},
cli.StringFlag{Name: "mount-label", Usage: "set the mount label"},
cli.StringFlag{Name: "net", Value: "", Usage: "network namespace"},
cli.StringFlag{Name: "pid", Value: "", Usage: "pid namespace"},
cli.StringFlag{Name: "process-label", Usage: "set the process label"},
cli.StringFlag{Name: "rootfs", Usage: "set the rootfs"},
cli.StringFlag{Name: "security", Value: "", Usage: "set the security profile (high, medium, low)"},
cli.StringFlag{Name: "uts", Value: "", Usage: "uts namespace"},
cli.StringFlag{Name: "mnt", Value: "", Usage: "mount namespace"},
cli.StringFlag{Name: "veth-bridge", Usage: "veth bridge"},
cli.StringFlag{Name: "veth-address", Usage: "veth ip address"},
cli.StringFlag{Name: "veth-bridge", Usage: "veth bridge"},
cli.StringFlag{Name: "veth-gateway", Usage: "veth gateway address"},
cli.IntFlag{Name: "veth-mtu", Usage: "veth mtu"},
cli.BoolFlag{Name: "cgroup", Usage: "mount the cgroup data for the container"},
cli.StringSliceFlag{Name: "bind", Value: &cli.StringSlice{}, Usage: "add bind mounts to the container"},
cli.StringSliceFlag{Name: "sysctl", Value: &cli.StringSlice{}, Usage: "set system properties in the container"},
cli.StringSliceFlag{Name: "tmpfs", Value: &cli.StringSlice{}, Usage: "add tmpfs mounts to the container"},
}

var configCommand = cli.Command{
Expand Down Expand Up @@ -203,6 +204,24 @@ func modify(config *configs.Config, context *cli.Context) {
Device: "cgroup",
})
}
modifySecurityProfile(context, config)
}

func modifySecurityProfile(context *cli.Context, config *configs.Config) {
profileName := context.String("security")
if profileName == "" {
return
}
profile := profiles[profileName]
if profile == nil {
logrus.Fatalf("invalid profile name %q", profileName)
}
config.Rlimits = profile.Rlimits
config.Capabilities = profile.Capabilities
config.Seccomp = profile.Seccomp
config.AppArmorProfile = profile.ApparmorProfile
config.MountLabel = profile.MountLabel
config.ProcessLabel = profile.ProcessLabel
}

func getTemplate() *configs.Config {
Expand Down Expand Up @@ -290,13 +309,5 @@ func getTemplate() *configs.Config {
Flags: defaultMountFlags | syscall.MS_RDONLY,
},
},
Rlimits: []configs.Rlimit{
{
Type: syscall.RLIMIT_NOFILE,
Hard: 1024,
Soft: 1024,
},
},
}

}
Loading

0 comments on commit 2045026

Please sign in to comment.