51
51
patchMounts string
52
52
patchPorts string
53
53
patchIsolators string
54
+ patchSeccompMode string
55
+ patchSeccompSet string
54
56
55
57
catPrettyPrint bool
56
58
69
71
[--ports=query,protocol=tcp,port=8080[:query2,...]]
70
72
[--supplementary-groups=gid1,gid2,...]
71
73
[--isolators=resource/cpu,request=50m,limit=100m[:resource/memory,...]]
74
+ [--seccomp-mode=remove|retain[,errno=EPERM]]
75
+ [--seccomp-set=syscall1,syscall2,...]]
72
76
[--replace]
73
77
INPUT_ACI_FILE
74
78
[OUTPUT_ACI_FILE]` ,
@@ -99,6 +103,8 @@ func init() {
99
103
cmdPatchManifest .Flags .StringVar (& patchMounts , "mounts" , "" , "Replace mount points" )
100
104
cmdPatchManifest .Flags .StringVar (& patchPorts , "ports" , "" , "Replace ports" )
101
105
cmdPatchManifest .Flags .StringVar (& patchIsolators , "isolators" , "" , "Replace isolators" )
106
+ cmdPatchManifest .Flags .StringVar (& patchSeccompMode , "seccomp-mode" , "" , "Enable and configure seccomp isolator" )
107
+ cmdPatchManifest .Flags .StringVar (& patchSeccompSet , "seccomp-set" , "" , "Set of syscalls for seccomp isolator enforcing" )
102
108
103
109
cmdCatManifest .Flags .BoolVar (& catPrettyPrint , "pretty-print" , false , "Print with better style" )
104
110
}
@@ -211,7 +217,11 @@ func patchManifest(im *schema.ImageManifest) error {
211
217
if err != nil {
212
218
return fmt .Errorf ("cannot parse capability %q: %v" , patchCaps , err )
213
219
}
214
- app .Isolators = append (app .Isolators , caps .AsIsolator ())
220
+ isolator , err = caps .AsIsolator ()
221
+ if err != nil {
222
+ return err
223
+ }
224
+ app .Isolators = append (app .Isolators , * isolator )
215
225
}
216
226
if patchRevokeCaps != "" {
217
227
isolator := app .Isolators .GetByName (types .LinuxCapabilitiesRevokeSetName )
@@ -225,7 +235,11 @@ func patchManifest(im *schema.ImageManifest) error {
225
235
if err != nil {
226
236
return fmt .Errorf ("cannot parse capability %q: %v" , patchRevokeCaps , err )
227
237
}
228
- app .Isolators = append (app .Isolators , caps .AsIsolator ())
238
+ isolator , err = caps .AsIsolator ()
239
+ if err != nil {
240
+ return err
241
+ }
242
+ app .Isolators = append (app .Isolators , * isolator )
229
243
}
230
244
231
245
if patchMounts != "" {
@@ -250,6 +264,25 @@ func patchManifest(im *schema.ImageManifest) error {
250
264
}
251
265
}
252
266
267
+ // Parse seccomp args and override existing seccomp isolators
268
+ if patchSeccompMode != "" {
269
+ seccomp , err := parseSeccompArgs (patchSeccompMode , patchSeccompSet )
270
+ if err != nil {
271
+ return err
272
+ }
273
+ seccompIsolator , err := seccomp .AsIsolator ()
274
+ if err != nil {
275
+ return err
276
+ }
277
+ seccompReps := []types.ACIdentifier {types .LinuxSeccompRemoveSetName , types .LinuxSeccompRetainSetName }
278
+ _ , err = app .Isolators .ReplaceIsolatorsByName (* seccompIsolator , seccompReps )
279
+ if err != nil {
280
+ return err
281
+ }
282
+ } else if patchSeccompSet != "" {
283
+ return fmt .Errorf ("--seccomp-set specified without --seccomp-mode" )
284
+ }
285
+
253
286
if patchIsolators != "" {
254
287
isolators := strings .Split (patchIsolators , ":" )
255
288
for _ , is := range isolators {
@@ -260,14 +293,16 @@ func patchManifest(im *schema.ImageManifest) error {
260
293
261
294
_ , ok := types .ResourceIsolatorNames [name ]
262
295
263
- if name == types .LinuxNoNewPrivilegesName {
296
+ switch name {
297
+ case types .LinuxNoNewPrivilegesName :
264
298
ok = true
265
299
kv := strings .Split (is , "," )
266
300
if len (kv ) != 2 {
267
301
return fmt .Errorf ("isolator %s: invalid format" , name )
268
302
}
269
-
270
303
isolatorStr = fmt .Sprintf (`{ "name": "%s", "value": %s }` , name , kv [1 ])
304
+ case types .LinuxSeccompRemoveSetName , types .LinuxSeccompRetainSetName :
305
+ ok = false
271
306
}
272
307
273
308
if ! ok {
@@ -284,6 +319,47 @@ func patchManifest(im *schema.ImageManifest) error {
284
319
return nil
285
320
}
286
321
322
+ // parseSeccompArgs parses seccomp mode and set CLI flags, preparing an
323
+ // appropriate seccomp isolator.
324
+ func parseSeccompArgs (patchSeccompMode string , patchSeccompSet string ) (types.AsIsolator , error ) {
325
+ // Parse mode flag and additional keyed arguments.
326
+ var errno , mode string
327
+ args := strings .Split (patchSeccompMode , "," )
328
+ for _ , a := range args {
329
+ kv := strings .Split (a , "=" )
330
+ switch len (kv ) {
331
+ case 1 :
332
+ // mode, either "remove" or "retain"
333
+ mode = kv [0 ]
334
+ case 2 :
335
+ // k=v argument, only "errno" allowed for now
336
+ if kv [0 ] == "errno" {
337
+ errno = kv [1 ]
338
+ } else {
339
+ return nil , fmt .Errorf ("invalid seccomp-mode optional argument: %s" , a )
340
+ }
341
+ default :
342
+ return nil , fmt .Errorf ("cannot parse seccomp-mode argument: %s" , a )
343
+ }
344
+ }
345
+
346
+ // Instantiate an Isolator with the content specified by the --seccomp-set parameter.
347
+ var err error
348
+ var seccomp types.AsIsolator
349
+ switch mode {
350
+ case "remove" :
351
+ seccomp , err = types .NewLinuxSeccompRemoveSet (errno , strings .Split (patchSeccompSet , "," )... )
352
+ case "retain" :
353
+ seccomp , err = types .NewLinuxSeccompRetainSet (errno , strings .Split (patchSeccompSet , "," )... )
354
+ default :
355
+ err = fmt .Errorf ("unknown seccomp mode %s" , mode )
356
+ }
357
+ if err != nil {
358
+ return nil , fmt .Errorf ("cannot parse seccomp isolator: %s" , err )
359
+ }
360
+ return seccomp , nil
361
+ }
362
+
287
363
// extractManifest iterates over the tar reader and locate the manifest. Once
288
364
// located, the manifest can be printed, replaced or patched.
289
365
func extractManifest (tr * tar.Reader , tw * tar.Writer , printManifest bool , newManifest []byte ) error {
0 commit comments