From 2ee6d1e8b6cf6a1e6009b71844f4fa2325d824a1 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Mon, 24 Aug 2015 14:30:45 -0400 Subject: [PATCH] Connect Seccomp configuration in Spec to configuration in Libcontainer Signed-off-by: Matthew Heon --- libcontainer/seccomp/config.go | 53 +++++++++++++++++++++++++++ spec.go | 66 ++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 libcontainer/seccomp/config.go diff --git a/libcontainer/seccomp/config.go b/libcontainer/seccomp/config.go new file mode 100644 index 000000000..5acf06685 --- /dev/null +++ b/libcontainer/seccomp/config.go @@ -0,0 +1,53 @@ +package seccomp + +import ( + "fmt" + + "github.com/opencontainers/runc/libcontainer/configs" +) + +// ConvertStringToOperator converts a string into a Seccomp comparison operator. +// Comparison operators use the names they are assigned by Libseccomp's header. +// Attempting to convert a string that is not a valid operator results in an +// error. +func ConvertStringToOperator(in string) (configs.Operator, error) { + switch in { + case "SCMP_CMP_NE": + return configs.NotEqualTo, nil + case "SCMP_CMP_LT": + return configs.LessThan, nil + case "SCMP_CMP_LE": + return configs.LessThanOrEqualTo, nil + case "SCMP_CMP_EQ": + return configs.EqualTo, nil + case "SCMP_CMP_GE": + return configs.GreaterThan, nil + case "SCMP_CMP_GT": + return configs.GreaterThanOrEqualTo, nil + case "SCMP_CMP_MASKED_EQ": + return configs.MaskEqualTo, nil + default: + return 0, fmt.Errorf("string %s is not a valid operator for seccomp", in) + } +} + +// ConvertStringToAction converts a string into a Seccomp rule match action. +// Actions use the named they are assigned in Libseccomp's header, though some +// (notable, SCMP_ACT_TRACE) are not available in this implementation and will +// return errors. +// Attempting to convert a string that is not a valid action results in an +// error. +func ConvertStringToAction(in string) (configs.Action, error) { + switch in { + case "SCMP_ACT_KILL": + return configs.Kill, nil + case "SCMP_ACT_ERRNO": + return configs.Errno, nil + case "SCMP_ACT_TRAP": + return configs.Trap, nil + case "SCMP_ACT_ALLOW": + return configs.Allow, nil + default: + return 0, fmt.Errorf("string %s is not a valid action for seccomp", in) + } +} diff --git a/spec.go b/spec.go index f0e0c4491..8f4c88099 100644 --- a/spec.go +++ b/spec.go @@ -15,6 +15,7 @@ import ( "github.com/codegangsta/cli" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" + "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/specs" ) @@ -180,6 +181,10 @@ var specCommand = cli.Command{ Swappiness: -1, }, }, + Seccomp: specs.Seccomp{ + DefaultAction: "SCMP_ACT_ALLOW", + Syscalls: []*specs.Syscall{}, + }, }, } data, err := json.MarshalIndent(&spec, "", "\t") @@ -282,6 +287,11 @@ func createLibcontainerConfig(cgroupName string, spec *specs.LinuxSpec) (*config "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", } } + seccomp, err := setupSeccomp(&spec.Linux.Seccomp) + if err != nil { + return nil, err + } + config.Seccomp = seccomp config.Sysctl = spec.Linux.Sysctl config.ProcessLabel = spec.Linux.SelinuxProcessLabel config.AppArmorProfile = spec.Linux.ApparmorProfile @@ -470,3 +480,59 @@ func parseMountOptions(options string) (int, string) { } return flag, strings.Join(data, ",") } + +func setupSeccomp(config *specs.Seccomp) (*configs.Seccomp, error) { + if config == nil { + return nil, nil + } + + // No default action specified, no syscalls listed, assume seccomp disabled + if config.DefaultAction == "" && len(config.Syscalls) == 0 { + return nil, nil + } + + newConfig := new(configs.Seccomp) + newConfig.Syscalls = []*configs.Syscall{} + + // Convert default action from string representation + newDefaultAction, err := seccomp.ConvertStringToAction(string(config.DefaultAction)) + if err != nil { + return nil, err + } + newConfig.DefaultAction = newDefaultAction + + // Loop through all syscall blocks and convert them to libcontainer format + for _, call := range config.Syscalls { + newAction, err := seccomp.ConvertStringToAction(string(call.Action)) + if err != nil { + return nil, err + } + + newCall := configs.Syscall{ + Name: call.Name, + Action: newAction, + Args: []*configs.Arg{}, + } + + // Loop through all the arguments of the syscall and convert them + for _, arg := range call.Args { + newOp, err := seccomp.ConvertStringToOperator(string(arg.Op)) + if err != nil { + return nil, err + } + + newArg := configs.Arg{ + Index: arg.Index, + Value: arg.Value, + ValueTwo: arg.ValueTwo, + Op: newOp, + } + + newCall.Args = append(newCall.Args, &newArg) + } + + newConfig.Syscalls = append(newConfig.Syscalls, &newCall) + } + + return newConfig, nil +}