Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check CAP_LAST_CAP while setting privileged #138

Merged
merged 1 commit into from
Jul 27, 2016

Conversation

haiyanmeng
Copy link
Contributor

The PR checks whether each cap inside capability.List() is <= capability.CAP_LAST_CAP before adding it into finalCapList.
This avoids add unsupported cap into finalCapList. For example, CAP_AUDIT_READ is added into the kernel since Linux 3.16, and not supported on RHEL7.

Signed-off-by: Haiyan Meng hmeng@redhat.com

@haiyanmeng
Copy link
Contributor Author

@mrunalp , PTAL.

@wking
Copy link
Contributor

wking commented Jul 21, 2016

On Thu, Jul 21, 2016 at 09:39:36AM -0700, hmeng-19 wrote:

The PR checks whether each cap inside capability.List() is <=
capability.CAP_LAST_CAP before adding it into finalCapList.

This is host-specific (e.g. maybe you're using a host with an old
kernel to build a container for a host with a new kernel). ‘validate’
has a --host-specific flag to cover this sort of thing 1. Maybe we
should promote that to a global option?

@haiyanmeng
Copy link
Contributor Author

@wking , I am testing octools on RHEL7 recently.
After running the following command, CAP_AUDIT_READ was also put into config.json. However, rhel7 does not support this cap, because its kernel is 3.10.

ocitools generate --privileged --tty --output=config.json --uidmappings=0:0:1024 --gidmappings=0:0:1024

@wking
Copy link
Contributor

wking commented Jul 21, 2016

On Thu, Jul 21, 2016 at 09:49:08AM -0700, hmeng-19 wrote:

After running the following command, CAP_AUDIT_READ was also put
into config.json. However, rhel7 does not support this cap,
because its kernel is 3.10.

That's only a problem if you're also trying to run the container on
the same kernel that was used to generate the config. A system
running Linux 3.10 is capable of generating a config that uses
CAP_AUDIT_READ (or a Solaris config, or a Windows config). It just
can't run containers using those configs.

A --host-specific flag says “Don't be generic, I want to
generate/validate for the current host”. For you, that would end up
looking like:

$ ocitools --host-specific generate --privileged --tty --output=config.json --uidmappings=0:0:1024 --gidmappings=0:0:1024

@haiyanmeng
Copy link
Contributor Author

@wking , sounds good. It would be nice we can take care both cases:

  1. create config.json with ocitools and use the config.json with runc on the same machine;
  2. create config.json with ocitools and use the config.json with runc on different machines;

It is easy to picture both use cases.

@wking
Copy link
Contributor

wking commented Jul 21, 2016

On Thu, Jul 21, 2016 at 10:01:54AM -0700, hmeng-19 wrote:

It would be nice we can take care both cases:

Agreed, that's why I'm suggesting a global option ;).

@haiyanmeng
Copy link
Contributor Author

@mrunalp , how do you think about this?

@mrunalp
Copy link
Contributor

mrunalp commented Jul 21, 2016

Sounds good to me.

@haiyanmeng
Copy link
Contributor Author

@mrunalp , @wking , PTAL.

@@ -84,7 +84,7 @@ var bundleValidateCommand = cli.Command{
return fmt.Errorf("The root path %q is not a directory.", rootfsPath)
}

hostCheck := context.Bool("host-specific")
hostCheck := hostSpecific || context.Bool("host-specific")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want both a global and a per-command --host-specific here. We should drop the per-command option.

And I'm not all that familiar with urfave/cli, but do we really need the package-global hostSpecific? I'd expect you to be able to pull that from the context, even though it's set via a global variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want both a global and a per-command --host-specific here. We should drop the per-command option.

I am okay with drop the per-command --host-specific option once @mrunalp and you are okay with it.
I keep it for now just in case some important users are using it.

Copy link
Contributor Author

@haiyanmeng haiyanmeng Jul 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm not all that familiar with urfave/cli, but do we really need the package-global hostSpecific? I'd expect you to be able to pull that from the context, even though it's set via a global variable.

I use a global var here to avoid multiple func calls to context.GlobalBool. However, it does not make too much difference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, here's an example of accessing a global option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 21, 2016 at 12:31:53PM -0700, hmeng-19 wrote:

I keep it for now just in case some important users are using it.

We haven't tagged an ocitools release yet or said anything about
forward compat in it's command-line API, so I think we're free to
change whatever we want. But if we know of any consumers, giving them
a heads up on the change would be good (ideally as part of a
release-tagging process ;).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 21, 2016 at 12:33:31PM -0700, hmeng-19 wrote:

I use a global var here to avoid multiple func calls to
context.GlobalBool.

What's the drawback to multiple GlobalBool calls? I like that more
than a package global, since it keeps the “single, unambiguous,
authoritative” representation of that setting 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, multiple calls to GlobalBool are fine. Also, can drop per command option in favor of global.

@haiyanmeng
Copy link
Contributor Author

@mrunalp , @wking , PTAL.

Log level (panic, fatal, error, warn, info, or debug) (default: "error").

**--host-specific**
Generate host-specific configs or do host-specific validations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section (including the following paragraph) needs to be genericized now that it's covering both generate and validate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment has been addressed.

@haiyanmeng
Copy link
Contributor Author

@wking , @mrunalp , PTAL.

privileged := false
if context.IsSet("privileged") {
privileged = context.Bool("privileged")
}
g.SetupPrivileged(privileged)
g.SetupPrivileged(privileged, hostSpecific)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this more, I think that we shouldn't pass this as part of the API. We should have a call to enable hostSpecific on the generate object and then use that variable in individual APIs

g := generate.New()
g.EnableHostSpecific()
g.SetupPrivileged()
...
g.SaveToFile()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Thu, Jul 21, 2016 at 04:01:34PM -0700, Mrunal Patel wrote:

privileged := false
if context.IsSet("privileged") {
    privileged = context.Bool("privileged")
}
  • g.SetupPrivileged(privileged)
  • g.SetupPrivileged(privileged, hostSpecific)

Thinking about this more, I think that we shouldn't pass this as
part of the API. We should have a call to enable hostSpecific on the
generate object and then use that variable in individual APIs

g := generate.New()
g.EnableHostSpecific()
g.SetupPrivileged()

This works for me. I think it depends on the setting though; I prefer
seccomp-only to be a Save(ToFile) parameter and not a Generator-wide
setting 1. The threshold is “can we think of a reason why a single
Generator would need different values in different contexts?”, and
that makes me a bit jumpy (my crystal ball isn't always that clear ;).
But in this case a Generator setting seems safe enough.

@haiyanmeng
Copy link
Contributor Author

@mrunalp , PTAL.

@haiyanmeng
Copy link
Contributor Author

@mrunalp , EnableHostSpecific has a pointer receiver. Do you think I should change all the other receivers of other generate methods to be pointers?
I can also change hostSpecific to be a package-level var.

@@ -21,7 +21,8 @@ var (

// Generator represents a generator for a container spec.
type Generator struct {
spec *rspec.Spec
spec *rspec.Spec
hostSpecific bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make this private with a setter (and no getter)? Is there a reason to not make it public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I currently did not think of any cases where Generator.hostSpsecific is queried outside the package.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Fri, Jul 22, 2016 at 10:16:03AM -0700, hmeng-19 wrote:

@@ -21,7 +21,8 @@ var (

// Generator represents a generator for a container spec.
type Generator struct {

  • spec *rspec.Spec
  • spec *rspec.Spec
  • hostSpecific bool

I currently did not think of any cases where
Generator.hostSpsecific is queried outside the package.

“I can't think of any reason you'd care” is different from “we don't
want people touching this directly”. Since a public field doesn't
require getters/setters, I'd rather keep things public unless we have
reasons to make them private.

@wking
Copy link
Contributor

wking commented Jul 22, 2016

On Fri, Jul 22, 2016 at 09:45:37AM -0700, hmeng-19 wrote:

Do you think I should change all the other receivers of other
generate methods to be pointers?

I think so, but this should probably be a separate commit, since it's
going to be noisy. Copy-by-value Generators relying on the underlying
Generator.spec being a pointer seems like it could be confusing.

**--host-specific**
Generate host-specific configs or do host-specific validations.

By default, generator addes process capabilities into the config without
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“addes” → “adds”

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accept. Thanks.

@haiyanmeng
Copy link
Contributor Author

I think so, but this should probably be a separate commit, since it's
going to be noisy. Copy-by-value Generators relying on the underlying
Generator.spec being a pointer seems like it could be confusing.

@wking , sounds good. I will work on it after the PR is done.

@haiyanmeng
Copy link
Contributor Author

@wking , @mrunalp , PTAL.

@haiyanmeng
Copy link
Contributor Author

@wking , @mrunalp , I added getHostSpecific method and rebased the PR on the upstream master. PTAL.

@wking
Copy link
Contributor

wking commented Jul 25, 2016

On Mon, Jul 25, 2016 at 11:45:14AM -0700, hmeng-19 wrote:

@wking , @mrunalp , I added getHostSpecific method and rebased the
PR on the upstream master. PTAL.

Go suggests not using a ‘Get’ prefix 1, and I'd still rather just
make the property public and skip the getter/setter 2.

@haiyanmeng
Copy link
Contributor Author

@wking , @mrunalp , I added a new commit which:
converts hostSpecific into a public field HostSpecific;
replace GetSpec with Spec.
PTAL.
I will squash the commits before it is ready to be merged.

@mrunalp
Copy link
Contributor

mrunalp commented Jul 26, 2016

LGTM

@haiyanmeng
Copy link
Contributor Author

@mrunalp , PTAL.
I rebased the PR on top of the upstream master and squashed the commits into a single one.

gp.HostSpecific = true
}

g := *gp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this. It seemed to compile and run fine for me with the following change on top of 751e18b:

diff --git a/cmd/ocitools/generate.go b/cmd/ocitools/generate.go
index ab1f6cc..a6423a0 100644
--- a/cmd/ocitools/generate.go
+++ b/cmd/ocitools/generate.go
@@ -96,12 +96,11 @@ var generateCommand = cli.Command{
    },
 }

-func setupSpec(gp *generate.Generator, context *cli.Context) error {
+func setupSpec(g *generate.Generator, context *cli.Context) error {
    if context.GlobalBool("host-specific") {
-       gp.HostSpecific = true
+       g.HostSpecific = true
    }

-   g := *gp
    spec := g.Spec()

    if len(spec.Version) == 0 {
@@ -374,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

@wking
Copy link
Contributor

wking commented Jul 26, 2016

On Tue, Jul 26, 2016 at 11:31:38AM -0700, hmeng-19 wrote:

I rebased the PR on top of the upstream master and squashed the
commits into a single one.

Except for 1 751e18b looks good to me.

I'd rather see this v1.0.0-rc1-compatible change based on the
v1.0.0.rc1 branch so we could have it in both master and that branch
without cherry picking and subsequent post-v1.0.0.rc1 merge
duplication. More on this in #140 and the comments after 2.

Signed-off-by: Haiyan Meng <hmeng@redhat.com>
@haiyanmeng
Copy link
Contributor Author

@wking , thanks for pointing out. Fixed it. PTAL.

@wking
Copy link
Contributor

wking commented Jul 27, 2016

bf3f0d4 looks good to me, although I'd still rather not have to
cherry-pick it back into v1.0.0.rc1 1.

@haiyanmeng
Copy link
Contributor Author

@mrunalp , PTAL.

@mrunalp
Copy link
Contributor

mrunalp commented Jul 27, 2016

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants