From 6d0aa0a52d37f61ed3b13dd71e32dff8a7981100 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 5 Jan 2024 11:57:19 +0100 Subject: [PATCH] cli/command/container: parseSecurityOpts: fix --security-opt seccomp=builtin Docker v23.0 and up allow the daemon to be configured to have seccomp disabled by default (using the "unconfined" profile as default), and introduced a new "builtin" profile-name for the default (see [moby@f8795ed364586acd][1] and [mnoby@ac449d6b5ad29a50][2]). However, the CLI had no special handling for the "builtin" profile, which resulted in it trying to load it as a file, which would fail; docker run -it --rm --security-opt seccomp=builtin busybox docker: opening seccomp profile (builtin) failed: open builtin: no such file or directory. See 'docker run --help'. This patch adds a special case for the "builtin" profile, to allow using the default profile on daemons with seccomp disabled (unconfined) by default. [1]: https://github.com/moby/moby/commit/f8795ed364586acd93f72e206a409e7e0e27edcc [2]: https://github.com/moby/moby/commit/ac449d6b5ad29a5086824729ce54eec6b0cc8545 Signed-off-by: Sebastiaan van Stijn --- cli/command/container/opts.go | 39 ++++++++++++++++++++++++------- docs/reference/commandline/run.md | 23 +++++++++--------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/cli/command/container/opts.go b/cli/command/container/opts.go index 837fc0d008..9ecef8ed02 100644 --- a/cli/command/container/opts.go +++ b/cli/command/container/opts.go @@ -28,6 +28,20 @@ import ( cdi "tags.cncf.io/container-device-interface/pkg/parser" ) +const ( + // TODO(thaJeztah): define these in the API-types, or query available defaults + // from the daemon, or require "local" profiles to be an absolute path or + // relative paths starting with "./". The daemon-config has consts for this + // but we don't want to import that package: + // https://github.com/moby/moby/blob/v23.0.0/daemon/config/config.go#L63-L67 + + // seccompProfileDefault is the built-in default seccomp profile. + seccompProfileDefault = "builtin" + // seccompProfileUnconfined is a special profile name for seccomp to use an + // "unconfined" seccomp profile. + seccompProfileUnconfined = "unconfined" +) + var deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`) // containerOptions is a data object with all the options for creating a container @@ -914,16 +928,23 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) { // "no-new-privileges" is the only option that does not require a value. return securityOpts, errors.Errorf("Invalid --security-opt: %q", opt) } - if k == "seccomp" && v != "unconfined" { - f, err := os.ReadFile(v) - if err != nil { - return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", v, err) + if k == "seccomp" { + switch v { + case seccompProfileDefault, seccompProfileUnconfined: + // known special names for built-in profiles, nothing to do. + default: + // value may be a filename, in which case we send the profile's + // content if it's valid JSON. + f, err := os.ReadFile(v) + if err != nil { + return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", v, err) + } + b := bytes.NewBuffer(nil) + if err := json.Compact(b, f); err != nil { + return securityOpts, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", v, err) + } + securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes()) } - b := bytes.NewBuffer(nil) - if err := json.Compact(b, f); err != nil { - return securityOpts, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", v, err) - } - securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes()) } } diff --git a/docs/reference/commandline/run.md b/docs/reference/commandline/run.md index 8d062932a8..56c0d5d630 100644 --- a/docs/reference/commandline/run.md +++ b/docs/reference/commandline/run.md @@ -1274,17 +1274,18 @@ in the image, or `SIGTERM` if the image has no `STOPSIGNAL` defined. ### Optional security options (--security-opt) -| Option | Description | -|:------------------------------------------|:--------------------------------------------------------------------------| -| `--security-opt="label=user:USER"` | Set the label user for the container | -| `--security-opt="label=role:ROLE"` | Set the label role for the container | -| `--security-opt="label=type:TYPE"` | Set the label type for the container | -| `--security-opt="label=level:LEVEL"` | Set the label level for the container | -| `--security-opt="label=disable"` | Turn off label confinement for the container | -| `--security-opt="apparmor=PROFILE"` | Set the apparmor profile to be applied to the container | -| `--security-opt="no-new-privileges=true"` | Disable container processes from gaining new privileges | -| `--security-opt="seccomp=unconfined"` | Turn off seccomp confinement for the container | -| `--security-opt="seccomp=profile.json"` | White-listed syscalls seccomp Json file to be used as a seccomp filter | +| Option | Description | +|:------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--security-opt="label=user:USER"` | Set the label user for the container | +| `--security-opt="label=role:ROLE"` | Set the label role for the container | +| `--security-opt="label=type:TYPE"` | Set the label type for the container | +| `--security-opt="label=level:LEVEL"` | Set the label level for the container | +| `--security-opt="label=disable"` | Turn off label confinement for the container | +| `--security-opt="apparmor=PROFILE"` | Set the apparmor profile to be applied to the container | +| `--security-opt="no-new-privileges=true"` | Disable container processes from gaining new privileges | +| `--security-opt="seccomp=unconfined"` | Turn off seccomp confinement for the container | +| `--security-opt="seccomp=builtin"` | Use the default (built-in) seccomp profile for the container. This can be used to enable seccomp for a container running on a daemon with a custom default profile set, or with seccomp disabled ("unconfined"). | +| `--security-opt="seccomp=profile.json"` | White-listed syscalls seccomp Json file to be used as a seccomp filter | The `--security-opt` flag lets you override the default labeling scheme for a container. Specifying the level in the following command allows you to share