Skip to content

Commit

Permalink
Make cache_key aware of mountpoints on key sources
Browse files Browse the repository at this point in the history
When attempting to unlock a BE using keys from another filesystem named
as a key source via org.zfsbootmenu:keysource, attempt to discover and
strip the expected mountpoint from the key source when looking for keys.
This allows, for example,

    zfs create -o mountpoint=/etc/zfs/keys zpool/keys

    zfs set org.zfsbootmenu:keysource=zpool/keys \
        keylocation=file:///etc/zfs/keys/zpool.key zpool/ROOT/bootenv

to work with ZFSBootMenu. Previously, the cache_key function would only
properly identify keys when the key source had a mountpoint of /.

When mountpoint=none or mountpoint=legacy, or in the event a key does
not exist at the new relative path, the prior behavior of looking for a
path verbatim with respect to the key source is preserved.
  • Loading branch information
ahesford committed Sep 14, 2021
1 parent 2d03ff5 commit d208103
Showing 1 changed file with 48 additions and 6 deletions.
54 changes: 48 additions & 6 deletions 90zfsbootmenu/zfsbootmenu-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1925,7 +1925,8 @@ be_keysource() {
# returns: 0 iff a key was cached

cache_key() {
local fs keylocation keyfile keydir keysrc keycache mutex mnt ret
local fs mnt ret mutex keycache
local ksmount relkeyloc keypath keylocation keyfile keydir keysrc

fs="${1}"
if [ -z "${fs}" ]; then
Expand Down Expand Up @@ -1995,19 +1996,60 @@ cache_key() {
return 1
fi

relkeyloc=""
if ksmount="$(zfs get -o value -H mountpoint "${keysrc}" )"; then
case "${ksmount}" in
none|legacy)
zdebug "no discernable mountpoint for ${keysrc}, using only absolute key path"
;;
/*)
# For absolute mountpoints, strip the root
ksmount="${ksmount#/}"

# Key location relative to expected mountpoint of keysource
relkeyloc="${keyfile#${ksmount}}"
relkeyloc="${relkeyloc#/}"

zdebug "${keysrc} mounts at ${ksmount}, trying relative path ${relkeyloc}"

if [ "${relkeyloc}" = "${keyfile}" ]; then
# If location isn't different, there is no relative location
relkeyloc=""
zdebug "relative path ${relkeyloc} matches absolute, ignoring"
fi
;;
*)
zwarn "ignoring nonsense mountpoint ${ksmount} on filesystem ${keysrc}"
;;
esac
fi

if [ -n "${relkeyloc}" ] && [ -e "${mnt}/${relkeyloc}" ]; then
# Prefer a path relative to the expected mountpoint of the keysource
keypath="${mnt}/${relkeyloc}"
zdebug "caching key from mount-relative path ${keysrc}:${relkeyloc}"
elif [ -e "${mnt}/${keyfile}" ]; then
keypath="${mnt}/${keyfile}"
zdebug "caching key from absolute path ${keysrc}:${keyfile}"
else
keypath=""
zdebug "no key found at ${keysrc}:${keyfile}"
fi

ret=1
if [ -e "${mnt}/${keyfile}" ]; then
if [ -n "${keypath}" ]; then
# Cache target is always full path below fs cache root
keydir="${keyfile%/*}"
if [ "${keydir}" != "${keyfile}" ] && [ -n "${keydir}" ]; then
mkdir -p "${keycache}/${keydir}"
fi

if cp "${mnt}/${keyfile}" "${keycache}/${keyfile}"; then
zdebug "copied key ${mnt}/${keyfile} to ${keycache}/${keyfile}"
if cp "${keypath}" "${keycache}/${keyfile}"; then
zdebug "copied key ${keypath} to ${keycache}/${keyfile}"
ret=0
else
zerror "failed to copy ${keypath} to ${keycache}/${keyfile}"
fi
else
zdebug "key file ${keysrc}:${keyfile} not found at ${mnt}/${keyfile}"
fi

# Clean up mount and mutex
Expand Down

0 comments on commit d208103

Please sign in to comment.