core: Process systemctl preset in %post

Rather than entirely symlinking `systemctl` → `/bin/true`, in order
to e.g. have NetworkManager be enabled, we need to process presets.

This is one of the things that's breaking FAHC where I did a
`--ex-unified-core` deployment.

(Actually it's a bit tempting to run a mass preset pass at the end,
 but for now let's do this)

Implementation note: this is our first use of GResources, which
is a handy way to embed data into our final binary.

Closes: https://github.com/projectatomic/rpm-ostree/issues/550

Closes: #1148
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-12-13 17:17:03 -05:00 committed by Atomic Bot
parent 9ff9f6c997
commit 6a2962fd8b
5 changed files with 42 additions and 4 deletions

View File

@ -86,6 +86,11 @@ CLEANFILES += $(gperf_gperf_sources:-gperf.gperf=-gperf.c)
nodist_librpmostreepriv_la_SOURCES = src/libpriv/rpmostree-script-gperf.c
rpmostree-libpriv-gresources.c: src/libpriv/gresources.xml Makefile $(shell glib-compile-resources --sourcedir=$(srcdir)/src/libpriv --generate-dependencies $(srcdir)/src/libpriv/gresources.xml)
$(AM_V_GEN) glib-compile-resources --target=$@ --sourcedir=$(srcdir)/src/libpriv --generate-source --c-name _rpmostree_ $<
BUILT_SOURCES += rpmostree-libpriv-gresources.c
librpmostreepriv_la_SOURCES += rpmostree-libpriv-gresources.c
AM_V_GPERF = $(AM_V_GPERF_$(V))
AM_V_GPERF_ = $(AM_V_GPERF_$(AM_DEFAULT_VERBOSITY))
AM_V_GPERF_0 = @echo " GPERF " $@;

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/rpmostree">
<file>systemctl-wrapper.sh</file>
</gresource>
</gresources>

View File

@ -3421,8 +3421,10 @@ rpmostree_context_assemble (RpmOstreeContext *self,
error))
return FALSE;
/* Also neuter systemctl - at least glusterfs calls it
* in %post without disallowing errors. Anyways,
/* Also neuter systemctl - at least glusterfs for example calls `systemctl
* start` in its %post which both violates Fedora policy and also will not
* work with the rpm-ostree model.
* See also https://github.com/projectatomic/rpm-ostree/issues/550
*/
if (renameat (tmprootfs_dfd, "usr/bin/systemctl",
tmprootfs_dfd, "usr/bin/systemctl.rpmostreesave") < 0)
@ -3435,8 +3437,18 @@ rpmostree_context_assemble (RpmOstreeContext *self,
else
{
have_systemctl = TRUE;
if (symlinkat ("true", tmprootfs_dfd, "usr/bin/systemctl") < 0)
return glnx_throw_errno_prefix (error, "symlinkat(usr/bin/systemctl)");
g_autoptr(GBytes) systemctl_wrapper = g_resources_lookup_data ("/rpmostree/systemctl-wrapper.sh",
G_RESOURCE_LOOKUP_FLAGS_NONE,
error);
if (!systemctl_wrapper)
return FALSE;
size_t len;
const guint8* buf = g_bytes_get_data (systemctl_wrapper, &len);
if (!glnx_file_replace_contents_with_perms_at (tmprootfs_dfd, "usr/bin/systemctl",
buf, len, 0755, (uid_t) -1, (gid_t) -1,
GLNX_FILE_REPLACE_NODATASYNC,
cancellable, error))
return FALSE;
}
/* Necessary for unified core to work with semanage calls in %post, like container-selinux */

View File

@ -0,0 +1,11 @@
#!/usr/bin/bash
# Used by rpmostree-core.c to intercept `systemctl` operations. We want to
# handle `preset`, and ignore everything else such as `start`/`stop` etc.
# See also https://github.com/projectatomic/rpm-ostree/issues/550
for arg in "$@"; do
if [[ $arg == preset ]]; then
exec /usr/bin/systemctl.rpmostreesave "$@"
fi
done
echo "rpm-ostree-systemctl: Ignored non-preset command:" "$@"

View File

@ -34,6 +34,10 @@ ostree --repo=${repobuild} ls -R ${treeref} /usr/share/man > manpages.txt
assert_file_has_content manpages.txt man5/ostree.repo.5
echo "ok manpages"
ostree --repo=${repobuild} ls ${treeref} usr/etc/systemd/system/multi-user.target.wants/chronyd.service > preset.txt
assert_file_has_content_literal preset.txt '-> /usr/lib/systemd/system/chronyd.service'
echo "ok systemctl preset"
ostree --repo=${repobuild} ls ${treeref} /usr/bin/su > su.txt
assert_file_has_content su.txt '^-04[71][0-7][0-7]'
echo "ok setuid"