Skip to content
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

Introducing load_key hook in zfsbootmenu/lib/zfsbootmenu-core.sh #452

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/guides/fedora/_include/zbm-install-deps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Install all packages required to build a ZFSBootMenu image on Fedora:
.. code-block:: bash

dnf install -y \
systemd-boot-unsigned \
perl-YAML-PP \
perl-Sort-Versions \
perl-boolean \
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/fedora/_include/zfs-config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ Install required packages
dnf install -y https://dl.fedoraproject.org/pub/fedora/linux/releases/${VERSION_ID}/Everything/x86_64/os/Packages/k/kernel-devel-$(uname -r).rpm

dnf --releasever=${VERSION_ID} install -y \
https://zfsonlinux.org/fedora/zfs-release-2-2$(rpm --eval "%{dist}").noarch.rpm
https://zfsonlinux.org/fedora/zfs-release-2-3$(rpm --eval "%{dist}").noarch.rpm

dnf install -y zfs zfs-dracut
4 changes: 2 additions & 2 deletions docs/guides/fedora/uefi.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Workstation 37 UEFI
Workstation 38 UEFI
===================

.. |distribution| replace:: fedora
Expand All @@ -16,7 +16,7 @@ It assumes the following:
* Your system is x86_64
* You're mildly comfortable with ZFS, EFI and discovering system facts on your own (``lsblk``, ``dmesg``, ``gdisk``, ...)

Download `Fedora Workstation Live <https://download.fedoraproject.org/pub/fedora/linux/releases/37/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-37-1.7.iso>`_
Download `Fedora Workstation Live <https://download.fedoraproject.org/pub/fedora/linux/releases/38/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-38-1.6.iso>`_
, write it to a USB drive and boot your system in EFI mode.

.. include:: ../_include/efi-boot-check.rst
Expand Down
6 changes: 4 additions & 2 deletions docs/guides/general/container-building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,16 @@ ZFSBootMenu supports :ref:`custom hooks <zbm-dracut-options>` in three stages:
any pools.
2. ``setup`` hooks run after pools are imported, right before ZFSBootMenu will either boot a default environment or
present a menu.
3. ``teardown`` hooks run immediately before ZFSBootMenu will ``kexec`` the kernel for the selected environment.
3. ``load_key`` hooks run immediately before attempting to load a key for a locked filesystem. Each hook is called with the name of the encryption root to be unlocked as its sole argument.
4. ``teardown`` hooks run immediately before ZFSBootMenu will ``kexec`` the kernel for the selected environment.

When ``zbm-builder.sh`` runs, it will identify custom hooks as executable files in the respective subdirectories of its
build directory:

1. ``hooks.early_setup.d``
2. ``hooks.setup.d``
3. ``hooks.teardown.d``
3. ``hooks.load_key.d``
4. ``hooks.teardown.d``

For each hook directory that contains at least one executable file, ``zbm-builder.sh`` will write custom configuration
snippets for ``dracut`` and ``mkinitcpio`` that will include these files in the output images.
Expand Down
9 changes: 8 additions & 1 deletion docs/man/dist/man7/zfsbootmenu.7
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "ZFSBOOTMENU" "7" "2023-05-21" "" "ZFSBootMenu"
.TH "ZFSBOOTMENU" "7" "2023-07-17" "" "ZFSBootMenu"
.SH NAME
zfsbootmenu \- System Integration
.SH SYNOPSIS
Expand Down Expand Up @@ -436,6 +436,13 @@ kexec \-\-unload
should be sufficient to return to the main menu. Likewise, the hook may construct and execute its own \fIkexec\fP command to alter boot\-time parameters. This may be useful, for example, to allow ZFSBootMenu to select a boot environment and then restructure the boot process to launch a Xen kernel with the selected environment configured as dom0.
.UNINDENT
.UNINDENT
.sp
\fBzfsbootmenu_skip_gcc_s=yes\fP
.INDENT 0.0
.INDENT 3.5
The ZFSBootMenu module attempts to detect and install a copy of the library \fBlibgcc_s.so\fP in its initramfs image on glibc systems. Because several executables may have latent dependencies on this library via a \fBdlopen\fP call in glibc itself, a failure to detect and install the library will cause initramfs generation to fail. If the host system has no dependencies on \fBlibgcc_s.so\fP, set \fBzfsbootmenu_skip_gcc_s=yes\fP to avoid this failure. Alternatively, if \fBlibgcc_s.so\fP is present in an undetected location, set this option and configure Dracut to explicitly install the library.
.UNINDENT
.UNINDENT
.SH OPTIONS FOR MKINITCPIO
.sp
The \fBdracut\fP options specified above may also be specified in a mkinitcpio configuration file when \fBgenerate\-zbm\fP is configured to create images using \fBmkinitcpio\fP\&. However, whereas the \fB<executable\-list>\fP values in the dracut configuration should be specified as a single, space\-separated string; in the mkinitcpio configuration, each \fB<executable\-list>\fP value must be specified as a Bash array like the standard mkinitcpio arguments.
Expand Down
10 changes: 10 additions & 0 deletions docs/man/zfsbootmenu.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ In addition to standard dracut configuration options, the ZFSBootMenu dracut mod

Any installed hooks are run right before the ZFSBootMenu menu will be presented; ZFS pools will generally have been imported and the default boot environment will be available in the *BOOTFS* environment variable. Hooks will not be run if the countdown timer expires (or was set to zero) and the default boot environment is automatically selected. **Note:** The hooks may be run multiple times if the menu is invoked multiple times, e.g., by dropping to an emergency shell and then returning to the menu. If a script should only run once, the script is responsible for keeping track of this.

**zfsbootmenu_load_key=<executable-list>**

An optional variable specifying a space-separated list of paths to load-key hooks that will be installed in the ZFSBootMenu initramfs. Any path in the list **<executable-list>** that exists and is executable will be installed.

Any installed hooks are run immediately before ZFSBootMenu menu attempts to load a key for the encryption root of a locked filesystem. Each hook will be run with the name of the encryption root as its sole argument. If any hook exits with a non-zero return code, the load attempt will be aborted and the encryption root will not be unlocked. Hooks can be used to prepare keys needed to unlock the encryption root or may even attempt to unlock the root directly; a filesystem that is unlocked after the hooks have run will be considered to have had its keys successfully loaded. **Note:** The hooks may be run multiple times if keys for a given encryption root need to be loaded multiple times, e.g., by triggering a re-import of the pool. If a script should only run once, the script is responsible for keeping track of this.

**zfsbootmenu_teardown=<executable-list>**

An optional variable specifying a space-separated list of paths to teardown hooks that will be installed in the ZFSBootMenu initramfs. Any path in the list **<executable-list>** that exists and is executable will be installed.
Expand Down Expand Up @@ -261,6 +267,10 @@ In addition to standard dracut configuration options, the ZFSBootMenu dracut mod

should be sufficient to return to the main menu. Likewise, the hook may construct and execute its own *kexec* command to alter boot-time parameters. This may be useful, for example, to allow ZFSBootMenu to select a boot environment and then restructure the boot process to launch a Xen kernel with the selected environment configured as dom0.

**zfsbootmenu_skip_gcc_s=yes**

The ZFSBootMenu module attempts to detect and install a copy of the library **libgcc_s.so** in its initramfs image on glibc systems. Because several executables may have latent dependencies on this library via a **dlopen** call in glibc itself, a failure to detect and install the library will cause initramfs generation to fail. If the host system has no dependencies on **libgcc_s.so**, set **zfsbootmenu_skip_gcc_s=yes** to avoid this failure. Alternatively, if **libgcc_s.so** is present in an undetected location, set this option and configure Dracut to explicitly install the library.

.. _zbm-mkinitcpio-options:

Options for mkinitcpio
Expand Down
45 changes: 26 additions & 19 deletions dracut/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,22 @@ install() {
fi
done

# Workaround for zfsonlinux/zfs#4749 by ensuring libgcc_s.so(.1) is included
_ret=0
# If zpool requires libgcc_s.so*, dracut will track and include it
if ! ldd "$( command -v zpool )" | grep -qF 'libgcc_s.so'; then
# On systems with gcc-config (Gentoo, Funtoo, etc.), use it to find libgcc_s
if command -v gcc-config >/dev/null 2>&1; then
dracut_install "/usr/lib/gcc/$(s=$(gcc-config -c); echo "${s%-*}/${s##*-}")/libgcc_s.so.1"
_ret=$?
# Otherwise, use dracut's library installation function to find the right one
elif ! inst_libdir_file "libgcc_s.so*"; then
# If all else fails, just try looking for some gcc arch directory
dracut_install /usr/lib/gcc/*/*/libgcc_s.so*
_ret=$?
fi
fi

if [ ${_ret} -ne 0 ]; then
dfatal "Unable to install libgcc_s.so"
# Add libgcc_s as appropriate
local _libgcc_s
if ! _libgcc_s="$( find_libgcc_s )"; then
dfatal "Unable to locate libgcc_s.so"
exit 1
fi

local _lib
while read -r _lib ; do
[ -n "${_lib}" ] || continue
if ! dracut_install "${_lib}"; then
dfatal "Failed to install '${_lib}'"
exit 1
fi
done <<< "${_libgcc_s}"

# shellcheck disable=SC2154
while read -r doc ; do
relative="${doc//${zfsbootmenu_module_root}\//}"
Expand All @@ -113,7 +108,7 @@ install() {
inst_simple "${_libexec}" "/libexec/$( basename "${_libexec}" )" || _ret=$?
done

# User-facing utilities, useful for running in a recover shell
# User-facing utilities, useful for running in a recovery shell
for _bin in "${zfsbootmenu_module_root}"/bin/*; do
inst_simple "${_bin}" "/bin/$( basename "${_bin}" )" || _ret=$?
done
Expand Down Expand Up @@ -156,6 +151,18 @@ install() {
done
fi

# Install "load_key" hooks
# shellcheck disable=SC2154
if [ -n "${zfsbootmenu_load_key}" ]; then
for _exec in ${zfsbootmenu_load_key}; do
if [ -x "${_exec}" ]; then
inst_simple "${_exec}" "/libexec/load_key.d/$(basename "${_exec}")" || _ret=$?
else
dwarning "load_key script (${_exec}) missing or not executable; cannot install"
fi
done
fi

# Install "teardown" hooks
# shellcheck disable=SC2154
if [ -n "${zfsbootmenu_teardown}" ]; then
Expand Down
1 change: 1 addition & 0 deletions etc/zbm-builder/mkinitcpio.conf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ HOOKS=(base udev autodetect modconf block filesystems keyboard)
#
# hooks.early_setup.d
# hooks.setup.d
# hooks.load_key.d
# hooks.teardown.d
#
# of the same build directory. Support for mkinitcpio.conf.d mimics similar
Expand Down
7 changes: 6 additions & 1 deletion etc/zfsbootmenu/mkinitcpio.conf
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ HOOKS=(base udev autodetect modconf block filesystems keyboard zfsbootmenu)
# tested and may break some (non-essential) ZFSBootMenu features.
#zfsbootmenu_miser="no"

# zfsbootmenu_early_setup, zfsbootmenu_setup, zfsbootmenu_teardown
# zfsbootmenu_early_setup, zfsbootmenu_setup, zfsbootmenu_load_key, zfsbootmenu_teardown
# ZFSBootMenu supports user-provided hooks that may be run at various points in
# the boot process. Set each of these variables to an array of executable files
# that should be installed as user hooks in the provided image. Files that are
Expand All @@ -90,10 +90,15 @@ HOOKS=(base udev autodetect modconf block filesystems keyboard zfsbootmenu)
# 'zfsbootmenu_setup' hooks are run after pools are imported and right before
# the menu is presented.
#
# 'zfsbootmenu_load_key' hooks are run immediately before attempting to load an
# encryption key and unlock a locked filesystem. Each hook is called with a
# single argument: the name of an encryption root that should be unlocked.
#
# 'zfsbootmenu_teardown' hooks are run immediately before a chosen boot
# environment is about to be launched. Any writable ZFS pools will have been
# exported, but read-only pools will generally still be available.
#
#zfsbootmenu_early_setup=()
#zfsbootmenu_setup=()
#zfsbootmenu_load_key=()
#zfsbootmenu_teardown=()
5 changes: 4 additions & 1 deletion etc/zfsbootmenu/recovery.conf.d/recovery.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Disk manipulation
install_optional_items+=" /bin/gdisk /bin/parted /bin/wipefs /bin/kpartx "
install_optional_items+=" /bin/gdisk /bin/parted /bin/wipefs /bin/kpartx /bin/sgdisk"

# Filesystem creation
install_optional_items+=" /bin/mkfs.vfat /bin/mkfs.ext4 "
Expand All @@ -13,3 +13,6 @@ install_optional_items+=" /bin/cryptsetup "
# Networking
install_optional_items+=" /bin/ip /bin/curl /bin/dhclient /sbin/dhclient-script /bin/ssh "
add_dracutmodules+=" kernel-network-modules qemu-net "

# SSL bundle for cURL
install_optional_items+=" /etc/ssl/certs/ca-certificates.crt "
3 changes: 3 additions & 0 deletions etc/zfsbootmenu/release.conf.d/common.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
zfsbootmenu_teardown+=" /zbm/contrib/xhci-teardown.sh "
zfsbootmenu_early_setup+=" /zbm/contrib/10-console-init.sh /zbm/contrib/20-console-autosize.sh "

# zbm-kcl
install_optional_items+=" /zbm/bin/zbm-kcl "

install_optional_items+=" /etc/zbm-commit-hash "

omit_dracutmodules+=" crypt-ssh nfs lunmask "
Expand Down
22 changes: 22 additions & 0 deletions initcpio/install/zfsbootmenu
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ build() {
# Binaries required for ZBM operation
add_zbm_binaries

# Add libgcc_s as appropriate
local _libgcc_s
if ! _libgcc_s="$( find_libgcc_s )"; then
error "unable to locate libgcc_s.so"
exit 1
fi

local _lib
while read -r _lib ; do
[ -n "${_lib}" ] || continue
if ! add_binary "${_lib}"; then
error "Failed to install '${_lib}'"
exit 1
fi
done <<< "${_libgcc_s}"

# On-line documentation
while read -r doc; do
relative="${doc#"${zfsbootmenu_module_root}/"}"
Expand Down Expand Up @@ -178,6 +194,12 @@ build() {
add_file "${_file}" "/libexec/setup.d/${_file##*/}"
done

# shellcheck disable=SC2154
for _file in "${zfsbootmenu_load_key[@]}"; do
[ -x "${_file}" ] || continue
add_file "${_file}" "/libexec/load_key.d/${_file##*/}"
done

# shellcheck disable=SC2154
for _file in "${zfsbootmenu_teardown[@]}"; do
[ -x "${_file}" ] || continue
Expand Down
2 changes: 1 addition & 1 deletion releng/rst2help.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -e
td="zfsbootmenu/help-files"
for size in 52 92 132 ; do
rm "${td}/${size}"/* >/dev/null 2>&1 || /bin/true
for doc in docs/online/*.rst docs/man/zfsbootmenu.7.rst; do
for doc in docs/online/*.rst docs/man/zfsbootmenu.7.rst docs/man/zbm-kcl.8.rst; do
[ -d "${td}/${size}" ] || mkdir -p "${td}/${size}"
file="$( basename -s .rst "${doc}" ).ansi"
echo "Converting ${doc} for ${size} columns"
Expand Down
2 changes: 1 addition & 1 deletion zbm-builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ if ! [ -r "${BUILD_DIRECTORY}"/config.yaml ]; then
fi

# Try to include ZBM hooks in the images by default
for stage in early_setup setup teardown; do
for stage in early_setup setup load_key teardown; do
[ -d "${BUILD_DIRECTORY}/hooks.${stage}.d" ] || continue

# Only executable hooks are added to the image
Expand Down
106 changes: 106 additions & 0 deletions zfsbootmenu/help-files/132/zbm-kcl.8.ansi
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
zbm-kcl

SYNOPSIS

zbm-kcl [OPTION]... [FILESYSTEM|EFI_EXECUTABLE]

DESCRIPTION

The zbm-kcl utility allows review and manipulation of the org.zfsbootmenu:commandline property on ZFS filesystems or the
.cmdline section encoded within ZFSBootMenu EFI executables. ZFSBootMenu reads the property org.zfsbootmenu:commandline, as
set or inherited on each environment that it recognizes, to set the command line for the kernel that it boots. The
ZFSBootMenu EFI executable reads its own .cmdline section to parse options that control the behavior of ZFSBootMenu itself.

The final argument is treated as a ZFS filesystem as long as one exists with the specified name. If a matching filesystem cannot
be found, the argument is treated as an EFI executable. To force zbm-kcl to treat the final argument as a relative path to
an EFI executable even when a ZFS filesystem exists with the same name, prefix the path with ./.

When neither a filesystem nor an EFI executable is specified, zbm-kcl will attempt to determine the root filesystem and operate
on that.

If an EFI executable of - is specified, stdin will be read as an EFI executable.

With no options specified, zbm-kcl will print the current value of org.zfsbootmenu:commandline of the selected filesystem or the
.cmdline section of the named EFI executable and exit.

OPTIONS

-a argument

Append the value of argument to the kernel command line. The value of argument can be a simple variable name for Boolean
arguments or may take the form var=value to provide a non-Boolean value. Multiple command-line arguments may be
accumulated into a single argument. If the value of any variable value contains spaces, it should be surrounded by
double quotes. In that case, surround the entire argument in single quotes to ensure that the double quotes are recorded
in the property:

zbm-kcl -a 'variable="some argument with spaces"'

This argument may be repeated any number of times.

-r argument

Remove argument from the kernel command line. The value of argument can be a simple variable name, in which case all arguments
of the form argument or argument=<arbitrary-value> will be stripped. Alternatively, a specific argument may be selected
by specifying argument=<specific-value>.

This argument may be repeated any number of times.

Note

All removal options are processed before any append options are processed, making it possible to replace an existing
argument by combining removal and append options into a single invocation of zbm-kcl.

-e

Open the contents of the command-line in an interactive editor. If the environment defines $EDITOR, that will be used;
otherwise, vi will be used by default. After making changes as desired, overwrite the (temporary) file that was opened
and quit the editor. The contents of the saved file will be written by zbm-kcl as the new command line.

-d

Delete the command-line property.

For a ZFS filesystem, this is accomplished by calling

zfs inherit org.zfsbootmenu:commandline <filesystem>

to allow the boot environment to inherit any command-line property that may be defined by some parent.

For a ZFSBootMenu EFI executable, the .cmdline section will be stripped.

-o destination

Save the modified command line to destination rather than back to the original source. When the source is a ZFS filesystem,
the destination must also be a valid ZFS filesystem. When the source is an EFI executable, the destination will be
treated as a file; a special EFI destination of - will cause the file to be written to stdout.

EXAMPLES

Change the loglevel value on the currently booted environment by removing any existing value from the command line and appending
the desired argument:

zbm-kcl -a loglevel=7 -r loglevel

Delete the entire command line from the zroot/ROOT/void boot environment, allowing it to inherit a command line set at zroot or
zroot/ROOT if either of these defines a value:

zbm-kcl -d zroot/ROOT/void

Allow interactive editing of the command line on the zroot/ROOT filesystem, but save the resulting changes to zroot/ROOT/void
rather than back to zroot/ROOT:

zbm-kcl -e -o zroot/ROOT/void zroot/ROOT

Review the current command line embedded in the EFI file /boot/efi/EFI/zfsbootmenu/zfsbootmenu.EFI:

zbm-kcl /boot/efi/EFI/zfsbootmenu/zfsbootmenu.EFI

Fetch the official ZFSBootMenu release EFI executable, customizing the menu timeout and saving the result to
zfsbootmenu-custom.EFI:

curl -L https://get.zfsbootmenu.org/efi | \
zbm-kcl -a zbm.timeout=15 -r zbm.timeout -o zfsbootmenu-slow.EFI -

SEE ALSO

zfsbootmenu(7)
Loading