-
Notifications
You must be signed in to change notification settings - Fork 199
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
pkg/subscriptions: Modernize FIPS mounts #2174
pkg/subscriptions: Modernize FIPS mounts #2174
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkg/subscriptions/subscriptions.go
Outdated
logrus.Errorf("Adding FIPS mode bind mounts to container: %v", err) | ||
} | ||
} else { | ||
logrus.Debug("/proc/sys/crypto/fips_enabled does not contain '1', not adding FIPS mode bind mounts") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth logging the value here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. The value can't change without a reboot, and it's going to be the the same across the entire host, regardless of whether one is inside of a container or outside. It should be simple to obtain the actual value using cat
if necessary for debugging.
The only case where this could differ from the global value is if somebody bind-mounted a file over it for testing purposes. I don't think we need to handle this eventuality.
pkg/subscriptions/subscriptions.go
Outdated
file, err := os.Create(fipsFile) | ||
fipsFileHost := filepath.Join(mountPoint, "etc/system-fips") | ||
if fileutils.Lexists(fipsFileHost) != nil { | ||
fipsFileTarget, err := filepath.EvalSymlinks(fipsFileHost) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conceptually allows an attacker to set up /etc/system-fips
inside the container to be a symlink with ../../
… to break out of the container and refer to hosts’ files.
Yes, we actually only compare the fipsFileTarget
text without referring to the possibly-unwanted file, but, still…
In other words, either we care about the specific symlink text, and we can just Readlink
(probably not), or we care about where the symlink evaluates, whatever its form, and in that case ..
in the /
directory of the container should be evaluated correctly (restricted to the containers’ root).
(https://github.com/cyphar/filepath-securejoin is used for that purpose in some parts of the codebase.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, fixed by using securejoin. I still need a fileutils.Lexists
, because the log messages should probably differ between /etc/system-fips
not existing (which is a common config) and /etc/system-fips
existing but not pointing to /run/secrets/system-fips
(which is probably an uncommon config). That shouldn't be an issue, though, since fileutils.Lexists
doesn't follow symlinks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn’t actually review the substance of the PR, whether the code correctly handles all relevant versions of the OSes and behaviors.
Just looking at the mechanism, all the filepath.Join(mountPoint, …)
in this file make me worried about symlink breakouts. There might not be much actually wrong there (at worst, I guess, triggering an an audit message about a DAC or SELinux permission violation by the container runtime when checking for presence of an out-of-contaienr file), but that’s just one small refactor away from disaster.
I do appreciate that almost all of that is pre-existing and not directly relevant to this PR.
I noticed this last week when I looked at this PR and reported this internally so yes this is an pre existing issue, fix in #2185 |
I'm on PTO until Oct 14, I'll fix the comments after that. |
fada40b
to
affa37c
Compare
pkg/subscriptions/subscriptions.go
Outdated
fips_enabled, err := os.ReadFile("/proc/sys/crypto/fips_enabled") | ||
if err != nil { | ||
logrus.Errorf("Failed to read /proc/sys/crypto/fips_enabled to determine FIPS state: %v", err) | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will log an error when the file does not exists, it not clear to me does the kernel always has the file or is that set to some CONFIG_ options in the kernel. If so we should certainly ignore ENOENT?
Second, this logs an error and then assumes fips is disabled, Given this is a security option should we not outright fail with the error (e.g. return the error to the caller)? I do realize MountsWithUIDGID() does not return an error so we would need to add a new function so maybe it is not worth it. Maybe it is not important enough but I always very much find it odd to log an error but then start the container anyway. Either way the issue is pre existing so I would not block this on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kernel always has that file, so there's no need to ignore ENOENT.
I can make the change to bubble up the error, but as you said, it's going to be a larger change because MountsWithUIDGID() does not currently fail. Maybe we should do that in a separate PR afterwards?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The kernel always has that file, so there's no need to ignore ENOENT.
@neverpanic not always. I work with systems where CONFIG_CRYPTO_FIPS is not always enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be fixed now.
affa37c
to
7e169c6
Compare
3f4818e
to
1b8afdf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one small nit otherwise LGTM
cc @TomSweeneyRedHat not sure if the fips changes here need any updates in the container RHEL docs.
pkg/subscriptions/subscriptions.go
Outdated
func shouldAddFIPSMounts() bool { | ||
fips_enabled, err := os.ReadFile("/proc/sys/crypto/fips_enabled") | ||
if err != nil { | ||
if !os.IsNotExist(err) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new code should use errors.Is(err, fs.ErrNotExist)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used os.ErrNotExist
, since that was already imported.
/etc/system-fips is deprecated in CentOS Stream 9 and has been removed from CentOS Stream 10. UBI8 containers still contain /etc/system-fips -> /run/secrets/system-fips, but UBI9 containers do not, so creating /run/secrets/system-fips on UBI9 (or later) does not serve a useful purpose. See [1, 2]. Instead of checking /etc/system-fips to determine whether FIPS mode is enabled on the host, read /proc/sys/crypto/fips_enabled, which works for all supported RHEL versions and likely even earlier. In CentOS 10 Stream, the crypto-policies package does now contain /usr/share/crypto-policies/default-fips-config, which is meant to serve as a file to bind-mount over /etc/crypto-policies/config when in FIPS mode [3]. Manual creation of this file is thus no longer required in containers/common for modern containers. Using this file as a source also enables improvements in crypto-policies tooling which will now - unmount the two bind mounts when a user manually changes the policy using update-crypto-policies --set, something which was previously broken in containers because /etc/crypto-policies/config was a read-only bind-mount, and - unmount and restore the two bind-mounts when the crypto-policies package is updated. The crypto-policies package will only do these steps if the the bind mounts for crypto-policies use the /usr/share/crypto-policies/default-fips-config file as source, so it makes sense for containers/common to switch to that. [1]: https://gitlab.com/redhat-crypto/fedora-crypto-policies/-/merge_requests/111 [2]: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/9.0_release_notes/deprecated_functionality#deprecated-functionality_security [3]: https://gitlab.com/redhat-crypto/fedora-crypto-policies/-/commit/04ceadccfc07e5946b08157d06ca5c0d5a229d92 Closes: containers#2130 Related: https://issues.redhat.com/browse/CRYPTO-13556 Signed-off-by: Clemens Lang <[email protected]>
1b8afdf
to
abf2f6b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Nice! |
/approve |
@kwilczynski: changing LGTM is restricted to collaborators In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
@mtrmac Mind giving this a final review/merge? I think it would be good to get this into podman 5.3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: giuseppe, kwilczynski, Luap99, neverpanic The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
First, creating a global file /etc/system-fips was never a good idea for testing as it affects other running tests at the same time. And as of a recent change to FIPS mounts[1] we no longer use the file so the test breaks with c/common v0.61. Instead it uses the kernel file /proc/sys/crypto/fips_enabled which requires the real fips mode to be activated and that in turn requires a reboot. As such this is not somthing that can be tested in upstream CI like that. [1] containers/common#2174 Signed-off-by: Paul Holzinger <[email protected]>
/etc/system-fips
is deprecated in CentOS Stream 9 and has been removed from CentOS Stream 10. UBI8 containers still contain/etc/system-fips -> /run/secrets/system-fips
, but UBI9 containers do not, so creating/run/secrets/system-fips
on UBI9 (or later) does not serve a useful purpose. See [1, 2].Instead of checking
/etc/system-fips
to determine whether FIPS mode is enabled on the host, read/proc/sys/crypto/fips_enabled
, which works for all supported RHEL versions and likely even earlier.In CentOS 10 Stream, the crypto-policies package does now contain
/usr/share/crypto-policies/default-fips-config
, which is meant to serve as a file to bind-mount over/etc/crypto-policies/config
when in FIPS mode [3]. Manual creation of this file is thus no longer required in containers/common for modern containers. Using this file as a source also enables improvements in crypto-policies tooling which will nowupdate-crypto-policies --set
, something which was previously broken in containers because/etc/crypto-policies/config
was a read-only bind-mount, and/usr/share/crypto-policies/default-fips-config
file as source, so it makes sense for containers/common to switch to that.
Closes: #2130
Related: https://issues.redhat.com/browse/CRYPTO-13556