Browse code

plugins: linux capabilities and device creation

In the plugin manifest, Capabilities has been moved to
Linux.Capabilities to avoid confusion with Interface.Types[i].Capability

A DeviceCreation boolean has also been added to the manifest. This could
be changed in the future to be specific to a major number.

Signed-off-by: Tibor Vass <tibor@docker.com>

Tibor Vass authored on 2016/09/10 01:27:53
Showing 3 changed files
... ...
@@ -1311,9 +1311,10 @@ definitions:
1311 1311
           - Entrypoint
1312 1312
           - Workdir
1313 1313
           - Network
1314
-          - Capabilities
1314
+          - Linux
1315 1315
           - Mounts
1316 1316
           - Devices
1317
+          - DeviceCreation
1317 1318
           - Env
1318 1319
           - Args
1319 1320
         properties:
... ...
@@ -1361,10 +1362,15 @@ definitions:
1361 1361
               Type:
1362 1362
                 x-nullable: false
1363 1363
                 type: "string"
1364
-          Capabilities:
1365
-            type: "array"
1366
-            items:
1367
-              type: "string"
1364
+          Linux:
1365
+            type: "object"
1366
+            x-nullable: false
1367
+            required: [Capabilities]
1368
+            properties:
1369
+              Capabilities:
1370
+                type: "array"
1371
+                items:
1372
+                  type: "string"
1368 1373
           Mounts:
1369 1374
             type: "array"
1370 1375
             items:
... ...
@@ -1373,6 +1379,9 @@ definitions:
1373 1373
             type: "array"
1374 1374
             items:
1375 1375
               $ref: "#/definitions/PluginDevice"
1376
+          DeviceCreation:
1377
+            type: "boolean"
1378
+            x-nullable: false
1376 1379
           Env:
1377 1380
             type: "array"
1378 1381
             items:
... ...
@@ -39,14 +39,14 @@ type PluginConfig struct {
39 39
 	// Required: true
40 40
 	Args PluginConfigArgs `json:"Args"`
41 41
 
42
-	// capabilities
43
-	// Required: true
44
-	Capabilities []string `json:"Capabilities"`
45
-
46 42
 	// description
47 43
 	// Required: true
48 44
 	Description string `json:"Description"`
49 45
 
46
+	// device creation
47
+	// Required: true
48
+	DeviceCreation bool `json:"DeviceCreation"`
49
+
50 50
 	// devices
51 51
 	// Required: true
52 52
 	Devices []PluginDevice `json:"Devices"`
... ...
@@ -67,6 +67,10 @@ type PluginConfig struct {
67 67
 	// Required: true
68 68
 	Interface PluginConfigInterface `json:"Interface"`
69 69
 
70
+	// linux
71
+	// Required: true
72
+	Linux PluginConfigLinux `json:"Linux"`
73
+
70 74
 	// mounts
71 75
 	// Required: true
72 76
 	Mounts []PluginMount `json:"Mounts"`
... ...
@@ -117,6 +121,15 @@ type PluginConfigInterface struct {
117 117
 	Types []PluginInterfaceType `json:"Types"`
118 118
 }
119 119
 
120
+// PluginConfigLinux plugin config linux
121
+// swagger:model PluginConfigLinux
122
+type PluginConfigLinux struct {
123
+
124
+	// capabilities
125
+	// Required: true
126
+	Capabilities []string `json:"Capabilities"`
127
+}
128
+
120 129
 // PluginConfigNetwork plugin config network
121 130
 // swagger:model PluginConfigNetwork
122 131
 type PluginConfigNetwork struct {
... ...
@@ -242,11 +242,18 @@ func (p *Plugin) ComputePrivileges() types.PluginPrivileges {
242 242
 			})
243 243
 		}
244 244
 	}
245
-	if len(m.Capabilities) > 0 {
245
+	if m.DeviceCreation {
246
+		privileges = append(privileges, types.PluginPrivilege{
247
+			Name:        "device-creation",
248
+			Description: "",
249
+			Value:       []string{"true"},
250
+		})
251
+	}
252
+	if len(m.Linux.Capabilities) > 0 {
246 253
 		privileges = append(privileges, types.PluginPrivilege{
247 254
 			Name:        "capabilities",
248 255
 			Description: "",
249
-			Value:       m.Capabilities,
256
+			Value:       m.Linux.Capabilities,
250 257
 		})
251 258
 	}
252 259
 	return privileges
... ...
@@ -292,6 +299,11 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
292 292
 		Readonly: false, // TODO: all plugins should be readonly? settable in config?
293 293
 	}
294 294
 
295
+	if p.PluginObj.Config.DeviceCreation {
296
+		rwm := "rwm"
297
+		s.Linux.Resources.Devices = []specs.DeviceCgroup{{Allow: true, Access: &rwm}}
298
+	}
299
+
295 300
 	mounts := append(p.PluginObj.Settings.Mounts, types.PluginMount{
296 301
 		Source:      &p.RuntimeSourcePath,
297 302
 		Destination: defaultPluginRuntimeDestination,
... ...
@@ -322,6 +334,12 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
322 322
 		s.Mounts = append(s.Mounts, m)
323 323
 	}
324 324
 
325
+	for i, m := range s.Mounts {
326
+		if strings.HasPrefix(m.Destination, "/dev/") && true { // TODO: && user specified /dev
327
+			s.Mounts = append(s.Mounts[:i], s.Mounts[i+1:]...)
328
+		}
329
+	}
330
+
325 331
 	envs := make([]string, 1, len(p.PluginObj.Settings.Env)+1)
326 332
 	envs[0] = "PATH=" + system.DefaultPathEnv
327 333
 	envs = append(envs, p.PluginObj.Settings.Env...)
... ...
@@ -331,12 +349,14 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
331 331
 	if len(cwd) == 0 {
332 332
 		cwd = "/"
333 333
 	}
334
-	s.Process = specs.Process{
335
-		Terminal: false,
336
-		Args:     args,
337
-		Cwd:      cwd,
338
-		Env:      envs,
339
-	}
334
+	s.Process.Terminal = false
335
+	s.Process.Args = args
336
+	s.Process.Cwd = cwd
337
+	s.Process.Env = envs
338
+
339
+	// TODO: what about duplicates?
340
+	// TODO: Should not need CAP_ prefix in manifest?
341
+	s.Process.Capabilities = append(s.Process.Capabilities, p.PluginObj.Config.Linux.Capabilities...)
340 342
 
341 343
 	return &s, nil
342 344
 }