-
Notifications
You must be signed in to change notification settings - Fork 208
rpmostree-core: Emulate new %sysusers RPM scriplet #5334
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
Conversation
|
Doesn't look too terrible ;) |
|
PR description is my understanding, may not be fully accurate, suggestions welcomed (and then I'll update the commit message). |
|
The code is written as it is specifically in order not to do this sort of thing. There's a long comment to that effect: so it seems like we might want to try and honor that goal somehow. Maybe special-case systemd and do something like this?
if we don't want to do that, we should probably at least update the comment... |
|
also, doing it this way doesn't feel 100% safe, because it seems like it would rely on systemd coming very early in the %post loop - because it must be done before any other package containing a file owned by a user or group that would be created by systemd's %post - but we don't appear to do anything to guarantee that that's the case? |
|
That should work but would make this very specific to the systemd package name. I agree that this is a bit of a brute force logic but maybe this is safer at the cost of re-reading the files a bit often? |
|
well, then, how about:
that seems most similar to what rpm is now doing, i guess? |
Agree that this is not a "fix", but more of a workaround. Ideally, we would add the RPM sysusers scriptlet support to rpm-ostree as a specific phase here before running the %post. |
|
For this to be "correct" (i.e. matching how RPM does it) we would have to re-implement rpm-software-management/rpm@009d139 as far as I understand. |
That could be another option. |
|
i'm trying to figure out how to subvert the 'run a package script' bits to just run a script we make up on the fly... |
|
rpm-ostree runs post-process scripts via https://github.com/coreos/rpm-ostree/blob/main/rust/src/composepost.rs#L515, so we should be able to directly add a call to sysusers using a similar logic. |
|
well, Ii'm trying to hook into the various levels of script running function in src/libpriv/rpmostree-scripts.cxx , which does more or less the same. But it's kinda tedious to figure out if there's a neat way to slip in, it's all tied into RPM business logic. but I don't want to repeat all the bwrap stuff... for now I guess I'll just test this PR as-is, if it at least fixes ostree builds for now that's better than what we have, we can slap it in as a downstream patch till Colin or someone can decide what the best long-term fix is... |
|
it does look like this works around the issue for now, so I'll go ahead and backport it downstream officially. I'll try and figure out if there's a significant impact on run time, too, once the test completes. |
b3217c7 to
ae2c0d2
Compare
|
Rebased and updated the commit description |
|
From a discussion with Jonathan, this will not work for package layering as the systemd |
|
Whipped this up while chatting with @travier: diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx
index 70905996..208696fe 100644
--- a/src/libpriv/rpmostree-core.cxx
+++ b/src/libpriv/rpmostree-core.cxx
@@ -4422,6 +4422,26 @@ rpmostree_context_assemble (RpmOstreeContext *self, GCancellable *cancellable, G
progress->end ("");
+ /* if the %__systemd_sysusers macro is defined, that _very likely_
+ * means that we're using an rpm with built-in sysusers support:
+ * https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers Ideally,
+ * librpm would expose that part as a public API but it's currently just
+ * done during the transaction. So here we just do it ourselves (though a bit
+ * differently; librpm checks for the user/group provides before proceeding to call
+ * sysusers _just_ for that package. Here we do it for all of them... See also:
+ * https://github.com/coreos/rpm-ostree/issues/5333 */
+ g_autofree char *sysusers_cmd = rpmExpand ("%__systemd_sysusers", NULL);
+ if (sysusers_cmd && *sysusers_cmd)
+ {
+ CXX_TRY_VAR (bwrap,
+ rpmostreecxx::bubblewrap_new_with_mutability (
+ tmprootfs_dfd, rpmostreecxx::BubblewrapMutability::MutateFreely),
+ error);
+ bwrap->append_child_arg (sysusers_cmd);
+ if (!CXX (bwrap->run (*cancellable), error))
+ return glnx_prefix_error (error, "Running systemd-sysusers (%s)", sysusers_cmd);
+ }
+
/* Some packages expect to be able to make temporary files here
* for obvious reasons, but we otherwise make `/var` read-only.
*/Not tested... |
|
The approach of running systemd-sysusers "wholesale" does seem to match with the current design.
Hmm don't we need mutability? Though I forget if that means just |
Ahh I think you're right. I thought the reverse and that it only implied |
|
Hum, I get: Looks like everything is already in So now the macro is not expanded. |
|
This fails weirdly on my systems which seems to point that there is another bug somewhere else: The |
ae2c0d2 to
36b1bd5
Compare
Could you expand on what you mean? Do you mean that it's not matching the design in RPM or the one in rpm-ostree? |
36b1bd5 to
d8179cd
Compare
Is that from |
|
This fails similarly in CI here: I don't think it's from sysusers. Likely something not correct in the patch here. The container build (that does not include sysusers) rightly failed on the hardcoded sysusers binary path. |
d8179cd to
84c4a22
Compare
|
This was from a previous run. I didn't refresh the page. |
84c4a22 to
7c21d84
Compare
|
There is something unexpected with the RPM macro expansion. Edit: The macro was being expanded on the host, not the composed rootfs, and I'm still running F41. |
b1ad7fa to
8baa2a8
Compare
|
I've reworked the test to test all Fedora releases still stable + f42. |
110fb83 to
e90ba11
Compare
|
Updated backport PR as we'll need this down to F42: https://src.fedoraproject.org/rpms/rpm-ostree/pull-request/67 |
|
Arg, it timed out on a Pagure access issue: |
35f6f5f to
7918173
Compare
- Add systemd-standalone-sysusers to container for F42+. Starting with Fedora 42, RPM will use sysusers to create users and we emulate that support by running sysusers in the rootfs before running other scriptlets. See: coreos#5333 - Test with Fedora 41 by default - Replace dnf with dnf5 for F41+ See: https://fedoraproject.org/wiki/Changes/SwitchToDnf5 - tests/compose-image: Remove fedora-repos-modular Support for modularity has been removed from Fedora. See: https://fedoraproject.org/wiki/Changes/RetireModularity
7918173 to
9eb66a4
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. One comment, but not worth a respin.
Thanks for expanding the test matrix!
| /* if the %__systemd_sysusers macro is defined, that _very likely_ means that | ||
| * we're using an rpm with built-in sysusers support: | ||
| * https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers | ||
| * Ideally, librpm would expose that part as a public API but it's currently | ||
| * just done during the transaction. So here we just do it ourselves, though | ||
| * a bit differently: librpm checks for the user/group provides before | ||
| * proceeding to call sysusers _just_ for that package. Here we do it for all | ||
| * of them. See also: https://github.com/coreos/rpm-ostree/issues/5333 */ |
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.
That comment should probably move to the Rust side now.
|
/retest |
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.
Only gave this a skim but looks sane to me.
|
|
||
| /// Run systemd-sysusers in the rootfs if the %__systemd_sysusers RPM macro is set. | ||
| pub(crate) fn run_sysusers(rootfs_dfd: i32) -> CxxResult<()> { | ||
| let args: Vec<_> = vec!["rpm", "--eval=%{?__systemd_sysusers}"] |
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.
Pointless nit: This can just be a static slice i.e. drop the vec!
Yes! Overdue for sure |
|
Regression in #5353. |
Hmm this may be that we're missing the nss-altfiles setup at this stage? That's a pretty bad bug if so |
Pointed out by Colin in coreos#5334 (comment).
In the work to rebase FCOS/RHCOS to fedora-bootc/rhel-bootc, I want to make it possible to opt out of the passwd/group bits baked in the minimal manifests (the problem there of course goes back to UID/GID drift issues -- this has caused issues as well on the IoT/Edge side). The current passwd/group files in the minimal manifest are both outdated and incomplete (most of it can in fact trace its lineage all the way back to Fedora Atomic Host). But more generally, in the FROM scratch flow, users _should_ have the ability to customize which user gets which UID. And one could imagine an option like `bootc-base-imagectl --passwd mypasswd --group mygroup` but (1) while the format is well-known, using it as an interface for building root filesystems is less so, and for example has no correspondence in the dnf world, and (2) such an interface implies taking ownership of all the entries. A more universal config file for this of course is systemd-sysusers. And recently, rpm-ostree learned in coreos#5334 to run systemd-sysusers prior to running any scriptlets for parity with similar functionality in RPM. So it basically works today in Fedora to completely ditch the monolithic passwd/group stuff and instead fixate UIDs via sysusers dropins. And then, combining that with `bootc-base-imagectl --add-dir`, this becomes possible to feed into the FROM scratch flow. We want to enable this flow in RHEL as well. All we need really is to force rpm-ostree to run systemd-sysusers even if the `%__systemd_sysusers` macro is undefined. Add a new `sysusers:` knob to the treefile. Currently, it takes one of two values: - `compose-auto`: `systemd-sysusers` is run at compose time if the `%__systemd_sysusers` RPM macro is defined (status quo) - `compose-forced`: `systemd-sysusers` is always run at compose time, even if the `%__systemd_sysusers` RPM macro is undefined And the net result of this then is it moves the emphasis further to systemd-sysusers as a way of ensuring UID coherence across builds and e.g. all the flexibility it implies around configurability/composition/overrides etc... (Worth noting that the systemd %post script actually always runs systemd-sysusers currently. But we can't rely on this because it's itself part of the RPM transaction and so has no effect on packages which have run before.) Then, for the bootc-base-imagectl flow, we can add a new `--sysusers` switch which sets this new option and crucially disables all the `check-passwd`/`check-group` logic. This is related to the nss-altfiles to sysusers migration though also somewhat independent. With `compose-forced`, the split back into `/usr/lib/{passwd,group}` still happens at the end of the compose. However I still went with the `sysusers:` enum and left room for other strategies to be implemented, since any strategy around nss-altfiles migration must take into account what semantics are desired from the systemd-sysusers run at compose time.
In the work to rebase FCOS/RHCOS to fedora-bootc/rhel-bootc, I want to make it possible to opt out of the passwd/group bits baked in the minimal manifests (the problem there of course goes back to UID/GID drift issues -- this has caused issues as well on the IoT/Edge side). The current passwd/group files in the minimal manifest are both outdated and incomplete (most of it can in fact trace its lineage all the way back to Fedora Atomic Host). But more generally, in the FROM scratch flow, users _should_ have the ability to customize which user gets which UID. And one could imagine an option like `bootc-base-imagectl --passwd mypasswd --group mygroup` but (1) while the format is well-known, using it as an interface for building root filesystems is less so, and for example has no correspondence in the dnf world, and (2) such an interface implies taking ownership of all the entries. A more universal config file for this of course is systemd-sysusers. And recently, rpm-ostree learned in coreos#5334 to run systemd-sysusers prior to running any scriptlets for parity with similar functionality in RPM. So it basically works today in Fedora to completely ditch the monolithic passwd/group stuff and instead fixate UIDs via sysusers dropins. And then, combining that with `bootc-base-imagectl --add-dir`, this becomes possible to feed into the FROM scratch flow. We want to enable this flow in RHEL as well. All we need really is to force rpm-ostree to run systemd-sysusers even if the `%__systemd_sysusers` macro is undefined. Add a new `sysusers:` knob to the treefile. Currently, it takes one of two values: - `compose-auto`: `systemd-sysusers` is run at compose time if the `%__systemd_sysusers` RPM macro is defined (status quo) - `compose-forced`: `systemd-sysusers` is always run at compose time, even if the `%__systemd_sysusers` RPM macro is undefined And the net result of this then is it moves the emphasis further to systemd-sysusers as a way of ensuring UID coherence across builds and e.g. all the flexibility it implies around configurability/composition/overrides etc... (Worth noting that the systemd %post script actually always runs systemd-sysusers currently. But we can't rely on this because it's itself part of the RPM transaction and so has no effect on packages which have run before.) Then, for the bootc-base-imagectl flow, we can add a new `--sysusers` switch which sets this new option and crucially disables all the `check-passwd`/`check-group` logic. This is related to the nss-altfiles to sysusers migration though also somewhat independent. With `compose-forced`, the split back into `/usr/lib/{passwd,group}` still happens at the end of the compose. However I still went with the `sysusers:` enum and left room for other strategies to be implemented, since any strategy around nss-altfiles migration must take into account what semantics are desired from the systemd-sysusers run at compose time.
In the work to rebase FCOS/RHCOS to fedora-bootc/rhel-bootc, I want to make it possible to opt out of the passwd/group bits baked in the minimal manifests (the problem there of course goes back to UID/GID drift issues -- this has caused issues as well on the IoT/Edge side). The current passwd/group files in the minimal manifest are both outdated and incomplete (most of it can in fact trace its lineage all the way back to Fedora Atomic Host). But more generally, in the FROM scratch flow, users _should_ have the ability to customize which user gets which UID. And one could imagine an option like `bootc-base-imagectl --passwd mypasswd --group mygroup` but (1) while the format is well-known, using it as an interface for building root filesystems is less so, and for example has no correspondence in the dnf world, and (2) such an interface implies taking ownership of all the entries. A more universal config file for this of course is systemd-sysusers. And recently, rpm-ostree learned in coreos#5334 to run systemd-sysusers prior to running any scriptlets for parity with similar functionality in RPM. So it basically works today in Fedora to completely ditch the monolithic passwd/group stuff and instead fixate UIDs via sysusers dropins. And then, combining that with `bootc-base-imagectl --add-dir`, this becomes possible to feed into the FROM scratch flow. We want to enable this flow in RHEL as well. All we need really is to force rpm-ostree to run systemd-sysusers even if the `%__systemd_sysusers` macro is undefined. Add a new experimental `sysusers:` knob to the treefile. Currently, it takes one of two values: - `compose-auto`: `systemd-sysusers` is run at compose time if the `%__systemd_sysusers` RPM macro is defined (status quo) - `compose-forced`: `systemd-sysusers` is always run at compose time, even if the `%__systemd_sysusers` RPM macro is undefined And the net result of this then is it moves the emphasis further to systemd-sysusers as a way of ensuring UID coherence across builds and e.g. all the flexibility it implies around configurability/composition/overrides etc... (Worth noting that the systemd %post script actually always runs systemd-sysusers currently. But we can't rely on this because it's itself part of the RPM transaction and so has no effect on packages which have run before.) Then, for the bootc-base-imagectl flow, we can add a new `--sysusers` switch which sets this new option and crucially disables all the `check-passwd`/`check-group` logic. This is related to the nss-altfiles to sysusers migration though also somewhat independent. With `compose-forced`, the split back into `/usr/lib/{passwd,group}` still happens at the end of the compose. However I still went with the `sysusers:` enum and left room for other strategies to be implemented, since any strategy around nss-altfiles migration must take into account what semantics are desired from the systemd-sysusers run at compose time.
In the work to rebase FCOS/RHCOS to fedora-bootc/rhel-bootc, I want to make it possible to opt out of the passwd/group bits baked in the minimal manifests (the problem there of course goes back to UID/GID drift issues -- this has caused issues as well on the IoT/Edge side). The current passwd/group files in the minimal manifest are both outdated and incomplete (most of it can in fact trace its lineage all the way back to Fedora Atomic Host). But more generally, in the FROM scratch flow, users _should_ have the ability to customize which user gets which UID. And one could imagine an option like `bootc-base-imagectl --passwd mypasswd --group mygroup` but (1) while the format is well-known, using it as an interface for building root filesystems is less so, and for example has no correspondence in the dnf world, and (2) such an interface implies taking ownership of all the entries. A more universal config file for this of course is systemd-sysusers. And recently, rpm-ostree learned in coreos#5334 to run systemd-sysusers prior to running any scriptlets for parity with similar functionality in RPM. So it basically works today in Fedora to completely ditch the monolithic passwd/group stuff and instead fixate UIDs via sysusers dropins. And then, combining that with `bootc-base-imagectl --add-dir`, this becomes possible to feed into the FROM scratch flow. We want to enable this flow in RHEL as well. All we need really is to force rpm-ostree to run systemd-sysusers even if the `%__systemd_sysusers` macro is undefined. Add a new experimental `sysusers:` knob to the treefile. Currently, it takes one of two values: - `compose-auto`: `systemd-sysusers` is run at compose time if the `%__systemd_sysusers` RPM macro is defined (status quo) - `compose-forced`: `systemd-sysusers` is always run at compose time, even if the `%__systemd_sysusers` RPM macro is undefined And the net result of this then is it moves the emphasis further to systemd-sysusers as a way of ensuring UID coherence across builds and e.g. all the flexibility it implies around configurability/composition/overrides etc... (Worth noting that the systemd %post script actually always runs systemd-sysusers currently. But we can't rely on this because it's itself part of the RPM transaction and so has no effect on packages which have run before.) Then, for the bootc-base-imagectl flow, we can add a new `--sysusers` switch which sets this new option and crucially disables all the `check-passwd`/`check-group` logic. This is related to the nss-altfiles to sysusers migration though also somewhat independent. With `compose-forced`, the split back into `/usr/lib/{passwd,group}` still happens at the end of the compose. However I still went with the `sysusers:` enum and left room for other strategies to be implemented, since any strategy around nss-altfiles migration must take into account what semantics are desired from the systemd-sysusers run at compose time.
rpmostree-core: Emulate new %sysusers RPM scriplet
As part of the migration to direct sysusers support in RPMs, packages
are no longer creating their users/groups in %pre scripts as they rely
on RPM to do the work in a built in %sysusers scriplet.
The RPM library does not expose a direct interface to call those
scriplets so we instead emulate the process by directly calling out to
the binary pointed by
%__systemd_sysusers, if it is set.See: https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers
See: rpm-software-management/rpm@009d139
See: fedora-silverblue/issue-tracker#636
See: https://gitlab.com/fedora/ostree/sig/-/issues/70
See: #5333
tests/compose-image: Test with Fedora 40, 41 & 42
Add systemd-standalone-sysusers to container for F42+.
Starting with Fedora 42, RPM will use sysusers to create users and we
emulate that support by running sysusers in the rootfs before running
other scriptlets.
See: Implement new RPM %sysusers script to fix user/group creation with sysusers #5333
Test with Fedora 41 by default
Replace dnf with dnf5 for F41+
See: https://fedoraproject.org/wiki/Changes/SwitchToDnf5
tests/compose-image: Remove fedora-repos-modular
Support for modularity has been removed from Fedora.
See: https://fedoraproject.org/wiki/Changes/RetireModularity