Gentoo Archives: gentoo-commits

From: Thomas Deutschmann <whissi@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/genkernel:master commit in: defaults/, /
Date: Sun, 12 Jan 2020 14:59:31
Message-Id: 1578772480.9e7b41cda3df648b509a0f8a2af29a683100a46f.whissi@gentoo
1 commit: 9e7b41cda3df648b509a0f8a2af29a683100a46f
2 Author: Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
3 AuthorDate: Fri Jan 10 16:07:20 2020 +0000
4 Commit: Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
5 CommitDate: Sat Jan 11 19:54:40 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/genkernel.git/commit/?id=9e7b41cd
7
8 Rework ZFS unlock
9
10 - Prompt for key when key is unavailable, not when key is available.
11
12 - Check ZFS' keystatus property instead of return value to allow
13 remote unlock.
14
15 - Add unlock-zfs command to remote rescue shell.
16
17 Closes: https://bugs.gentoo.org/705032
18 Signed-off-by: Thomas Deutschmann <whissi <AT> gentoo.org>
19
20 defaults/initrd.defaults | 3 ++
21 defaults/initrd.scripts | 38 +++++++++++++++-----
22 defaults/linuxrc | 42 +++++++++++++++-------
23 defaults/login-remote.sh | 5 +++
24 defaults/unlock-zfs.sh | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
25 gen_initramfs.sh | 6 ++++
26 6 files changed, 165 insertions(+), 20 deletions(-)
27
28 diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults
29 index 198800b..15326dd 100644
30 --- a/defaults/initrd.defaults
31 +++ b/defaults/initrd.defaults
32 @@ -103,6 +103,9 @@ CRYPT_KEYFILE_SWAP='/tmp/swap.key'
33 CRYPT_ROOT_OPENED_LOCKFILE='/tmp/ROOT.opened'
34 CRYPT_SWAP_OPENED_LOCKFILE='/tmp/SWAP.opened'
35
36 +ZFS_ENC_ENV_FILE='/etc/ZFS_ENC_ENV.conf'
37 +ZFS_ENC_OPENED_LOCKFILE='/tmp/ZFS.opened'
38 +
39 # Flag for if ok when using CDROOT
40 got_good_root='0'
41 # if LOOP found on root before mount, trigger Unpacking additional packages
42
43 diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
44 index 73cd94c..6c7d72b 100644
45 --- a/defaults/initrd.scripts
46 +++ b/defaults/initrd.scripts
47 @@ -1087,6 +1087,20 @@ warn_msg() {
48 [ "$2" != '1' ] && printf "%b\n" "${WARN}**${NORMAL}${BOLD} ${msg_string} ${NORMAL}"
49 }
50
51 +write_env_file() {
52 + local env_file=${1}
53 + shift
54 +
55 + run touch "${env_file}"
56 +
57 + local varname= varvalue=
58 + for varname in $*
59 + do
60 + eval varvalue=\$${varname}
61 + echo "${varname}=${varvalue}" >> "${env_file}"
62 + done
63 +}
64 +
65 crypt_filter() {
66 if [ "${CRYPT_SILENT}" = '1' ]
67 then
68 @@ -2265,14 +2279,15 @@ start_sshd() {
69 return
70 fi
71
72 - # setup environment variables for the ssh login shell
73 - local varname= varvalue=
74 - run touch "${CRYPT_ENV_FILE}"
75 - for varname in CRYPT_ROOT CRYPT_ROOT_TRIM CRYPT_SILENT CRYPT_SWAP
76 - do
77 - eval varvalue=\$${varname}
78 - echo "${varname}=${varvalue}" >> "${CRYPT_ENV_FILE}"
79 - done
80 + # setup environment variables for the remote rescue shell
81 + # ZFS will use a different file because $REAL_ROOT for ZFS
82 + # isn't known yet.
83 + write_env_file \
84 + "${CRYPT_ENV_FILE}" \
85 + CRYPT_ROOT \
86 + CRYPT_ROOT_TRIM \
87 + CRYPT_SILENT \
88 + CRYPT_SWAP
89
90 run touch /var/log/lastlog
91
92 @@ -2679,6 +2694,13 @@ get_mount_device() {
93 ' ${NEW_ROOT}/etc/fstab
94 }
95
96 +get_zfs_property() {
97 + local device=${1}
98 + local propertyname=${2}
99 +
100 + echo "$(zfs get -H -o value ${propertyname} "${device}" 2>/dev/null)"
101 +}
102 +
103 # If the kernel is handed a mount option is does not recognize, it WILL fail to
104 # mount. util-linux handles auto/noauto, but busybox passes it straight to the kernel
105 # which then rejects the mount.
106
107 diff --git a/defaults/linuxrc b/defaults/linuxrc
108 index f585017..7fbd0ad 100644
109 --- a/defaults/linuxrc
110 +++ b/defaults/linuxrc
111 @@ -491,7 +491,7 @@ then
112 if [ ! -x ${i} ]
113 then
114 USE_ZFS=0
115 - bad_msg 'Aborting use of zfs because ${i} not found!'
116 + bad_msg "Aborting use of ZFS because ${i} not found!"
117 break
118 fi
119 done
120 @@ -740,7 +740,7 @@ do
121 ROOT_DEV="${REAL_ROOT#*=}"
122 if [ "${ROOT_DEV}" != 'ZFS' ]
123 then
124 - if [ "$(zfs get type -o value -H ${ROOT_DEV} 2>/dev/null)" = 'filesystem' ]
125 + if [ "$(get_zfs_property "${ROOT_DEV}" type)" = 'filesystem' ]
126 then
127 got_good_root=1
128 REAL_ROOT=${ROOT_DEV}
129 @@ -753,7 +753,7 @@ do
130 continue
131 fi
132 else
133 - BOOTFS=$(/sbin/zpool list -H -o bootfs 2>/dev/null)
134 + BOOTFS=$(zpool list -H -o bootfs 2>/dev/null)
135 if [ "${BOOTFS}" != '-' ]
136 then
137 for i in ${BOOTFS}
138 @@ -801,6 +801,14 @@ do
139 echo
140 fi
141
142 + if [ "${USE_ZFS}" = '1' ]
143 + then
144 + write_env_file \
145 + "${ZFS_ENC_ENV_FILE}" \
146 + REAL_ROOT \
147 + ROOTFSTYPE
148 + fi
149 +
150 # Check for a block device or /dev/nfs or zfs encryption
151 if [ -n "${REAL_ROOT}" ] && [ "${REAL_ROOT}" = "/dev/nfs" ] || [ "${ROOTFSTYPE}" = "zfs" ] || [ -b "${REAL_ROOT}" ]
152 then
153 @@ -810,20 +818,30 @@ do
154 # let's check if this dataset is encrypted and ask for passphrase
155 if [ "$(zpool list -H -o feature@encryption "${REAL_ROOT%%/*}" 2>/dev/null)" = 'active' ]
156 then
157 - ZFS_KEYSTATUS="$(zfs get -H -o value keystatus "${REAL_ROOT}" 2>/dev/null)"
158 - ZFS_ENCRYPTIONROOT="$(zfs get -H -o value encryptionroot "${REAL_ROOT}" 2>/dev/null)"
159 - if ! [ "${ZFS_ENCRYPTIONROOT}" = '-' ] || [ "${ZFS_KEYSTATUS}" = 'available' ]
160 + ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
161 + ZFS_ENCRYPTIONROOT="$(get_zfs_property "${REAL_ROOT}" encryptionroot)"
162 + if [ "${ZFS_ENCRYPTIONROOT}" != '-' ] && [ "${ZFS_KEYSTATUS}" = 'unavailable' ]
163 then
164 good_msg "Detected ZFS encryption, asking for key"
165 - zfs load-key "${ZFS_ENCRYPTIONROOT}"
166 - retval=$?
167 - # if the key loaded fine, confirm got_good_root to exit second while loop
168 - if [ ${retval} -ne 0 ]
169 + run zfs load-key "${ZFS_ENCRYPTIONROOT}"
170 +
171 + # Get new key status to check if load-key was successful
172 + # or dataset has been opened by someone else in the meantime (through SSH for instance)
173 + ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
174 +
175 + if [ "${ZFS_KEYSTATUS}" != 'available' ]
176 then
177 - bad_msg "${ROOT_DEV} is encrypted and not mountable without key"
178 + bad_msg "${REAL_ROOT} is encrypted and not mountable without key"
179 got_good_root=0
180 break
181 fi
182 +
183 + if [ -f "${ZFS_ENC_OPENED_LOCKFILE}" ]
184 + then
185 + good_msg "${REAL_ROOT} device meanwhile was opened by someone else."
186 + else
187 + run touch "${ZFS_ENC_OPENED_LOCKFILE}"
188 + fi
189 fi
190 fi
191 else
192 @@ -849,7 +867,7 @@ do
193
194 if [ "${ROOTFSTYPE}" = 'zfs' ]
195 then
196 - if [ "$(zfs get -H -o value mountpoint "${REAL_ROOT}")" = 'legacy' ]
197 + if [ "$(get_zfs_property "${REAL_ROOT}" mountpoint)" = 'legacy' ]
198 then
199 MOUNT_STATE=rw
200 else
201
202 diff --git a/defaults/login-remote.sh b/defaults/login-remote.sh
203 index 588504f..94ee014 100644
204 --- a/defaults/login-remote.sh
205 +++ b/defaults/login-remote.sh
206 @@ -105,6 +105,11 @@ else
207 good_msg "${NORMAL}To remote unlock LUKS-encrypted swap device, run '${BOLD}unlock-luks swap${NORMAL}'."
208 fi
209
210 + if [ -e "${ZFS_ENC_ENV_FILE}" ] && [ ! -f "${ZFS_ENC_OPENED_LOCKFILE}" ]
211 + then
212 + good_msg "${NORMAL}To remote unlock ZFS root device, run '${BOLD}unlock-zfs${NORMAL}'."
213 + fi
214 +
215 echo
216
217 [ -x /bin/sh ] && SH=/bin/sh || SH=/bin/ash
218
219 diff --git a/defaults/unlock-zfs.sh b/defaults/unlock-zfs.sh
220 new file mode 100644
221 index 0000000..c22a214
222 --- /dev/null
223 +++ b/defaults/unlock-zfs.sh
224 @@ -0,0 +1,91 @@
225 +#!/bin/sh
226 +
227 +. /etc/initrd.defaults
228 +. /etc/initrd.scripts
229 +
230 +GK_INIT_LOG_PREFIX=${0}
231 +if [ -n "${SSH_CLIENT_IP}" ] && [ -n "${SSH_CLIENT_PORT}" ]
232 +then
233 + GK_INIT_LOG_PREFIX="${0}[${SSH_CLIENT_IP}:${SSH_CLIENT_PORT}]"
234 +fi
235 +
236 +if [ -f "${ZFS_ENC_ENV_FILE}" ]
237 +then
238 + . "${ZFS_ENC_ENV_FILE}"
239 +else
240 + bad_msg "${ZFS_ENC_ENV_FILE} does not exist! Did you boot without 'dozfs' kernel command-line parameter?"
241 + exit 1
242 +fi
243 +
244 +main() {
245 + if ! hash zfs >/dev/null 2>&1
246 + then
247 + bad_msg "zfs program is missing. Was initramfs built without --zfs parameter?"
248 + exit 1
249 + elif ! hash zpool >/dev/null 2>&1
250 + then
251 + bad_msg "zpool program is missing. Was initramfs built without --zfs parameter?"
252 + exit 1
253 + elif [ -z "${ROOTFSTYPE}" ]
254 + then
255 + bad_msg "Something went wrong. ROOTFSTYPE is not set!"
256 + exit 1
257 + elif [ "${ROOTFSTYPE}" != "zfs" ]
258 + then
259 + bad_msg "ROOTFSTYPE of 'zfs' required but '${ROOTFSTYPE}' detected!"
260 + exit 1
261 + elif [ -z "${REAL_ROOT}" ]
262 + then
263 + bad_msg "Something went wrong. REAL_ROOT is not set!"
264 + exit 1
265 + fi
266 +
267 + if [ "$(zpool list -H -o feature@encryption "${REAL_ROOT%%/*}" 2>/dev/null)" != 'active' ]
268 + then
269 + bad_msg "Root device ${REAL_ROOT} is not encrypted!"
270 + exit 1
271 + fi
272 +
273 + local ZFS_ENCRYPTIONROOT="$(get_zfs_property "${REAL_ROOT}" encryptionroot)"
274 + if [ "${ZFS_ENCRYPTIONROOT}" = '-' ]
275 + then
276 + bad_msg "Failed to determine encryptionroot for ${REAL_ROOT}!"
277 + exit 1
278 + fi
279 +
280 + local ZFS_KEYSTATUS=
281 + while true
282 + do
283 + if [ -e "${ZFS_ENC_OPENED_LOCKFILE}" ]
284 + then
285 + good_msg "${REAL_ROOT} device meanwhile was opened by someone else."
286 + break
287 + fi
288 +
289 + zfs load-key "${ZFS_ENCRYPTIONROOT}"
290 +
291 + ZFS_KEYSTATUS="$(get_zfs_property "${REAL_ROOT}" keystatus)"
292 + if [ "${ZFS_KEYSTATUS}" = 'available' ]
293 + then
294 + run touch "${ZFS_ENC_OPENED_LOCKFILE}"
295 + good_msg "ZFS device ${REAL_ROOT} opened"
296 + break
297 + else
298 + bad_msg "Failed to open ZFS device ${REAL_ROOT}"
299 +
300 + # We need to stop here with a non-zero exit code to prevent
301 + # a loop when invalid keyfile was sent.
302 + exit 1
303 + fi
304 + done
305 +
306 + if [ "${ZFS_KEYSTATUS}" = 'available' ]
307 + then
308 + # Kill any running load-key prompt.
309 + run pkill -f "load-key" >/dev/null 2>&1
310 + fi
311 +}
312 +
313 +main
314 +
315 +exit 0
316
317 diff --git a/gen_initramfs.sh b/gen_initramfs.sh
318 index 676b86d..8620414 100755
319 --- a/gen_initramfs.sh
320 +++ b/gen_initramfs.sh
321 @@ -1342,6 +1342,9 @@ append_dropbear() {
322 cp -a "${GK_SHARE}"/defaults/unlock-luks.sh "${TDIR}"/usr/sbin/unlock-luks \
323 || gen_die "Failed to copy '${GK_SHARE}/defaults/unlock-luks.sh' to '${TDIR}/usr/sbin/unlock-luks'"
324
325 + cp -a "${GK_SHARE}"/defaults/unlock-zfs.sh "${TDIR}"/usr/sbin/unlock-zfs \
326 + || gen_die "Failed to copy '${GK_SHARE}/defaults/unlock-zfs.sh' to '${TDIR}/usr/sbin/unlock-zfs'"
327 +
328 cp -aL "${DROPBEAR_AUTHORIZED_KEYS_FILE}" "${TDIR}"/root/.ssh/ \
329 || gen_die "Failed to copy '${DROPBEAR_AUTHORIZED_KEYS_FILE}'!"
330
331 @@ -1369,6 +1372,9 @@ append_dropbear() {
332 chmod 0755 "${TDIR}"/usr/sbin/unlock-luks \
333 || gen_die "Failed to chmod of '${TDIR}/usr/sbin/unlock-luks'!"
334
335 + chmod 0755 "${TDIR}"/usr/sbin/unlock-zfs \
336 + || gen_die "Failed to chmod of '${TDIR}/usr/sbin/unlock-zfs'!"
337 +
338 chmod 0640 "${TDIR}"/etc/shadow \
339 || gen_die "Failed to chmod of '${TDIR}/etc/shadow'!"