Skip to content

Commit a116901

Browse files
committed
Use seccomp library for adding seccomp configuration flags
Signed-off-by: Grantseltzer <[email protected]>
1 parent 9d3881d commit a116901

File tree

9 files changed

+702
-356
lines changed

9 files changed

+702
-356
lines changed

cmd/ocitools/generate.go

Lines changed: 246 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"errors"
45
"fmt"
56
"os"
67
"runtime"
@@ -51,11 +52,14 @@ var generateFlags = []cli.Flag{
5152
cli.StringSliceFlag{Name: "gidmappings", Usage: "add GIDMappings e.g HostID:ContainerID:Size"},
5253
cli.StringSliceFlag{Name: "sysctl", Usage: "add sysctl settings e.g net.ipv4.forward=1"},
5354
cli.StringFlag{Name: "apparmor", Usage: "specifies the the apparmor profile for the container"},
54-
cli.StringFlag{Name: "seccomp-default", Usage: "specifies the the defaultaction of Seccomp syscall restrictions"},
55-
cli.StringSliceFlag{Name: "seccomp-arch", Usage: "specifies Additional architectures permitted to be used for system calls"},
56-
cli.StringSliceFlag{Name: "seccomp-syscalls", Usage: "specifies Additional architectures permitted to be used for system calls, e.g Name:Action:Arg1_index/Arg1_value/Arg1_valuetwo/Arg1_op, Arg2_index/Arg2_value/Arg2_valuetwo/Arg2_op "},
57-
cli.StringSliceFlag{Name: "seccomp-allow", Usage: "specifies syscalls to be added to allowed"},
58-
cli.StringSliceFlag{Name: "seccomp-errno", Usage: "specifies syscalls to be added to list that returns an error"},
55+
cli.BoolFlag{Name: "seccomp-only", Usage: "specifies to export just a seccomp configuration file"},
56+
cli.StringFlag{Name: "seccomp-arch", Value: "amd64,x86,x32", Usage: "specifies additional architectures permitted to be used for system calls"},
57+
cli.StringFlag{Name: "seccomp-default", Value: "errno", Usage: "specifies default action to be used for system calls"},
58+
cli.StringFlag{Name: "seccomp-allow", Usage: "specifies syscalls to respond with allow"},
59+
cli.StringFlag{Name: "seccomp-trap", Usage: "specifies syscalls to respond with trap"},
60+
cli.StringFlag{Name: "seccomp-errno", Usage: "specifies syscalls to respond with errno"},
61+
cli.StringFlag{Name: "seccomp-trace", Usage: "specifies syscalls to respond with trace"},
62+
cli.StringFlag{Name: "seccomp-kill", Usage: "specifies syscalls to respond with kill"},
5963
cli.StringFlag{Name: "template", Usage: "base template to use for creating the configuration"},
6064
cli.StringSliceFlag{Name: "label", Usage: "add annotations to the configuration e.g. key=value"},
6165
}
@@ -86,11 +90,13 @@ var generateCommand = cli.Command{
8690
return err
8791
}
8892

93+
var exportOpts generate.ExportOptions
94+
exportOpts.Seccomp = context.Bool("seccomp-only")
95+
8996
if context.IsSet("output") {
90-
output := context.String("output")
91-
err = specgen.SaveToFile(output)
97+
err = specgen.SaveToFile(context.String("output"), exportOpts)
9298
} else {
93-
err = specgen.Save(os.Stdout)
99+
err = specgen.Save(os.Stdout, exportOpts)
94100
}
95101
if err != nil {
96102
return err
@@ -319,61 +325,262 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
319325
g.AddLinuxGIDMapping(hid, cid, size)
320326
}
321327

322-
var sd string
323-
var sa, ss []string
328+
err := addSeccomp(g, context)
329+
return err
330+
}
324331

325-
if context.IsSet("seccomp-default") {
326-
sd = context.String("seccomp-default")
332+
func setupLinuxNamespaces(context *cli.Context, g *generate.Generator, needsNewUser bool) {
333+
for _, nsName := range generate.Namespaces {
334+
if !context.IsSet(nsName) && !(needsNewUser && nsName == "user") {
335+
continue
336+
}
337+
nsPath := context.String(nsName)
338+
if nsPath == "host" {
339+
g.RemoveLinuxNamespace(nsName)
340+
continue
341+
}
342+
g.AddOrReplaceLinuxNamespace(nsName, nsPath)
327343
}
344+
}
328345

329-
if context.IsSet("seccomp-arch") {
330-
sa = context.StringSlice("seccomp-arch")
346+
func parseIDMapping(idms string) (uint32, uint32, uint32, error) {
347+
idm := strings.Split(idms, ":")
348+
if len(idm) != 3 {
349+
return 0, 0, 0, fmt.Errorf("idmappings error: %s", idms)
331350
}
332351

333-
if context.IsSet("seccomp-syscalls") {
334-
ss = context.StringSlice("seccomp-syscalls")
352+
hid, err := strconv.Atoi(idm[0])
353+
if err != nil {
354+
return 0, 0, 0, err
335355
}
336356

337-
if sd == "" && len(sa) == 0 && len(ss) == 0 {
338-
return nil
357+
cid, err := strconv.Atoi(idm[1])
358+
if err != nil {
359+
return 0, 0, 0, err
339360
}
340361

362+
size, err := strconv.Atoi(idm[2])
363+
if err != nil {
364+
return 0, 0, 0, err
365+
}
366+
367+
return uint32(hid), uint32(cid), uint32(size), nil
368+
}
369+
370+
func parseHook(s string) (string, []string) {
371+
parts := strings.Split(s, ":")
372+
args := []string{}
373+
path := parts[0]
374+
if len(parts) > 1 {
375+
args = parts[1:]
376+
}
377+
return path, args
378+
}
379+
380+
func parseTmpfsMount(s string) (string, []string, error) {
381+
var dest string
382+
var options []string
383+
var err error
384+
385+
parts := strings.Split(s, ":")
386+
if len(parts) == 2 {
387+
dest = parts[0]
388+
options = strings.Split(parts[1], ",")
389+
} else if len(parts) == 1 {
390+
dest = parts[0]
391+
options = []string{"rw", "noexec", "nosuid", "nodev", "size=65536k"}
392+
} else {
393+
err = fmt.Errorf("invalid value for --tmpfs")
394+
}
395+
396+
return dest, options, err
397+
}
398+
399+
func parseBindMount(s string) (string, string, string, error) {
400+
var source, dest string
401+
options := "ro"
402+
403+
bparts := strings.SplitN(s, ":", 3)
404+
switch len(bparts) {
405+
case 2:
406+
source, dest = bparts[0], bparts[1]
407+
case 3:
408+
source, dest, options = bparts[0], bparts[1], bparts[2]
409+
default:
410+
return source, dest, options, fmt.Errorf("--bind should have format src:dest:[options]")
411+
}
412+
413+
return source, dest, options, nil
414+
}
415+
416+
func addSeccomp(g *generate.Generator, context *cli.Context) error {
417+
341418
// Set the DefaultAction of seccomp
342-
if context.IsSet("seccomp-default") {
343-
if err := g.SetLinuxSeccompDefault(sd); err != nil {
344-
return err
345-
}
419+
seccompDefault := context.String("seccomp-default")
420+
err := g.SetDefaultSeccompAction(seccompDefault)
421+
if err != nil {
422+
return err
346423
}
347424

348425
// Add the additional architectures permitted to be used for system calls
349-
if context.IsSet("seccomp-arch") {
350-
for _, arch := range sa {
351-
if err := g.AddLinuxSeccompArch(arch); err != nil {
352-
return err
426+
seccompArch := context.String("seccomp-arch")
427+
architectureArgs := strings.Split(seccompArch, ",")
428+
err = g.SetSeccompArchitectures(architectureArgs)
429+
if err != nil {
430+
return err
431+
}
432+
433+
if context.IsSet("seccomp-kill") {
434+
seccompKill := context.String("seccomp-kill")
435+
killArgs := strings.Split(seccompKill, ",")
436+
setSyscallArgsSlice := [][]string{}
437+
for _, killArg := range killArgs {
438+
comparisonArgs := strings.Split(killArg, ":")
439+
if len(comparisonArgs) == 5 {
440+
setSyscallArgs := []string{"kill",
441+
comparisonArgs[0],
442+
comparisonArgs[1],
443+
comparisonArgs[2],
444+
comparisonArgs[3],
445+
comparisonArgs[4],
446+
}
447+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
448+
} else if len(comparisonArgs) == 1 {
449+
setSyscallArgs := []string{"kill", comparisonArgs[0]}
450+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
451+
} else {
452+
return errors.New("Invalid syscall argument formatting")
453+
}
454+
455+
for _, r := range setSyscallArgsSlice {
456+
err := g.SetSyscallAction(r)
457+
if err != nil {
458+
return err
459+
}
353460
}
354461
}
355462
}
463+
if context.IsSet("seccomp-trace") {
464+
seccompTrace := context.String("seccomp-trace")
465+
traceArgs := strings.Split(seccompTrace, ",")
466+
setSyscallArgsSlice := [][]string{}
467+
for _, traceArg := range traceArgs {
468+
comparisonArgs := strings.Split(traceArg, ":")
469+
if len(comparisonArgs) == 5 {
470+
setSyscallArgs := []string{"trace",
471+
comparisonArgs[0],
472+
comparisonArgs[1],
473+
comparisonArgs[2],
474+
comparisonArgs[3],
475+
comparisonArgs[4],
476+
}
477+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
478+
} else if len(comparisonArgs) == 1 {
479+
setSyscallArgs := []string{"trace", comparisonArgs[0]}
480+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
481+
} else {
482+
return errors.New("Invalid syscall argument formatting")
483+
}
356484

357-
// Set syscall restrict in Seccomp
358-
if context.IsSet("seccomp-syscalls") {
359-
for _, syscall := range ss {
360-
if err := g.AddLinuxSeccompSyscall(syscall); err != nil {
361-
return err
485+
for _, r := range setSyscallArgsSlice {
486+
err := g.SetSyscallAction(r)
487+
if err != nil {
488+
return err
489+
}
362490
}
363491
}
364492
}
365493

366-
if context.IsSet("seccomp-allow") {
367-
seccompAllows := context.StringSlice("seccomp-allow")
368-
for _, s := range seccompAllows {
369-
g.AddLinuxSeccompSyscallAllow(s)
494+
if context.IsSet("seccomp-errno") {
495+
seccompErrno := context.String("seccomp-errno")
496+
errnoArg := strings.Split(seccompErrno, ",")
497+
setSyscallArgsSlice := [][]string{}
498+
for _, errnoArg := range errnoArg {
499+
comparisonArgs := strings.Split(errnoArg, ":")
500+
if len(comparisonArgs) == 5 {
501+
setSyscallArgs := []string{"errno",
502+
comparisonArgs[0],
503+
comparisonArgs[1],
504+
comparisonArgs[2],
505+
comparisonArgs[3],
506+
comparisonArgs[4],
507+
}
508+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
509+
} else if len(comparisonArgs) == 1 {
510+
setSyscallArgs := []string{"errno", comparisonArgs[0]}
511+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
512+
} else {
513+
return errors.New("Invalid syscall argument formatting")
514+
}
515+
516+
for _, r := range setSyscallArgsSlice {
517+
err := g.SetSyscallAction(r)
518+
if err != nil {
519+
return err
520+
}
521+
}
370522
}
371523
}
372524

373-
if context.IsSet("seccomp-errno") {
374-
seccompErrnos := context.StringSlice("seccomp-errno")
375-
for _, s := range seccompErrnos {
376-
g.AddLinuxSeccompSyscallErrno(s)
525+
if context.IsSet("seccomp-trap") {
526+
seccompTrap := context.String("seccomp-trap")
527+
trapArg := strings.Split(seccompTrap, ",")
528+
setSyscallArgsSlice := [][]string{}
529+
for _, trapArg := range trapArg {
530+
comparisonArgs := strings.Split(trapArg, ":")
531+
if len(comparisonArgs) == 5 {
532+
setSyscallArgs := []string{"trap",
533+
comparisonArgs[0],
534+
comparisonArgs[1],
535+
comparisonArgs[2],
536+
comparisonArgs[3],
537+
comparisonArgs[4],
538+
}
539+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
540+
} else if len(comparisonArgs) == 1 {
541+
setSyscallArgs := []string{"trap", comparisonArgs[0]}
542+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
543+
} else {
544+
return errors.New("Invalid syscall argument formatting")
545+
}
546+
547+
for _, r := range setSyscallArgsSlice {
548+
err := g.SetSyscallAction(r)
549+
if err != nil {
550+
return err
551+
}
552+
}
553+
}
554+
}
555+
556+
if context.IsSet("seccomp-allow") {
557+
seccompAllow := context.String("seccomp-allow")
558+
allowArg := strings.Split(seccompAllow, ",")
559+
setSyscallArgsSlice := [][]string{}
560+
for _, allowArg := range allowArg {
561+
comparisonArgs := strings.Split(allowArg, ":")
562+
if len(comparisonArgs) == 5 {
563+
setSyscallArgs := []string{"allow",
564+
comparisonArgs[0],
565+
comparisonArgs[1],
566+
comparisonArgs[2],
567+
comparisonArgs[3],
568+
comparisonArgs[4],
569+
}
570+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
571+
} else if len(comparisonArgs) == 1 {
572+
setSyscallArgs := []string{"allow", comparisonArgs[0]}
573+
setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs)
574+
} else {
575+
return errors.New("Invalid syscall argument formatting")
576+
}
577+
578+
for _, r := range setSyscallArgsSlice {
579+
err := g.SetSyscallAction(r)
580+
if err != nil {
581+
return err
582+
}
583+
}
377584
}
378585
}
379586

0 commit comments

Comments
 (0)