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

libct/cap: switch to moby/sys/capability, lazy init #4358

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

kolyshkin
Copy link
Contributor

@kolyshkin kolyshkin commented Jul 23, 2024

This has started as a simple way to reduce init() overhead in libcontainer/capabilities, but ended up switching to the fork of gocapability package, and also fixing a big issue in handling of ambient capabilities.

Please see individual commits for details; I will open an issue about ambient caps tomorrow.

@kolyshkin kolyshkin marked this pull request as ready for review July 23, 2024 17:45
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM; left one suggestion (not blocking)

Copy link
Member

@rata rata left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@rata
Copy link
Member

rata commented Jul 30, 2024

This still LGTM. Let me know if it's ready, IMHO this is ready to merge.

@thaJeztah
Copy link
Member

@kolyshkin was the last commit intended for this PR, or for a follow up?

@kolyshkin kolyshkin changed the title libct/cap: switch to lazy init libct/cap: switch to kolyshkin/capability, lazy init, fix for ambient caps Aug 1, 2024
go.mod Outdated Show resolved Hide resolved
@kolyshkin
Copy link
Contributor Author

@kolyshkin was the last commit intended for this PR, or for a follow up?

I can split this PR into two, but really I want all this to be merged (and you don't have to re-review the first two commits).

@ningmingxiao

This comment was marked as outdated.

@kolyshkin
Copy link
Contributor Author

we want mv github.com/kolyshkin/capability to github.com/opencontainers/capability can you help me move [https://github.com/kolyshkin/capability] to under opencontainers org? @gregkh @bfirsh

Please don't tag people you don't know. These are definitely not those who can help. We will figure it out.

@thaJeztah thaJeztah self-requested a review August 2, 2024 08:08
Copy link
Member

@rata rata left a comment

Choose a reason for hiding this comment

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

This mostly LGTM, left some comments

libcontainer/capabilities/capabilities.go Show resolved Hide resolved
out = append(out, v)
}
}
return out
}
inheritable := capSlice(capConfig.Inheritable, nil)
// Ambient vector can not contain values not raised in the Inheritable vector,
Copy link
Member

Choose a reason for hiding this comment

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

The whole sentence from: https://pkg.go.dev/kernel.org/pub/linux/libs/security/libcap/cap#section-readme is:

Note, the Ambient vector cannot contain values not raised in the Inh vector, so setting values directly in one vector may have the side effect of mirroring the value in the other vector to maintain this constraint

I guess we want to ignore it, instead of adding it, as we are doing for a long time now. But wanted to raise this, just in case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that library raises inheritable bits where the corresponding ambient bits are raised.

I agree that we should not change the behavior (and instead maybe document that if you want to raise ambient caps, you have to raise inheritable ones as well).

Copy link
Member

Choose a reason for hiding this comment

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

SGTM

@kolyshkin kolyshkin changed the title libct/cap: switch to kolyshkin/capability, lazy init, fix for ambient caps libct/cap: switch to kolyshkin/capability, lazy init Aug 6, 2024
@kolyshkin kolyshkin marked this pull request as draft August 6, 2024 19:22
@kolyshkin kolyshkin changed the title libct/cap: switch to kolyshkin/capability, lazy init libct/cap: switch to moby/sys/capability, lazy init Sep 12, 2024
@kolyshkin kolyshkin force-pushed the rm-cap-init branch 2 times, most recently from 26aaa82 to e63cec2 Compare September 16, 2024 19:41
@kolyshkin kolyshkin marked this pull request as ready for review September 16, 2024 19:41
@rata
Copy link
Member

rata commented Sep 19, 2024

@kolyshkin I see you marked this as ready, but as you didn't re-request a review, it doesn't notify anyone.

Is this ready for review? I see the first 3 commits here are also in #4367, which seems confusing (and splitting the threads of review for those). Do you want us to review the rest of the commits only here, but those are here to avoid conflicts/something? Can you explain a little bit what is your intention here?

@kolyshkin
Copy link
Contributor Author

@kolyshkin I see you marked this as ready, but as you didn't re-request a review, it doesn't notify anyone.

Is this ready for review? I see the first 3 commits here are also in #4367, which seems confusing (and splitting the threads of review for those). Do you want us to review the rest of the commits only here, but those are here to avoid conflicts/something? Can you explain a little bit what is your intention here?

Sorry for the confusion; I think we should merge #4367 first, and I am still working on it (need to add a new test case by @lifubang).

@kolyshkin kolyshkin force-pushed the rm-cap-init branch 2 times, most recently from 0583622 to ff2e3dd Compare September 26, 2024 05:40
@kolyshkin
Copy link
Contributor Author

No longer a draft; PTAL @lifubang @AkihiroSuda @thaJeztah

// compatibility we have to ignore those Ambient caps that are not also raised
// in Inheritable (and issue a warning).
ambient := capSlice(capConfig.Ambient, inheritable)
if len(ignoredCaps) > 0 {
Copy link
Member

Choose a reason for hiding this comment

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

There are at least 2 conditions to return error when setting ambient caps:

  1. The ambient cap sets is not in both permitted and inheritable cap sets;
  2. The PR_CAP_AMBIENT_LOWER securebit has been set.

So maybe this is not enough. I take another easy way to implement this compatibility. (#4418)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This PR handles condition 1. As for condition 2, it works as it used to work before, no changes needed here.

In general, I think, we should return an error when we're unable to set a capability requested. The warning which this PR adds is a temporary measure, to ensure we're not breaking our users. Eventually this warning should become an error.

Copy link
Member

Choose a reason for hiding this comment

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

This PR handles condition 1.

Because of ‘both permitted and inheritable cap sets’.

Even in condition 1, I think you need to add check ‘permitted’ too, not only ‘inheritable’. Please see my first commit in #4418 .

As for condition 2, it works as it used to work before, no changes needed here.

I think this error was also masked before this PR, but will be failed in the future. It should have a compatibility like condition 1.

Copy link
Contributor Author

@kolyshkin kolyshkin Sep 28, 2024

Choose a reason for hiding this comment

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

Even in condition 1, I think you need to add check ‘permitted’ too, not only ‘inheritable’. Please see my first commit in #4418 .

It looks like such configuration is not working in the current runc version:

@test "runc run [raise inheritable bit not set in permitted]" {
        update_config '   .process.capabilities.inheritable = ["CAP_KILL"]
                        | .process.capabilities.permitted = ["CAP_CHOWN"]'
#                       | .process.capabilities.ambient = ["CAP_KILL", "CAP_CHOWN"]'

        runc run testct
        [ "$status" -eq 0 ]
 runc run testct (status=1):
   time="2024-09-27T17:31:28-07:00" level=error msg="runc run failed: unable to start container process: error during container init: unable to apply caps: operation not permitted"

This means:

  1. If it's not working now, it should not start work in the future.
  2. We don't have to check for permitted bit set when checking ambient.

As for condition 2, it works as it used to work before, no changes needed here.

I think this error was also masked before this PR, but will be failed in the future. It should have a compatibility like condition 1.

You might be right, I need to check it.

Copy link
Member

Choose a reason for hiding this comment

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

It looks like such configuration is not working in the current runc version:

31be074

@kolyshkin
Copy link
Contributor Author

@cyphar @AkihiroSuda PTAL

Signed-off-by: Kir Kolyshkin <[email protected]>
A map which is created in func init is only used by capSlice, which is
only used by New, which is only used by runc init. Switch to lazy init
to slightly save on startup time.

Signed-off-by: Kir Kolyshkin <[email protected]>
Move capSlice to be an internal function of New. This way, we don't have
to pass most parameters.

This is a preparation for the next commit.

Signed-off-by: Kir Kolyshkin <[email protected]>
Fixing a long standing bug in github.com/syndtr/gocapability package
(ignoring errors when setting ambient caps, see [1]) revealed that
it's not possible to raise those ambient capabilities for which
inheritable capabilities are not raised. In other words, "the Ambient
vector cannot contain values not raised in the Inh vector" ([2]).

The example spec in libct/specconv had a few ambient capabilities set
but no inheritable ones. As a result, when capability package with fix
from [1] is used, we get an error trying to start a container ("unable
to apply caps: permission denied").

The only decent way to fix this is to ignore raised ambient capabilities
for which inheritable capabilities are not raised (essentially mimicking
the old behavior). Let's also add a warning about ignored capabilities,
with an intention to change it to an error later.

Fix the example spec accordingly (remove the ambient caps).

This is in preparation to switch to github.com/kolyshkin/capability.

[1]: kolyshkin/capability#3
[2]: https://pkg.go.dev/kernel.org/pub/linux/libs/security/libcap/cap#IAB.SetVector
Signed-off-by: Kir Kolyshkin <[email protected]>
This removes the last unversioned package in runc's direct dependencies.

Signed-off-by: Kir Kolyshkin <[email protected]>
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.

6 participants