libpriv: Introduce an rpmostree-kernel.[ch] for dracut
Since the dracut run is now separated from the rest of postprocess, we change it to use the bwrap API diretly, and this lets use the new _IMMUTABLE bwrap type. This will make it easier to reuse for client-side initramfs regeneration. Splitting this off makes it also easier to simplify the remaining mutable usage in postprocess.c. Closes: #560 Approved by: jlebon
This commit is contained in:
parent
f0ec738376
commit
e1cdfa1712
@ -32,6 +32,8 @@ librpmostreepriv_la_SOURCES = \
|
|||||||
src/libpriv/rpmostree-core.h \
|
src/libpriv/rpmostree-core.h \
|
||||||
src/libpriv/rpmostree-bwrap.c \
|
src/libpriv/rpmostree-bwrap.c \
|
||||||
src/libpriv/rpmostree-bwrap.h \
|
src/libpriv/rpmostree-bwrap.h \
|
||||||
|
src/libpriv/rpmostree-kernel.c \
|
||||||
|
src/libpriv/rpmostree-kernel.h \
|
||||||
src/libpriv/rpmostree-scripts.c \
|
src/libpriv/rpmostree-scripts.c \
|
||||||
src/libpriv/rpmostree-scripts.h \
|
src/libpriv/rpmostree-scripts.h \
|
||||||
src/libpriv/rpmostree-refsack.h \
|
src/libpriv/rpmostree-refsack.h \
|
||||||
|
125
src/libpriv/rpmostree-kernel.c
Normal file
125
src/libpriv/rpmostree-kernel.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013,2014,2017 Colin Walters <walters@verbum.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General
|
||||||
|
* Public License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
#include <ostree.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <utime.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libglnx.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gio/gunixinputstream.h>
|
||||||
|
#include <gio/gunixoutputstream.h>
|
||||||
|
|
||||||
|
#include "rpmostree-kernel.h"
|
||||||
|
#include "rpmostree-bwrap.h"
|
||||||
|
#include "rpmostree-util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
dracut_child_setup (gpointer data)
|
||||||
|
{
|
||||||
|
int fd = GPOINTER_TO_INT (data);
|
||||||
|
|
||||||
|
/* Move the tempfile fd to 3 (and without the cloexec flag) */
|
||||||
|
if (dup2 (fd, 3) < 0)
|
||||||
|
err (1, "dup2");
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
rpmostree_run_dracut (int rootfs_dfd,
|
||||||
|
char **argv,
|
||||||
|
int *out_initramfs_tmpfd,
|
||||||
|
char **out_initramfs_tmppath,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
/* Shell wrapper around dracut to write to the O_TMPFILE fd;
|
||||||
|
* at some point in the future we should add --fd X instead of -f
|
||||||
|
* to dracut.
|
||||||
|
*/
|
||||||
|
static const char rpmostree_dracut_wrapper_path[] = "usr/bin/rpmostree-dracut-wrapper";
|
||||||
|
/* This also hardcodes a few arguments */
|
||||||
|
static const char rpmostree_dracut_wrapper[] =
|
||||||
|
"#!/usr/bin/bash\n"
|
||||||
|
"set -euo pipefail\n"
|
||||||
|
"extra_argv=; if (dracut --help; true) | grep -q -e --reproducible; then extra_argv=\"--reproducible --gzip\"; fi\n"
|
||||||
|
"dracut $extra_argv -v --add ostree --tmpdir=/tmp -f /tmp/initramfs.img \"$@\"\n"
|
||||||
|
"cat /tmp/initramfs.img >/proc/self/fd/3\n";
|
||||||
|
glnx_fd_close int tmp_fd = -1;
|
||||||
|
g_autofree char *tmpfile_path = NULL;
|
||||||
|
g_autoptr(RpmOstreeBwrap) bwrap = NULL;
|
||||||
|
|
||||||
|
/* First tempfile is just our shell script */
|
||||||
|
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "usr/bin",
|
||||||
|
O_RDWR | O_CLOEXEC,
|
||||||
|
&tmp_fd, &tmpfile_path,
|
||||||
|
error))
|
||||||
|
goto out;
|
||||||
|
if (glnx_loop_write (tmp_fd, rpmostree_dracut_wrapper, sizeof (rpmostree_dracut_wrapper)) < 0
|
||||||
|
|| fchmod (tmp_fd, 0755) < 0)
|
||||||
|
{
|
||||||
|
glnx_set_error_from_errno (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glnx_link_tmpfile_at (rootfs_dfd, GLNX_LINK_TMPFILE_NOREPLACE,
|
||||||
|
tmp_fd, tmpfile_path, rootfs_dfd, rpmostree_dracut_wrapper_path,
|
||||||
|
error))
|
||||||
|
goto out;
|
||||||
|
/* We need to close the writable FD now to be able to exec it */
|
||||||
|
close (tmp_fd); tmp_fd = -1;
|
||||||
|
|
||||||
|
/* Second tempfile is the initramfs contents */
|
||||||
|
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "tmp",
|
||||||
|
O_WRONLY | O_CLOEXEC,
|
||||||
|
&tmp_fd, &tmpfile_path,
|
||||||
|
error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
bwrap = rpmostree_bwrap_new (rootfs_dfd, RPMOSTREE_BWRAP_IMMUTABLE, error, NULL);
|
||||||
|
if (!bwrap)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Set up argv and run */
|
||||||
|
rpmostree_bwrap_append_child_argv (bwrap, (char*)glnx_basename (rpmostree_dracut_wrapper_path), NULL);
|
||||||
|
for (char **iter = argv; iter && *iter; iter++)
|
||||||
|
rpmostree_bwrap_append_child_argv (bwrap, *iter, NULL);
|
||||||
|
|
||||||
|
rpmostree_bwrap_set_child_setup (bwrap, dracut_child_setup, GINT_TO_POINTER (tmp_fd));
|
||||||
|
|
||||||
|
if (!rpmostree_bwrap_run (bwrap, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
*out_initramfs_tmpfd = tmp_fd; tmp_fd = -1;
|
||||||
|
*out_initramfs_tmppath = g_steal_pointer (&tmpfile_path);
|
||||||
|
out:
|
||||||
|
if (tmpfile_path != NULL)
|
||||||
|
(void) unlink (tmpfile_path);
|
||||||
|
unlinkat (rootfs_dfd, rpmostree_dracut_wrapper_path, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
31
src/libpriv/rpmostree-kernel.h
Normal file
31
src/libpriv/rpmostree-kernel.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013,2014,2017 Colin Walters <walters@verbum.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation; either version 2 of the licence or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General
|
||||||
|
* Public License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostree.h>
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
rpmostree_run_dracut (int rootfs_dfd,
|
||||||
|
char **argv,
|
||||||
|
int *out_initramfs_tmpfd,
|
||||||
|
char **out_initramfs_tmppath,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
@ -38,6 +38,7 @@
|
|||||||
#include <gio/gunixoutputstream.h>
|
#include <gio/gunixoutputstream.h>
|
||||||
|
|
||||||
#include "rpmostree-postprocess.h"
|
#include "rpmostree-postprocess.h"
|
||||||
|
#include "rpmostree-kernel.h"
|
||||||
#include "rpmostree-bwrap.h"
|
#include "rpmostree-bwrap.h"
|
||||||
#include "rpmostree-passwd-util.h"
|
#include "rpmostree-passwd-util.h"
|
||||||
#include "rpmostree-rpm-util.h"
|
#include "rpmostree-rpm-util.h"
|
||||||
@ -50,19 +51,17 @@ typedef enum {
|
|||||||
RPMOSTREE_POSTPROCESS_BOOT_LOCATION_NEW
|
RPMOSTREE_POSTPROCESS_BOOT_LOCATION_NEW
|
||||||
} RpmOstreePostprocessBootLocation;
|
} RpmOstreePostprocessBootLocation;
|
||||||
|
|
||||||
|
/* This bwrap case is for treecompose which isn't isn't yet operating on
|
||||||
|
* hardlinks, so we just bind mount things mutably.
|
||||||
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
run_sync_in_root_at (int rootfs_fd,
|
run_bwrap_mutably (int rootfs_fd,
|
||||||
const char *binpath,
|
const char *binpath,
|
||||||
char **child_argv,
|
char **child_argv,
|
||||||
GSpawnChildSetupFunc setup_func,
|
|
||||||
gpointer data,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autoptr(RpmOstreeBwrap) bwrap = NULL;
|
g_autoptr(RpmOstreeBwrap) bwrap = NULL;
|
||||||
|
|
||||||
/* Bind all of the primary toplevel dirs; unlike the script case, treecompose
|
|
||||||
* isn't yet operating on hardlinks, so we can just bind mount things mutably.
|
|
||||||
*/
|
|
||||||
bwrap = rpmostree_bwrap_new (rootfs_fd, RPMOSTREE_BWRAP_MUTATE_FREELY, error,
|
bwrap = rpmostree_bwrap_new (rootfs_fd, RPMOSTREE_BWRAP_MUTATE_FREELY, error,
|
||||||
"--bind", "var", "/var",
|
"--bind", "var", "/var",
|
||||||
"--bind", "etc", "/etc",
|
"--bind", "etc", "/etc",
|
||||||
@ -83,9 +82,6 @@ run_sync_in_root_at (int rootfs_fd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup_func)
|
|
||||||
rpmostree_bwrap_set_child_setup (bwrap, setup_func, data);
|
|
||||||
|
|
||||||
if (!rpmostree_bwrap_run (bwrap, error))
|
if (!rpmostree_bwrap_run (bwrap, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -255,88 +251,6 @@ find_ensure_one_subdirectory (int rootfs_dfd,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dracut_child_setup (gpointer data)
|
|
||||||
{
|
|
||||||
int fd = GPOINTER_TO_INT (data);
|
|
||||||
|
|
||||||
/* Move the tempfile fd to 3 (and without the cloexec flag) */
|
|
||||||
if (dup2 (fd, 3) < 0)
|
|
||||||
err (1, "dup2");
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
run_dracut (int rootfs_dfd,
|
|
||||||
char **argv,
|
|
||||||
int *out_initramfs_tmpfd,
|
|
||||||
char **out_initramfs_tmppath,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
gboolean ret = FALSE;
|
|
||||||
/* Shell wrapper around dracut to write to the O_TMPFILE fd;
|
|
||||||
* at some point in the future we should add --fd X instead of -f
|
|
||||||
* to dracut.
|
|
||||||
*/
|
|
||||||
static const char rpmostree_dracut_wrapper_path[] = "usr/bin/rpmostree-dracut-wrapper";
|
|
||||||
/* This also hardcodes a few arguments */
|
|
||||||
static const char rpmostree_dracut_wrapper[] =
|
|
||||||
"#!/usr/bin/bash\n"
|
|
||||||
"set -euo pipefail\n"
|
|
||||||
"extra_argv=; if (dracut --help; true) | grep -q -e --reproducible; then extra_argv=\"--reproducible --gzip\"; fi\n"
|
|
||||||
"dracut $extra_argv -v --add ostree --tmpdir=/tmp -f /tmp/initramfs.img \"$@\"\n"
|
|
||||||
"cat /tmp/initramfs.img >/proc/self/fd/3\n";
|
|
||||||
g_autoptr(GPtrArray) child_argv = g_ptr_array_new ();
|
|
||||||
glnx_fd_close int tmp_fd = -1;
|
|
||||||
g_autofree char *tmpfile_path = NULL;
|
|
||||||
|
|
||||||
/* First tempfile is just our shell script */
|
|
||||||
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "usr/bin",
|
|
||||||
O_RDWR | O_CLOEXEC,
|
|
||||||
&tmp_fd, &tmpfile_path,
|
|
||||||
error))
|
|
||||||
goto out;
|
|
||||||
if (glnx_loop_write (tmp_fd, rpmostree_dracut_wrapper, sizeof (rpmostree_dracut_wrapper)) < 0
|
|
||||||
|| fchmod (tmp_fd, 0755) < 0)
|
|
||||||
{
|
|
||||||
glnx_set_error_from_errno (error);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!glnx_link_tmpfile_at (rootfs_dfd, GLNX_LINK_TMPFILE_NOREPLACE,
|
|
||||||
tmp_fd, tmpfile_path, rootfs_dfd, rpmostree_dracut_wrapper_path,
|
|
||||||
error))
|
|
||||||
goto out;
|
|
||||||
/* We need to close the writable FD now to be able to exec it */
|
|
||||||
close (tmp_fd); tmp_fd = -1;
|
|
||||||
|
|
||||||
/* Second tempfile is the initramfs contents */
|
|
||||||
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "tmp",
|
|
||||||
O_WRONLY | O_CLOEXEC,
|
|
||||||
&tmp_fd, &tmpfile_path,
|
|
||||||
error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Set up argv and run */
|
|
||||||
g_ptr_array_add (child_argv, (char*)glnx_basename (rpmostree_dracut_wrapper_path));
|
|
||||||
for (char **iter = argv; iter && *iter; iter++)
|
|
||||||
g_ptr_array_add (child_argv, *iter);
|
|
||||||
g_ptr_array_add (child_argv, NULL);
|
|
||||||
if (!run_sync_in_root_at (rootfs_dfd, (char*)child_argv->pdata[0], (char**)child_argv->pdata,
|
|
||||||
dracut_child_setup, GINT_TO_POINTER (tmp_fd),
|
|
||||||
error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = TRUE;
|
|
||||||
*out_initramfs_tmpfd = tmp_fd; tmp_fd = -1;
|
|
||||||
*out_initramfs_tmppath = g_steal_pointer (&tmpfile_path);
|
|
||||||
out:
|
|
||||||
if (tmpfile_path != NULL)
|
|
||||||
(void) unlink (tmpfile_path);
|
|
||||||
unlinkat (rootfs_dfd, rpmostree_dracut_wrapper_path, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_kernel_prep (int rootfs_dfd,
|
do_kernel_prep (int rootfs_dfd,
|
||||||
JsonObject *treefile,
|
JsonObject *treefile,
|
||||||
@ -408,8 +322,7 @@ do_kernel_prep (int rootfs_dfd,
|
|||||||
|
|
||||||
{
|
{
|
||||||
char *child_argv[] = { "depmod", (char*)kver, NULL };
|
char *child_argv[] = { "depmod", (char*)kver, NULL };
|
||||||
if (!run_sync_in_root_at (rootfs_dfd, "depmod", child_argv,
|
if (!run_bwrap_mutably (rootfs_dfd, "depmod", child_argv, error))
|
||||||
NULL, NULL, error))
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +358,7 @@ do_kernel_prep (int rootfs_dfd,
|
|||||||
}
|
}
|
||||||
g_ptr_array_add (dracut_argv, NULL);
|
g_ptr_array_add (dracut_argv, NULL);
|
||||||
|
|
||||||
if (!run_dracut (rootfs_dfd, (char**)dracut_argv->pdata,
|
if (!rpmostree_run_dracut (rootfs_dfd, (char**)dracut_argv->pdata,
|
||||||
&initramfs_tmp_fd, &initramfs_tmp_path,
|
&initramfs_tmp_fd, &initramfs_tmp_path,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
@ -1839,8 +1752,7 @@ rpmostree_treefile_postprocessing (int rootfs_fd,
|
|||||||
|
|
||||||
{
|
{
|
||||||
char *child_argv[] = { binpath, NULL };
|
char *child_argv[] = { binpath, NULL };
|
||||||
if (!run_sync_in_root_at (rootfs_fd, binpath, child_argv,
|
if (!run_bwrap_mutably (rootfs_fd, binpath, child_argv, error))
|
||||||
NULL, NULL, error))
|
|
||||||
{
|
{
|
||||||
g_prefix_error (error, "While executing postprocessing script '%s': ", bn);
|
g_prefix_error (error, "While executing postprocessing script '%s': ", bn);
|
||||||
goto out;
|
goto out;
|
||||||
|
Loading…
Reference in New Issue
Block a user