Skip to content
This repository has been archived by the owner on Aug 14, 2020. It is now read-only.

Commit

Permalink
actool: add support for patching seccomp isolators
Browse files Browse the repository at this point in the history
  • Loading branch information
lucab committed Jun 15, 2016
1 parent 77d87e2 commit 3e2e69b
Showing 1 changed file with 84 additions and 4 deletions.
88 changes: 84 additions & 4 deletions actool/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ var (
patchMounts string
patchPorts string
patchIsolators string
patchSeccompMode string
patchSeccompSet string

catPrettyPrint bool

Expand All @@ -69,6 +71,8 @@ var (
[--ports=query,protocol=tcp,port=8080[:query2,...]]
[--supplementary-groups=gid1,gid2,...]
[--isolators=resource/cpu,request=50m,limit=100m[:resource/memory,...]]
[--seccomp-mode=remove|retain[,errno=EPERM]]
[--seccomp-set=syscall1,syscall2,...]]
[--replace]
INPUT_ACI_FILE
[OUTPUT_ACI_FILE]`,
Expand Down Expand Up @@ -99,6 +103,8 @@ func init() {
cmdPatchManifest.Flags.StringVar(&patchMounts, "mounts", "", "Replace mount points")
cmdPatchManifest.Flags.StringVar(&patchPorts, "ports", "", "Replace ports")
cmdPatchManifest.Flags.StringVar(&patchIsolators, "isolators", "", "Replace isolators")
cmdPatchManifest.Flags.StringVar(&patchSeccompMode, "seccomp-mode", "", "Enable and configure seccomp isolator")
cmdPatchManifest.Flags.StringVar(&patchSeccompSet, "seccomp-set", "", "Set of syscalls for seccomp isolator enforcing")

cmdCatManifest.Flags.BoolVar(&catPrettyPrint, "pretty-print", false, "Print with better style")
}
Expand Down Expand Up @@ -211,7 +217,11 @@ func patchManifest(im *schema.ImageManifest) error {
if err != nil {
return fmt.Errorf("cannot parse capability %q: %v", patchCaps, err)
}
app.Isolators = append(app.Isolators, caps.AsIsolator())
isolator, err = caps.AsIsolator()
if err != nil {
return err
}
app.Isolators = append(app.Isolators, *isolator)
}
if patchRevokeCaps != "" {
isolator, _ := app.Isolators.GetByName(types.LinuxCapabilitiesRevokeSetName)
Expand All @@ -225,7 +235,11 @@ func patchManifest(im *schema.ImageManifest) error {
if err != nil {
return fmt.Errorf("cannot parse capability %q: %v", patchRevokeCaps, err)
}
app.Isolators = append(app.Isolators, caps.AsIsolator())
isolator, err = caps.AsIsolator()
if err != nil {
return err
}
app.Isolators = append(app.Isolators, *isolator)
}

if patchMounts != "" {
Expand All @@ -250,6 +264,27 @@ func patchManifest(im *schema.ImageManifest) error {
}
}

// Parse seccomp args and override existing seccomp isolators
if patchSeccompMode != "" {
seccomp, err := parseSeccompArgs(patchSeccompMode, patchSeccompSet)
if err != nil {
return err
}
seccompIsolator, err := seccomp.AsIsolator()
if err != nil {
return err
}
seccompReps := []types.ACIdentifier{types.LinuxSeccompRemoveSetName, types.LinuxSeccompRetainSetName}
_, err = app.Isolators.ReplaceIsolatorsByName(*seccompIsolator, seccompReps)
if err != nil {
return err
}
} else {
if patchSeccompSet != "" {
return fmt.Errorf("--seccomp-set specified without --seccomp-mode")
}
}

if patchIsolators != "" {
isolators := strings.Split(patchIsolators, ":")
for _, is := range isolators {
Expand All @@ -260,14 +295,18 @@ func patchManifest(im *schema.ImageManifest) error {

_, ok := types.ResourceIsolatorNames[name]

if name == types.LinuxNoNewPrivilegesName {
switch name {
case types.LinuxNoNewPrivilegesName:
ok = true
kv := strings.Split(is, ",")
if len(kv) != 2 {
return fmt.Errorf("isolator %s: invalid format", name)
}

isolatorStr = fmt.Sprintf(`{ "name": "%s", "value": %s }`, name, kv[1])
case types.LinuxSeccompRemoveSetName:
fallthrough
case types.LinuxSeccompRetainSetName:
ok = false
}

if !ok {
Expand All @@ -284,6 +323,47 @@ func patchManifest(im *schema.ImageManifest) error {
return nil
}

// parseSeccompArgs parses seccomp mode and set CLI flags, preparing an
// appropriate seccomp isolator.
func parseSeccompArgs(patchSeccompMode string, patchSeccompSet string) (types.AsIsolator, error) {
// Parse mode flag and additional keyed arguments.
var errno, mode string
args := strings.Split(patchSeccompMode, ",")
for _, a := range args {
kv := strings.Split(a, "=")
switch len(kv) {
case 1:
// mode, either "remove" or "retain"
mode = kv[0]
case 2:
// k=v argument, only "errno" allowed for now
if kv[0] == "errno" {
errno = kv[1]
} else {
return nil, fmt.Errorf("invalid seccomp-mode optional argument: %s", a)
}
default:
return nil, fmt.Errorf("cannot parse seccomp-mode argument: %s", a)
}
}

// Instantiate an Isolator with the content specified by the --seccomp-set parameter.
var err error
var seccomp types.AsIsolator
switch mode {
case "remove":
seccomp, err = types.NewLinuxSeccompRemoveSet(errno, strings.Split(patchSeccompSet, ",")...)
case "retain":
seccomp, err = types.NewLinuxSeccompRetainSet(errno, strings.Split(patchSeccompSet, ",")...)
default:
err = fmt.Errorf("Unknown seccomp mode %s", mode)
}
if err != nil {
return nil, fmt.Errorf("cannot parse seccomp isolator: %s", err)
}
return seccomp, nil
}

// extractManifest iterates over the tar reader and locate the manifest. Once
// located, the manifest can be printed, replaced or patched.
func extractManifest(tr *tar.Reader, tw *tar.Writer, printManifest bool, newManifest []byte) error {
Expand Down

0 comments on commit 3e2e69b

Please sign in to comment.