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

Merged
merged 3 commits into from
Dec 3, 2024

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
@kolyshkin kolyshkin requested review from thaJeztah and rata August 1, 2024 08:33
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 Outdated 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 requested a review from cyphar September 26, 2024 05:41
@kolyshkin
Copy link
Contributor Author

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

@lifubang lifubang marked this pull request as ready for review September 26, 2024 06:07
// 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

@AkihiroSuda AkihiroSuda requested a review from rata October 8, 2024 02:03
@lifubang
Copy link
Member

lifubang commented Oct 8, 2024

@AkihiroSuda There is at least one error in this PR(#4358 (comment)), I suggest to wait moby/sys/capability to make an new release(moby/sys#165).

@rata
Copy link
Member

rata commented Oct 9, 2024

@lifubang Thanks, but can you elaborate on what is the error exactly? The link to a test case, what does that mean? Should that test fail? Or is it working and it shouldn't? Is that before/after the PR? What do you want to show exactly? I'll check-out this branch and test myself, but it would be great if you can elaborate more on your concern.

@lifubang
Copy link
Member

lifubang commented Oct 9, 2024

but can you elaborate on what is the error exactly?

#4358 (comment)
This PR will cause at least these two regressions.

The link to a test case, what does that mean?

It means the regression 1. So, how about merge this test case first to ensure we can't introduce any regression in the future?

@lifubang
Copy link
Member

lifubang commented Oct 9, 2024

I think we can split this PR to 3 PRs, then we can push the progress more easily.
PR 1: Switch to github.com/moby/sys/capability, this PR should not change any logicbehavior of runc, because we should replace the dependency package which has a long time bug and is in a unmaintained state ASAP;
PR 2: libct/cap: switch to lazy init;
PR 3: Improve the error msgs of cap set.

But unfortunately, there are still some bugs in github.com/moby/sys/capability. So we need to wait a new release of it.

@rata
Copy link
Member

rata commented Oct 9, 2024

@lifubang I fully agree, let's make this PR be 1 or 1 and 2. And PR 3 can be done later, maybe even after the 1.2.0 release (I'm not sure I'd hold the release for adding a warning, especially something that has been like this for a long time).

@kolyshkin what do you think?

@kolyshkin
Copy link
Contributor Author

PR 1: Switch to github.com/moby/sys/capability, this PR should not change any logicbehavior of runc, because we should replace the dependency package which has a long time bug and is in a unmaintained state ASAP;

Unfortunately it does change the behavior, because of the bug in the original package which is fixed in the fork (kolyshkin/capability#3).

Even if we try to work around this (set the AMBIENT caps separately and ignore the error), it will still change the behavior, because the fork returns the error as soon as it has it, while the original package keep going and tries to set all capabilities.

To solve this, we need something like AmbientRaise which is being added by moby/sys#165. As soon as it is merged and a new release is made, we can make the "PR 1 " work with maximum level of compatibility with the current version.

@kolyshkin
Copy link
Contributor Author

But unfortunately, there are still some bugs in github.com/moby/sys/capability. So we need to wait a new release of it.

More like "missing functionality" (of setting ambient capabilities one by one), although we can actually use x/sys/unix for that.

The only bug I'm aware of is this one, and it does not affect runc in any way.

@lifubang
Copy link
Member

To solve this, we need something like AmbientRaise which is being added by moby/sys#165. As soon as it is merged and a new release is made, we can make the "PR 1 " work with maximum level of compatibility with the current version.

Yes, like #4418, it is the final usage after we release moby/sys/capability v0.4.0.

@kolyshkin kolyshkin force-pushed the rm-cap-init branch 2 times, most recently from b9a4909 to 490ab7a Compare November 1, 2024 17:17
@kolyshkin
Copy link
Contributor Author

moby/sys/capability v0.4.0 released; this PR is rebased and (hopefully) ready for review.

PTAL @thaJeztah @lifubang

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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 <kolyshkin@gmail.com>
This removes the last unversioned package in runc's direct dependencies.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin kolyshkin merged commit 67c8a28 into opencontainers:main Dec 3, 2024
40 checks passed
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.

7 participants