core,kernel: Set up /etc/passwd for dracut
This fixes a longstanding spew of error messages from the initramfs because we don't have nss-altfiles set up there. Rather than trying to do it, just do the dance of re-synthesizing `/etc/passwd` as it traditionally looks around running dracut, the same as we do for scripts during core layering. Yes, this is all a mess and hopefully I'll get to sysusers soon...
This commit is contained in:
parent
9c4e7590b2
commit
b797a42f3e
@ -3798,6 +3798,49 @@ rpmostree_context_get_kernel_changed (RpmOstreeContext *self)
|
||||
return self->kernel_changed;
|
||||
}
|
||||
|
||||
/* We have a messy dance in dealing with /usr/etc and /etc; the
|
||||
* current model is basically to have it be /etc whenever we're running
|
||||
* any code.
|
||||
*/
|
||||
gboolean
|
||||
rpmostree_core_undo_usretc (int rootfs_dfd,
|
||||
gboolean *renamed_etc,
|
||||
GError **error)
|
||||
{
|
||||
if (!glnx_fstatat_allow_noent (rootfs_dfd, "usr/etc", NULL, 0, error))
|
||||
return FALSE;
|
||||
if (errno == 0)
|
||||
{
|
||||
/* In general now, we place contents in /etc when running scripts */
|
||||
if (!glnx_renameat (rootfs_dfd, "usr/etc", rootfs_dfd, "etc", error))
|
||||
return FALSE;
|
||||
/* But leave a compat symlink, as we used to bind mount, so scripts
|
||||
* could still use that too.
|
||||
*/
|
||||
if (symlinkat ("../etc", rootfs_dfd, "usr/etc") < 0)
|
||||
return glnx_throw_errno_prefix (error, "symlinkat");
|
||||
*renamed_etc = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*renamed_etc = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
rpmostree_core_redo_usretc (int rootfs_dfd,
|
||||
GError **error)
|
||||
{
|
||||
/* Remove the symlink and swap back */
|
||||
if (!glnx_unlinkat (rootfs_dfd, "usr/etc", 0, error))
|
||||
return FALSE;
|
||||
if (!glnx_renameat (rootfs_dfd, "etc", rootfs_dfd, "usr/etc", error))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_one_ostree_layer (RpmOstreeContext *self,
|
||||
int rootfs_dfd,
|
||||
@ -4129,20 +4172,9 @@ rpmostree_context_assemble (RpmOstreeContext *self,
|
||||
gboolean skip_sanity_check = FALSE;
|
||||
g_variant_dict_lookup (self->spec->dict, "skip-sanity-check", "b", &skip_sanity_check);
|
||||
|
||||
if (!glnx_fstatat_allow_noent (tmprootfs_dfd, "usr/etc", NULL, 0, error))
|
||||
gboolean renamed_etc = FALSE;
|
||||
if (!rpmostree_core_undo_usretc (tmprootfs_dfd, &renamed_etc, error))
|
||||
return FALSE;
|
||||
gboolean renamed_etc = (errno == 0);
|
||||
if (renamed_etc)
|
||||
{
|
||||
/* In general now, we place contents in /etc when running scripts */
|
||||
if (!glnx_renameat (tmprootfs_dfd, "usr/etc", tmprootfs_dfd, "etc", error))
|
||||
return FALSE;
|
||||
/* But leave a compat symlink, as we used to bind mount, so scripts
|
||||
* could still use that too.
|
||||
*/
|
||||
if (symlinkat ("../etc", tmprootfs_dfd, "usr/etc") < 0)
|
||||
return glnx_throw_errno_prefix (error, "symlinkat");
|
||||
}
|
||||
|
||||
/* NB: we're not running scripts right now for removals, so this is only for overlays and
|
||||
* replacements */
|
||||
@ -4388,14 +4420,8 @@ rpmostree_context_assemble (RpmOstreeContext *self,
|
||||
}
|
||||
|
||||
/* Undo the /etc move above */
|
||||
if (renamed_etc)
|
||||
{
|
||||
/* Remove the symlink and swap back */
|
||||
if (!glnx_unlinkat (tmprootfs_dfd, "usr/etc", 0, error))
|
||||
if (renamed_etc && !rpmostree_core_redo_usretc (tmprootfs_dfd, error))
|
||||
return FALSE;
|
||||
if (!glnx_renameat (tmprootfs_dfd, "etc", tmprootfs_dfd, "usr/etc", error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* And clean up var/tmp, we don't want it in commits */
|
||||
if (!glnx_shutil_rm_rf_at (tmprootfs_dfd, "var/tmp", cancellable, error))
|
||||
|
@ -230,3 +230,11 @@ gboolean rpmostree_context_commit (RpmOstreeContext *self,
|
||||
char **out_commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean
|
||||
rpmostree_core_undo_usretc (int rootfs_dfd,
|
||||
gboolean *renamed_etc,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
rpmostree_core_redo_usretc (int rootfs_dfd,
|
||||
GError **error);
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <gio/gunixinputstream.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
|
||||
#include "rpmostree-passwd-util.h"
|
||||
#include "rpmostree-core.h"
|
||||
#include "rpmostree-kernel.h"
|
||||
#include "rpmostree-bwrap.h"
|
||||
#include "rpmostree-util.h"
|
||||
@ -496,6 +498,21 @@ rpmostree_run_dracut (int rootfs_dfd,
|
||||
g_auto(GLnxTmpfile) tmpf = { 0, };
|
||||
g_autoptr(GBytes) random_cpio_data = NULL;
|
||||
|
||||
/* We need to have /etc/passwd since dracut doesn't have altfiles
|
||||
* today. Though maybe in the future we should add it, but
|
||||
* in the end we want to use systemd-sysusers of course.
|
||||
**/
|
||||
gboolean renamed_etc = FALSE;
|
||||
if (!rpmostree_core_undo_usretc (rootfs_dfd, &renamed_etc, error))
|
||||
return FALSE;
|
||||
gboolean have_passwd = FALSE;
|
||||
if (!rpmostree_passwd_prepare_rpm_layering (rootfs_dfd,
|
||||
NULL,
|
||||
&have_passwd,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* Previously we used to error out if argv or rebuild_from_initramfs were both
|
||||
* not set; now we simply use the defaults (which in Fedora today also means
|
||||
* implicitly hostonly). That case is for `rpm-ostree override replace
|
||||
@ -607,6 +624,12 @@ rpmostree_run_dracut (int rootfs_dfd,
|
||||
if (rebuild_from_initramfs)
|
||||
(void) unlinkat (rootfs_dfd, rebuild_from_initramfs, 0);
|
||||
|
||||
if (have_passwd && !rpmostree_passwd_complete_rpm_layering (rootfs_dfd, error))
|
||||
goto out;
|
||||
|
||||
if (renamed_etc && !rpmostree_core_redo_usretc (rootfs_dfd, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
*out_initramfs_tmpf = tmpf; tmpf.initialized = FALSE; /* Transfer */
|
||||
out:
|
||||
|
@ -21,6 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
@ -129,5 +129,11 @@ initramfs=$(vm_cmd grep ^initrd /boot/loader/entries/ostree-2-$osname.conf | sed
|
||||
test -n "${initramfs}"
|
||||
vm_cmd lsinitrd $initramfs > lsinitrd.txt
|
||||
assert_not_file_has_content lsinitrd.txt /etc/rpmostree-initramfs-testing
|
||||
|
||||
echo "ok initramfs disable"
|
||||
# while we're here, sanity check we also ship /etc/passwd in the initrd to
|
||||
# soothe systemd-udevd
|
||||
for x in passwd group; do
|
||||
assert_file_has_content lsinitrd.txt " etc/$x"
|
||||
done
|
||||
rm -f lsinitrd.txt
|
||||
echo "ok initramfs has passwd"
|
||||
|
Loading…
Reference in New Issue
Block a user