From bf3f0d4d75153ce56b0c83a5767149e518a18c83 Mon Sep 17 00:00:00 2001 From: Haiyan Meng Date: Thu, 21 Jul 2016 12:30:18 -0400 Subject: [PATCH] Check CAP_LAST_CAP while setting privileged Signed-off-by: Haiyan Meng --- cmd/ocitools/generate.go | 12 ++++++++---- cmd/ocitools/main.go | 4 ++++ cmd/ocitools/validate.go | 3 +-- generate/generate.go | 31 ++++++++++++++++++++++--------- man/ocitools-validate.1.md | 10 ---------- man/ocitools.1.md | 17 ++++++++++++++++- 6 files changed, 51 insertions(+), 26 deletions(-) diff --git a/cmd/ocitools/generate.go b/cmd/ocitools/generate.go index fca5d6fcb..a6423a028 100644 --- a/cmd/ocitools/generate.go +++ b/cmd/ocitools/generate.go @@ -78,7 +78,7 @@ var generateCommand = cli.Command{ } } - err := setupSpec(specgen, context) + err := setupSpec(&specgen, context) if err != nil { return err } @@ -96,8 +96,12 @@ var generateCommand = cli.Command{ }, } -func setupSpec(g generate.Generator, context *cli.Context) error { - spec := g.GetSpec() +func setupSpec(g *generate.Generator, context *cli.Context) error { + if context.GlobalBool("host-specific") { + g.HostSpecific = true + } + + spec := g.Spec() if len(spec.Version) == 0 { g.SetVersion(rspec.Version) @@ -369,7 +373,7 @@ func checkNs(nsMaps map[string]string, nsName string) bool { return true } -func setupLinuxNamespaces(g generate.Generator, needsNewUser bool, nsMaps map[string]string) { +func setupLinuxNamespaces(g *generate.Generator, needsNewUser bool, nsMaps map[string]string) { for _, nsName := range generate.Namespaces { if !checkNs(nsMaps, nsName) && !(needsNewUser && nsName == "user") { continue diff --git a/cmd/ocitools/main.go b/cmd/ocitools/main.go index daf8d4359..7ced60de2 100644 --- a/cmd/ocitools/main.go +++ b/cmd/ocitools/main.go @@ -18,6 +18,10 @@ func main() { Value: "error", Usage: "Log level (panic, fatal, error, warn, info, or debug)", }, + cli.BoolFlag{ + Name: "host-specific", + Usage: "generate host-specific configs or do host-specific validations", + }, } app.Commands = []cli.Command{ diff --git a/cmd/ocitools/validate.go b/cmd/ocitools/validate.go index 760b44ea4..0fab50202 100644 --- a/cmd/ocitools/validate.go +++ b/cmd/ocitools/validate.go @@ -24,7 +24,6 @@ type configCheck func(rspec.Spec, string, bool) []string var bundleValidateFlags = []cli.Flag{ cli.StringFlag{Name: "path", Value: ".", Usage: "path to a bundle"}, - cli.BoolFlag{Name: "host-specific", Usage: "Check host specific configs."}, } var ( @@ -99,7 +98,7 @@ var bundleValidateCommand = cli.Command{ return fmt.Errorf("The root path %q is not a directory.", rootfsPath) } - hostCheck := context.Bool("host-specific") + hostCheck := context.GlobalBool("host-specific") checks := []configCheck{ checkMandatoryFields, diff --git a/generate/generate.go b/generate/generate.go index fd5d9c6f9..f1d0c8865 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -21,7 +21,8 @@ var ( // Generator represents a generator for a container spec. type Generator struct { - spec *rspec.Spec + spec *rspec.Spec + HostSpecific bool } // New creates a spec Generator with the default spec. @@ -139,12 +140,16 @@ func New() Generator { Devices: []rspec.Device{}, }, } - return Generator{&spec} + return Generator{ + spec: &spec, + } } // NewFromSpec creates a spec Generator from a given spec. func NewFromSpec(spec *rspec.Spec) Generator { - return Generator{spec} + return Generator{ + spec: spec, + } } // NewFromFile loads the template specifed in a file into a spec Generator. @@ -166,7 +171,9 @@ func NewFromTemplate(r io.Reader) (Generator, error) { if err := json.NewDecoder(r).Decode(&spec); err != nil { return Generator{}, err } - return Generator{&spec}, nil + return Generator{ + spec: &spec, + }, nil } // SetSpec sets the spec in the Generator g. @@ -174,8 +181,8 @@ func (g *Generator) SetSpec(spec *rspec.Spec) { g.spec = spec } -// GetSpec gets the spec in the Generator g. -func (g *Generator) GetSpec() *rspec.Spec { +// Spec gets the spec in the Generator g. +func (g *Generator) Spec() *rspec.Spec { return g.spec } @@ -953,6 +960,9 @@ func (g *Generator) SetupPrivileged(privileged bool) { // Add all capabilities in privileged mode. var finalCapList []string for _, cap := range capability.List() { + if g.HostSpecific && cap > capability.CAP_LAST_CAP { + continue + } finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String()))) } g.initSpecLinux() @@ -963,12 +973,15 @@ func (g *Generator) SetupPrivileged(privileged bool) { } } -func checkCap(c string) error { +func checkCap(c string, hostSpecific bool) error { isValid := false cp := strings.ToUpper(c) for _, cap := range capability.List() { if cp == strings.ToUpper(cap.String()) { + if hostSpecific && cap > capability.CAP_LAST_CAP { + return fmt.Errorf("CAP_%s is not supported on the current host", cp) + } isValid = true break } @@ -990,7 +1003,7 @@ func (g *Generator) ClearProcessCapabilities() { // AddProcessCapability adds a process capability into g.spec.Process.Capabilities. func (g *Generator) AddProcessCapability(c string) error { - if err := checkCap(c); err != nil { + if err := checkCap(c, g.HostSpecific); err != nil { return err } @@ -1009,7 +1022,7 @@ func (g *Generator) AddProcessCapability(c string) error { // DropProcessCapability drops a process capability from g.spec.Process.Capabilities. func (g *Generator) DropProcessCapability(c string) error { - if err := checkCap(c); err != nil { + if err := checkCap(c, g.HostSpecific); err != nil { return err } diff --git a/man/ocitools-validate.1.md b/man/ocitools-validate.1.md index a65a152cc..e5e3a1b8b 100644 --- a/man/ocitools-validate.1.md +++ b/man/ocitools-validate.1.md @@ -18,16 +18,6 @@ Validate an OCI bundle **--path=PATH Path to bundle -**--host-specific** - Check host specific configs. - By default, validation only tests for compatibility with a hypothetical host. - With this flag, validation will also run more specific tests to see whether - the current host is capable of launching a container from the configuration. - For example, validating a compliant Windows configuration on a Linux machine - will pass without this flag ("there may be a Windows host capable of - launching this container"), but will fail with it ("this host is not capable - of launching this container"). - # SEE ALSO **ocitools**(1) diff --git a/man/ocitools.1.md b/man/ocitools.1.md index bf338b2ab..a698fff4e 100644 --- a/man/ocitools.1.md +++ b/man/ocitools.1.md @@ -15,11 +15,26 @@ ocitools is a collection of tools for working with the [OCI runtime specificatio # OPTIONS **--help** - Print usage statement + Print usage statement. **-v**, **--version** Print version information. +**--log-level** + Log level (panic, fatal, error, warn, info, or debug) (default: "error"). + +**--host-specific** + Generate host-specific configs or do host-specific validations. + + By default, generator generates configs without checking whether they are + supported on the current host. With this flag, generator will first check + whether each config is supported on the current host, and only add it into + the config file if it passes the checking. + + By default, validation only tests for compatibility with a hypothetical host. + With this flag, validation will also run more specific tests to see whether + the current host is capable of launching a container from the configuration. + # COMMANDS **validate** Validating OCI bundle