From: "Thomas Deutschmann" <whissi@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/genkernel:master commit in: defaults/, /
Date: Sun, 12 Jan 2020 14:59:27 +0000 (UTC) [thread overview]
Message-ID: <1578772480.9e7b41cda3df648b509a0f8a2af29a683100a46f.whissi@gentoo> (raw)
commit: 9e7b41cda3df648b509a0f8a2af29a683100a46f
Author: Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
AuthorDate: Fri Jan 10 16:07:20 2020 +0000
Commit: Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
CommitDate: Sat Jan 11 19:54:40 2020 +0000
URL: https://gitweb.gentoo.org/proj/genkernel.git/commit/?id=9e7b41cd
Rework ZFS unlock
- Prompt for key when key is unavailable, not when key is available.
- Check ZFS' keystatus property instead of return value to allow
remote unlock.
- Add unlock-zfs command to remote rescue shell.
Closes: https://bugs.gentoo.org/705032
Signed-off-by: Thomas Deutschmann <whissi <AT> gentoo.org>
defaults/initrd.defaults | 3 ++
defaults/initrd.scripts | 38 +++++++++++++++-----
defaults/linuxrc | 42 +++++++++++++++-------
defaults/login-remote.sh | 5 +++
defaults/unlock-zfs.sh | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
gen_initramfs.sh | 6 ++++
6 files changed, 165 insertions(+), 20 deletions(-)
diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults
index 198800b..15326dd 100644
--- a/defaults/initrd.defaults
+++ b/defaults/initrd.defaults
@@ -103,6 +103,9 @@ CRYPT_KEYFILE_SWAP='/tmp/swap.key'
CRYPT_ROOT_OPENED_LOCKFILE='/tmp/ROOT.opened'
CRYPT_SWAP_OPENED_LOCKFILE='/tmp/SWAP.opened'
+ZFS_ENC_ENV_FILE='/etc/ZFS_ENC_ENV.conf'
+ZFS_ENC_OPENED_LOCKFILE='/tmp/ZFS.opened'
+
# Flag for if ok when using CDROOT
got_good_root='0'
# if LOOP found on root before mount, trigger Unpacking additional packages
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index 73cd94c..6c7d72b 100644
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -1087,6 +1087,20 @@ warn_msg() {
[ "$2" != '1' ] && printf "%b\n" "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
}
+write_env_file() {
+ local env_file=${1}
+ shift
+
+ run touch "${env_file}"
+
+ local varname= varvalue=
+ for varname in $*
+ do
+ eval varvalue=\$${varname}
+ echo "${varname}=${varvalue}" >> "${env_file}"
+ done
+}
+
crypt_filter() {
if [ "${CRYPT_SILENT}" = '1' ]
then
@@ -2265,14 +2279,15 @@ start_sshd() {
return
fi
- # setup environment variables for the ssh login shell
- local varname= varvalue=
- run touch "${CRYPT_ENV_FILE}"
- for varname in CRYPT_ROOT CRYPT_ROOT_TRIM CRYPT_SILENT CRYPT_SWAP
- do
- eval varvalue=\$${varname}
- echo "${varname}=${varvalue}" >> "${CRYPT_ENV_FILE}"
- done
+ # setup environment variables for the remote rescue shell
+ # ZFS will use a different file because $REAL_ROOT for ZFS
+ # isn't known yet.
+ write_env_file \
+ "${CRYPT_ENV_FILE}" \
+ CRYPT_ROOT \
+ CRYPT_ROOT_TRIM \
+ CRYPT_SILENT \
+ CRYPT_SWAP
run touch /var/log/lastlog
@@ -2679,6 +2694,13 @@ get_mount_device() {
' ${NEW_ROOT}/etc/fstab
}
+get_zfs_property() {
+ local device=${1}
+ local propertyname=${2}
+
+ echo "$(zfs get -H -o value ${propertyname} "${device}" 2>/dev/null)"
+}
+
# If the kernel is handed a mount option is does not recognize, it WILL fail to
# mount. util-linux handles auto/noauto, but busybox passes it straight to the kernel
# which then rejects the mount.
diff --git a/defaults/linuxrc b/defaults/linuxrc
index f585017..7fbd0ad 100644
--- a/defaults/linuxrc
+++ b/defaults/linuxrc
@@ -491,7 +491,7 @@ then
if [ ! -x ${i} ]
then
USE_ZFS=0
- bad_msg 'Aborting use of zfs because ${i} not found!'
+ bad_msg "Aborting use of ZFS because ${i} not found!"
break
fi
done
@@ -740,7 +740,7 @@ do
ROOT_DEV="${REAL_ROOT#*=}"
if [ "${ROOT_DEV}" != 'ZFS' ]
then
- if [ "$(zfs get type -o value -H ${ROOT_DEV} 2>/dev/null)" = 'filesystem' ]
+ if [ "$(get_zfs_property "${ROOT_DEV}" type)" = 'filesystem' ]
then
got_good_root=1
REAL_ROOT=${ROOT_DEV}
@@ -753,7 +753,7 @@ do
continue
fi
else
- BOOTFS=$(/sbin/zpool list -H -o bootfs 2>/dev/null)
+ BOOTFS=$(zpool list -H -o bootfs 2>/dev/null)
if [ "${BOOTFS}" != '-' ]
then
for i in ${BOOTFS}
@@ -801,6 +801,14 @@ do
echo
fi
+ if [ "${USE_ZFS}" = '1' ]
+ then
+ write_env_file \
+ "${ZFS_ENC_ENV_FILE}" \
+ REAL_ROOT \
+ ROOTFSTYPE
+ fi
+
# Check for a block device or /dev/nfs or zfs encryption
if [ -n "${REAL_ROOT}" ] && [ "${REAL_ROOT}" = "/dev/nfs" ] || [ "${ROOTFSTYPE}" = "zfs" ] || [ -b "${REAL_ROOT}" ]
then
@@ -810,20 +818,30 @@ do
# let's check if this dataset is encrypted and ask for passphrase
if [ "$(zpool list -H -o feature@encryption "${REAL_ROOT%%/*}" 2>/dev/null)" = 'active' ]
then
- ZFS_KEYSTATUS="$(zfs get -H -o value keystatus "${REAL_ROOT}" 2>/dev/null)"
- ZFS_ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${REAL_ROOT}" 2>/dev/null)"
- if ! [ "${ZFS_ENCRYPTIONROOT}" = '-' ] || [ "${ZFS_KEYSTATUS}" = 'available' ]
+ ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
+ ZFS_ENCRYPTIONROOT="$(get_zfs_property "${REAL_ROOT}" encryptionroot)"
+ if [ "${ZFS_ENCRYPTIONROOT}" != '-' ] && [ "${ZFS_KEYSTATUS}" = 'unavailable' ]
then
good_msg "Detected ZFS encryption, asking for key"
- zfs load-key "${ZFS_ENCRYPTIONROOT}"
- retval=$?
- # if the key loaded fine, confirm got_good_root to exit second while loop
- if [ ${retval} -ne 0 ]
+ run zfs load-key "${ZFS_ENCRYPTIONROOT}"
+
+ # Get new key status to check if load-key was successful
+ # or dataset has been opened by someone else in the meantime (through SSH for instance)
+ ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
+
+ if [ "${ZFS_KEYSTATUS}" != 'available' ]
then
- bad_msg "${ROOT_DEV} is encrypted and not mountable without key"
+ bad_msg "${REAL_ROOT} is encrypted and not mountable without key"
got_good_root=0
break
fi
+
+ if [ -f "${ZFS_ENC_OPENED_LOCKFILE}" ]
+ then
+ good_msg "${REAL_ROOT} device meanwhile was opened by someone else."
+ else
+ run touch "${ZFS_ENC_OPENED_LOCKFILE}"
+ fi
fi
fi
else
@@ -849,7 +867,7 @@ do
if [ "${ROOTFSTYPE}" = 'zfs' ]
then
- if [ "$(zfs get -H -o value mountpoint "${REAL_ROOT}")" = 'legacy' ]
+ if [ "$(get_zfs_property "${REAL_ROOT}" mountpoint)" = 'legacy' ]
then
MOUNT_STATE=rw
else
diff --git a/defaults/login-remote.sh b/defaults/login-remote.sh
index 588504f..94ee014 100644
--- a/defaults/login-remote.sh
+++ b/defaults/login-remote.sh
@@ -105,6 +105,11 @@ else
good_msg "${NORMAL}To remote unlock LUKS-encrypted swap device, run '${BOLD}unlock-luks swap${NORMAL}'."
fi
+ if [ -e "${ZFS_ENC_ENV_FILE}" ] && [ ! -f "${ZFS_ENC_OPENED_LOCKFILE}" ]
+ then
+ good_msg "${NORMAL}To remote unlock ZFS root device, run '${BOLD}unlock-zfs${NORMAL}'."
+ fi
+
echo
[ -x /bin/sh ] && SH=/bin/sh || SH=/bin/ash
diff --git a/defaults/unlock-zfs.sh b/defaults/unlock-zfs.sh
new file mode 100644
index 0000000..c22a214
--- /dev/null
+++ b/defaults/unlock-zfs.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+. /etc/initrd.defaults
+. /etc/initrd.scripts
+
+GK_INIT_LOG_PREFIX=${0}
+if [ -n "${SSH_CLIENT_IP}" ] && [ -n "${SSH_CLIENT_PORT}" ]
+then
+ GK_INIT_LOG_PREFIX="${0}[${SSH_CLIENT_IP}:${SSH_CLIENT_PORT}]"
+fi
+
+if [ -f "${ZFS_ENC_ENV_FILE}" ]
+then
+ . "${ZFS_ENC_ENV_FILE}"
+else
+ bad_msg "${ZFS_ENC_ENV_FILE} does not exist! Did you boot without 'dozfs' kernel command-line parameter?"
+ exit 1
+fi
+
+main() {
+ if ! hash zfs >/dev/null 2>&1
+ then
+ bad_msg "zfs program is missing. Was initramfs built without --zfs parameter?"
+ exit 1
+ elif ! hash zpool >/dev/null 2>&1
+ then
+ bad_msg "zpool program is missing. Was initramfs built without --zfs parameter?"
+ exit 1
+ elif [ -z "${ROOTFSTYPE}" ]
+ then
+ bad_msg "Something went wrong. ROOTFSTYPE is not set!"
+ exit 1
+ elif [ "${ROOTFSTYPE}" != "zfs" ]
+ then
+ bad_msg "ROOTFSTYPE of 'zfs' required but '${ROOTFSTYPE}' detected!"
+ exit 1
+ elif [ -z "${REAL_ROOT}" ]
+ then
+ bad_msg "Something went wrong. REAL_ROOT is not set!"
+ exit 1
+ fi
+
+ if [ "$(zpool list -H -o feature@encryption "${REAL_ROOT%%/*}" 2>/dev/null)" != 'active' ]
+ then
+ bad_msg "Root device ${REAL_ROOT} is not encrypted!"
+ exit 1
+ fi
+
+ local ZFS_ENCRYPTIONROOT="$(get_zfs_property "${REAL_ROOT}" encryptionroot)"
+ if [ "${ZFS_ENCRYPTIONROOT}" = '-' ]
+ then
+ bad_msg "Failed to determine encryptionroot for ${REAL_ROOT}!"
+ exit 1
+ fi
+
+ local ZFS_KEYSTATUS=
+ while true
+ do
+ if [ -e "${ZFS_ENC_OPENED_LOCKFILE}" ]
+ then
+ good_msg "${REAL_ROOT} device meanwhile was opened by someone else."
+ break
+ fi
+
+ zfs load-key "${ZFS_ENCRYPTIONROOT}"
+
+ ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
+ if [ "${ZFS_KEYSTATUS}" = 'available' ]
+ then
+ run touch "${ZFS_ENC_OPENED_LOCKFILE}"
+ good_msg "ZFS device ${REAL_ROOT} opened"
+ break
+ else
+ bad_msg "Failed to open ZFS device ${REAL_ROOT}"
+
+ # We need to stop here with a non-zero exit code to prevent
+ # a loop when invalid keyfile was sent.
+ exit 1
+ fi
+ done
+
+ if [ "${ZFS_KEYSTATUS}" = 'available' ]
+ then
+ # Kill any running load-key prompt.
+ run pkill -f "load-key" >/dev/null 2>&1
+ fi
+}
+
+main
+
+exit 0
diff --git a/gen_initramfs.sh b/gen_initramfs.sh
index 676b86d..8620414 100755
--- a/gen_initramfs.sh
+++ b/gen_initramfs.sh
@@ -1342,6 +1342,9 @@ append_dropbear() {
cp -a "${GK_SHARE}"/defaults/unlock-luks.sh "${TDIR}"/usr/sbin/unlock-luks \
|| gen_die "Failed to copy '${GK_SHARE}/defaults/unlock-luks.sh' to '${TDIR}/usr/sbin/unlock-luks'"
+ cp -a "${GK_SHARE}"/defaults/unlock-zfs.sh "${TDIR}"/usr/sbin/unlock-zfs \
+ || gen_die "Failed to copy '${GK_SHARE}/defaults/unlock-zfs.sh' to '${TDIR}/usr/sbin/unlock-zfs'"
+
cp -aL "${DROPBEAR_AUTHORIZED_KEYS_FILE}" "${TDIR}"/root/.ssh/ \
|| gen_die "Failed to copy '${DROPBEAR_AUTHORIZED_KEYS_FILE}'!"
@@ -1369,6 +1372,9 @@ append_dropbear() {
chmod 0755 "${TDIR}"/usr/sbin/unlock-luks \
|| gen_die "Failed to chmod of '${TDIR}/usr/sbin/unlock-luks'!"
+ chmod 0755 "${TDIR}"/usr/sbin/unlock-zfs \
+ || gen_die "Failed to chmod of '${TDIR}/usr/sbin/unlock-zfs'!"
+
chmod 0640 "${TDIR}"/etc/shadow \
|| gen_die "Failed to chmod of '${TDIR}/etc/shadow'!"
next reply other threads:[~2020-01-12 14:59 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-12 14:59 Thomas Deutschmann [this message]
-- strict thread matches above, loose matches on Subject: below --
2020-08-28 20:18 [gentoo-commits] proj/genkernel:master commit in: defaults/, / Thomas Deutschmann
2020-08-28 20:18 Thomas Deutschmann
2020-08-01 21:41 Thomas Deutschmann
2020-07-23 23:57 Thomas Deutschmann
2020-07-16 15:03 Thomas Deutschmann
2019-11-24 20:00 Thomas Deutschmann
2017-01-02 20:14 Matt Thode
2016-01-05 18:51 Richard Farina
2015-04-12 21:04 Mike Frysinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1578772480.9e7b41cda3df648b509a0f8a2af29a683100a46f.whissi@gentoo \
--to=whissi@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox