Skip to content

Commit

Permalink
Update runtime spec to 1.0.0.rc5
Browse files Browse the repository at this point in the history
Signed-off-by: Mrunal Patel <[email protected]>
  • Loading branch information
mrunalp committed Mar 15, 2017
1 parent 31980a5 commit 4f9cb13
Show file tree
Hide file tree
Showing 21 changed files with 436 additions and 217 deletions.
8 changes: 7 additions & 1 deletion exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,13 @@ func getProcess(context *cli.Context, bundle string) (*specs.Process, error) {
p.SelinuxLabel = l
}
if caps := context.StringSlice("cap"); len(caps) > 0 {
p.Capabilities = caps
for _, c := range caps {
p.Capabilities.Bounding = append(p.Capabilities.Bounding, c)
p.Capabilities.Inheritable = append(p.Capabilities.Inheritable, c)
p.Capabilities.Effective = append(p.Capabilities.Effective, c)
p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
}
}
// append the passed env variables
p.Env = append(p.Env, context.StringSlice("env")...)
Expand Down
85 changes: 65 additions & 20 deletions libcontainer/capabilities_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"strings"

"github.com/opencontainers/runc/libcontainer/configs"
"github.com/syndtr/gocapability/capability"
)

Expand All @@ -28,40 +29,84 @@ func init() {
}
}

func newCapWhitelist(caps []string) (*whitelist, error) {
l := []capability.Cap{}
for _, c := range caps {
func newContainerCapList(capConfig *configs.Capabilities) (*containerCapabilities, error) {
bounding := []capability.Cap{}
for _, c := range capConfig.Bounding {
v, ok := capabilityMap[c]
if !ok {
return nil, fmt.Errorf("unknown capability %q", c)
}
l = append(l, v)
bounding = append(bounding, v)
}
effective := []capability.Cap{}
for _, c := range capConfig.Effective {
v, ok := capabilityMap[c]
if !ok {
return nil, fmt.Errorf("unknown capability %q", c)
}
effective = append(effective, v)
}
inheritable := []capability.Cap{}
for _, c := range capConfig.Inheritable {
v, ok := capabilityMap[c]
if !ok {
return nil, fmt.Errorf("unknown capability %q", c)
}
inheritable = append(inheritable, v)
}
permitted := []capability.Cap{}
for _, c := range capConfig.Permitted {
v, ok := capabilityMap[c]
if !ok {
return nil, fmt.Errorf("unknown capability %q", c)
}
permitted = append(permitted, v)
}
ambient := []capability.Cap{}
for _, c := range capConfig.Ambient {
v, ok := capabilityMap[c]
if !ok {
return nil, fmt.Errorf("unknown capability %q", c)
}
ambient = append(ambient, v)
}
pid, err := capability.NewPid(os.Getpid())
if err != nil {
return nil, err
}
return &whitelist{
keep: l,
pid: pid,
return &containerCapabilities{
bounding: bounding,
effective: effective,
inheritable: inheritable,
permitted: permitted,
ambient: ambient,
pid: pid,
}, nil
}

type whitelist struct {
pid capability.Capabilities
keep []capability.Cap
type containerCapabilities struct {
pid capability.Capabilities
bounding []capability.Cap
effective []capability.Cap
inheritable []capability.Cap
permitted []capability.Cap
ambient []capability.Cap
}

// dropBoundingSet drops the capability bounding set to those specified in the whitelist.
func (w *whitelist) dropBoundingSet() error {
w.pid.Clear(capability.BOUNDS)
w.pid.Set(capability.BOUNDS, w.keep...)
return w.pid.Apply(capability.BOUNDS)
// ApplyBoundingSet sets the capability bounding set to those specified in the whitelist.
func (c *containerCapabilities) ApplyBoundingSet() error {
c.pid.Clear(capability.BOUNDS)
c.pid.Set(capability.BOUNDS, c.bounding...)
return c.pid.Apply(capability.BOUNDS)
}

// drop drops all capabilities for the current process except those specified in the whitelist.
func (w *whitelist) drop() error {
w.pid.Clear(allCapabilityTypes)
w.pid.Set(allCapabilityTypes, w.keep...)
return w.pid.Apply(allCapabilityTypes)
// Apply sets all the capabilities for the current process in the config.
func (c *containerCapabilities) ApplyCaps() error {
c.pid.Clear(allCapabilityTypes)
c.pid.Set(capability.BOUNDS, c.bounding...)
c.pid.Set(capability.PERMITTED, c.permitted...)
c.pid.Set(capability.INHERITABLE, c.inheritable...)
c.pid.Set(capability.EFFECTIVE, c.effective...)
c.pid.Set(capability.AMBIENT, c.ambient...)
return c.pid.Apply(allCapabilityTypes)
}
17 changes: 15 additions & 2 deletions libcontainer/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ type Config struct {
Namespaces Namespaces `json:"namespaces"`

// Capabilities specify the capabilities to keep when executing the process inside the container
// All capbilities not specified will be dropped from the processes capability mask
Capabilities []string `json:"capabilities"`
// All capabilities not specified will be dropped from the processes capability mask
Capabilities *Capabilities `json:"capabilities"`

// Networks specifies the container's network setup to be created
Networks []*Network `json:"networks"`
Expand Down Expand Up @@ -197,6 +197,19 @@ type Hooks struct {
Poststop []Hook
}

type Capabilities struct {
// Bounding is the set of capabilities checked by the kernel.
Bounding []string
// Effective is the set of capabilities checked by the kernel.
Effective []string
// Inheritable is the capabilities preserved across execve.
Inheritable []string
// Permitted is the limiting superset for effective capabilities.
Permitted []string
// Ambient is the ambient set of capabilities that are kept.
Ambient []string
}

func (hooks *Hooks) UnmarshalJSON(b []byte) error {
var state struct {
Prestart []CommandHook
Expand Down
24 changes: 12 additions & 12 deletions libcontainer/configs/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ func TestMarshalHooksWithUnexpectedType(t *testing.T) {

func TestFuncHookRun(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
Version: "1",
ID: "1",
Pid: 1,
Bundle: "/bundle",
}

fHook := configs.NewFunctionHook(func(s configs.HookState) error {
Expand All @@ -138,10 +138,10 @@ func TestFuncHookRun(t *testing.T) {

func TestCommandHookRun(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
Version: "1",
ID: "1",
Pid: 1,
Bundle: "/bundle",
}
timeout := time.Second

Expand All @@ -161,10 +161,10 @@ func TestCommandHookRun(t *testing.T) {

func TestCommandHookRunTimeout(t *testing.T) {
state := configs.HookState{
Version: "1",
ID: "1",
Pid: 1,
BundlePath: "/bundle",
Version: "1",
ID: "1",
Pid: 1,
Bundle: "/bundle",
}
timeout := (10 * time.Millisecond)

Expand Down
16 changes: 8 additions & 8 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ func (c *linuxContainer) start(process *Process, isInit bool) error {

if c.config.Hooks != nil {
s := configs.HookState{
Version: c.config.Version,
ID: c.id,
Pid: parent.pid(),
BundlePath: utils.SearchLabels(c.config.Labels, "bundle"),
Version: c.config.Version,
ID: c.id,
Pid: parent.pid(),
Bundle: utils.SearchLabels(c.config.Labels, "bundle"),
}
for i, hook := range c.config.Hooks.Poststart {
if err := hook.Run(s); err != nil {
Expand Down Expand Up @@ -1157,10 +1157,10 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
case notify.GetScript() == "setup-namespaces":
if c.config.Hooks != nil {
s := configs.HookState{
Version: c.config.Version,
ID: c.id,
Pid: int(notify.GetPid()),
BundlePath: utils.SearchLabels(c.config.Labels, "bundle"),
Version: c.config.Version,
ID: c.id,
Pid: int(notify.GetPid()),
Bundle: utils.SearchLabels(c.config.Labels, "bundle"),
}
for i, hook := range c.config.Hooks.Prestart {
if err := hook.Run(s); err != nil {
Expand Down
37 changes: 18 additions & 19 deletions libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ type network struct {

// initConfig is used for transferring parameters from Exec() to Init()
type initConfig struct {
Args []string `json:"args"`
Env []string `json:"env"`
Cwd string `json:"cwd"`
Capabilities []string `json:"capabilities"`
ProcessLabel string `json:"process_label"`
AppArmorProfile string `json:"apparmor_profile"`
NoNewPrivileges bool `json:"no_new_privileges"`
User string `json:"user"`
AdditionalGroups []string `json:"additional_groups"`
Config *configs.Config `json:"config"`
Networks []*network `json:"network"`
PassedFilesCount int `json:"passed_files_count"`
ContainerId string `json:"containerid"`
Rlimits []configs.Rlimit `json:"rlimits"`
CreateConsole bool `json:"create_console"`
Args []string `json:"args"`
Env []string `json:"env"`
Cwd string `json:"cwd"`
Capabilities *configs.Capabilities `json:"capabilities"`
ProcessLabel string `json:"process_label"`
AppArmorProfile string `json:"apparmor_profile"`
NoNewPrivileges bool `json:"no_new_privileges"`
User string `json:"user"`
AdditionalGroups []string `json:"additional_groups"`
Config *configs.Config `json:"config"`
Networks []*network `json:"network"`
PassedFilesCount int `json:"passed_files_count"`
ContainerId string `json:"containerid"`
Rlimits []configs.Rlimit `json:"rlimits"`
CreateConsole bool `json:"create_console"`
}

type initer interface {
Expand Down Expand Up @@ -121,12 +121,12 @@ func finalizeNamespace(config *initConfig) error {
if config.Capabilities != nil {
capabilities = config.Capabilities
}
w, err := newCapWhitelist(capabilities)
w, err := newContainerCapList(capabilities)
if err != nil {
return err
}
// drop capabilities in bounding set before changing user
if err := w.dropBoundingSet(); err != nil {
if err := w.ApplyBoundingSet(); err != nil {
return err
}
// preserve existing capabilities while we change users
Expand All @@ -139,8 +139,7 @@ func finalizeNamespace(config *initConfig) error {
if err := system.ClearKeepCaps(); err != nil {
return err
}
// drop all other capabilities
if err := w.drop(); err != nil {
if err := w.ApplyCaps(); err != nil {
return err
}
if config.Cwd != "" {
Expand Down
Loading

0 comments on commit 4f9cb13

Please sign in to comment.