Browse code

Allow caps to be toggled in native driver with plugin flag Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/03/21 09:10:24
Showing 4 changed files
... ...
@@ -27,7 +27,9 @@ func DropCapabilities(container *libcontainer.Container) error {
27 27
 func getCapabilitiesMask(container *libcontainer.Container) []capability.Cap {
28 28
 	drop := []capability.Cap{}
29 29
 	for _, c := range container.CapabilitiesMask {
30
-		drop = append(drop, c.Value)
30
+		if !c.Enabled {
31
+			drop = append(drop, c.Value)
32
+		}
31 33
 	}
32 34
 	return drop
33 35
 }
... ...
@@ -18,21 +18,21 @@ var (
18 18
 	namespaceList = Namespaces{}
19 19
 
20 20
 	capabilityList = Capabilities{
21
-		{Key: "SETPCAP", Value: capability.CAP_SETPCAP, Enabled: true},
22
-		{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE, Enabled: true},
23
-		{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO, Enabled: true},
24
-		{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT, Enabled: true},
25
-		{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN, Enabled: true},
26
-		{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE, Enabled: true},
27
-		{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE, Enabled: true},
28
-		{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME, Enabled: true},
29
-		{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG, Enabled: true},
30
-		{Key: "MKNOD", Value: capability.CAP_MKNOD, Enabled: true},
31
-		{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE, Enabled: true},
32
-		{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL, Enabled: true},
33
-		{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE, Enabled: true},
34
-		{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN, Enabled: true},
35
-		{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN, Enabled: true},
21
+		{Key: "SETPCAP", Value: capability.CAP_SETPCAP, Enabled: false},
22
+		{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE, Enabled: false},
23
+		{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO, Enabled: false},
24
+		{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT, Enabled: false},
25
+		{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN, Enabled: false},
26
+		{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE, Enabled: false},
27
+		{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE, Enabled: false},
28
+		{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME, Enabled: false},
29
+		{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG, Enabled: false},
30
+		{Key: "MKNOD", Value: capability.CAP_MKNOD, Enabled: false},
31
+		{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE, Enabled: false},
32
+		{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL, Enabled: false},
33
+		{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE, Enabled: false},
34
+		{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN, Enabled: false},
35
+		{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN, Enabled: false},
36 36
 	}
37 37
 )
38 38
 
... ...
@@ -86,7 +86,8 @@ func (c *Capability) String() string {
86 86
 func GetCapability(key string) *Capability {
87 87
 	for _, capp := range capabilityList {
88 88
 		if capp.Key == key {
89
-			return capp
89
+			cpy := *capp
90
+			return &cpy
90 91
 		}
91 92
 	}
92 93
 	return nil
... ...
@@ -95,10 +96,14 @@ func GetCapability(key string) *Capability {
95 95
 // Contains returns true if the specified Capability is
96 96
 // in the slice
97 97
 func (c Capabilities) Contains(capp string) bool {
98
+	return c.Get(capp) != nil
99
+}
100
+
101
+func (c Capabilities) Get(capp string) *Capability {
98 102
 	for _, cap := range c {
99 103
 		if cap.Key == capp {
100
-			return true
104
+			return cap
101 105
 		}
102 106
 	}
103
-	return false
107
+	return nil
104 108
 }
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"github.com/dotcloud/docker/pkg/libcontainer"
7 7
 	"github.com/dotcloud/docker/runtime/execdriver"
8 8
 	"os"
9
+	"strings"
9 10
 )
10 11
 
11 12
 // createContainer populates and configures the container type with the
... ...
@@ -63,9 +64,39 @@ func createContainer(c *execdriver.Command) *libcontainer.Container {
63 63
 		container.Mounts = append(container.Mounts, libcontainer.Mount{m.Source, m.Destination, m.Writable, m.Private})
64 64
 	}
65 65
 
66
+	configureCustomOptions(container, c.Config["native"])
67
+
66 68
 	return container
67 69
 }
68 70
 
71
+// configureCustomOptions takes string commands from the user and allows modification of the
72
+// container's default configuration.
73
+//
74
+// format: <key> <value>
75
+// i.e: cap +MKNOD cap -NET_ADMIN
76
+// i.e: cgroup devices.allow *:*
77
+func configureCustomOptions(container *libcontainer.Container, opts []string) {
78
+	for _, opt := range opts {
79
+		parts := strings.Split(strings.TrimSpace(opt), " ")
80
+		switch parts[0] {
81
+		case "cap":
82
+			value := strings.TrimSpace(parts[1])
83
+			c := container.CapabilitiesMask.Get(value[1:])
84
+			if c == nil {
85
+				continue
86
+			}
87
+			switch value[0] {
88
+			case '-':
89
+				c.Enabled = false
90
+			case '+':
91
+				c.Enabled = true
92
+			default:
93
+				// do error here
94
+			}
95
+		}
96
+	}
97
+}
98
+
69 99
 // getDefaultTemplate returns the docker default for
70 100
 // the libcontainer configuration file
71 101
 func getDefaultTemplate() *libcontainer.Container {
... ...
@@ -75,9 +75,6 @@ func NewDriver(root, initPath string) (*driver, error) {
75 75
 }
76 76
 
77 77
 func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
78
-	if err := d.validateCommand(c); err != nil {
79
-		return -1, err
80
-	}
81 78
 	var (
82 79
 		term        nsinit.Terminal
83 80
 		container   = createContainer(c)
... ...
@@ -181,15 +178,6 @@ func (d *driver) removeContainerRoot(id string) error {
181 181
 	return os.RemoveAll(filepath.Join(d.root, id))
182 182
 }
183 183
 
184
-func (d *driver) validateCommand(c *execdriver.Command) error {
185
-	// we need to check the Config of the command to make sure that we
186
-	// do not have any of the lxc-conf variables
187
-	for _, conf := range c.Config["native"] {
188
-		log.Println(conf)
189
-	}
190
-	return nil
191
-}
192
-
193 184
 func getEnv(key string, env []string) string {
194 185
 	for _, pair := range env {
195 186
 		parts := strings.Split(pair, "=")