mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
dissect-image: Various fixes w.r.t verity signature checking (#44386)
This commit is contained in:
3 files changed
+57
-27
No files matched your search
+24
-12
@@ -1062,7 +1062,7 @@ static int dissect_image_from_unpartitioned(
|
||||
m->verity_ready = verity_settings_data_covers(verity, PARTITION_ROOT);
|
||||
|
||||
m->has_verity_sig = false; /* signature not embedded, must be specified */
|
||||
m->verity_sig_ready = m->verity_ready && iovec_is_set(&verity->root_hash);
|
||||
m->verity_sig_ready = m->verity_ready && iovec_is_set(&verity->root_hash_sig);
|
||||
|
||||
if (uuid)
|
||||
m->image_uuid = *uuid;
|
||||
@@ -3549,13 +3549,11 @@ static int do_crypt_activate_verity(
|
||||
return r < 0 ? r : -EDESTADDRREQ;
|
||||
|
||||
log_debug("Activation of signed Verity volume without validating signature is permitted by policy. Continuing.");
|
||||
} else
|
||||
measure_signature = false;
|
||||
} else {
|
||||
log_debug("Verity activation via userspace signature logic worked, activating by root hash.");
|
||||
|
||||
/* Otherwise let's see what signature-less activation results in. */
|
||||
|
||||
measure_signature = true;
|
||||
|
||||
measure_signature = true;
|
||||
}
|
||||
} else if (!FLAGS_SET(policy_flags, PARTITION_POLICY_VERITY))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ERFKILL),
|
||||
"No-signature activation of Verity volume not allowed by policy, refusing.");
|
||||
@@ -5487,7 +5485,6 @@ int mountfsd_mount_image_fd(
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *di = NULL;
|
||||
_cleanup_close_ int verity_data_fd = -EBADF;
|
||||
_cleanup_free_ char *ps = NULL;
|
||||
const char *error_id;
|
||||
int r;
|
||||
|
||||
assert(image_fd >= 0);
|
||||
@@ -5567,7 +5564,8 @@ int mountfsd_mount_image_fd(
|
||||
}
|
||||
|
||||
sd_json_variant *reply = NULL;
|
||||
r = varlink_callbo_and_log(
|
||||
const char *error_id = NULL;
|
||||
r = sd_varlink_callbo(
|
||||
vl,
|
||||
"io.systemd.MountFileSystem.MountImage",
|
||||
&reply,
|
||||
@@ -5585,7 +5583,23 @@ int mountfsd_mount_image_fd(
|
||||
SD_JSON_BUILD_PAIR_CONDITION(verity && iovec_is_set(&verity->root_hash_sig), "verityRootHashSignature", JSON_BUILD_IOVEC_BASE64(&verity->root_hash_sig)),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("allowInteractiveAuthentication", FLAGS_SET(flags, DISSECT_IMAGE_ALLOW_INTERACTIVE_AUTH)));
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_error_errno(r, "Failed to issue MountImage() varlink call: %m");
|
||||
if (error_id) {
|
||||
/* Return the same errors as dissected_image_decrypt(), so that callers can report them the
|
||||
* same way, whether they mount the image themselves or through mountfsd. */
|
||||
if (streq(error_id, "io.systemd.MountFileSystem.KeyNotFound"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EDESTADDRREQ),
|
||||
"mountfsd refused the image, because no trusted key validates its signature.");
|
||||
if (streq(error_id, "io.systemd.MountFileSystem.DeniedByImagePolicy"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERFKILL),
|
||||
"mountfsd refused the image, because the image policy doesn't permit it.");
|
||||
|
||||
r = sd_varlink_error_to_errno(error_id, reply);
|
||||
if (r != -EBADR)
|
||||
return log_error_errno(r, "Failed to issue MountImage() varlink call: %m");
|
||||
|
||||
return log_error_errno(r, "Failed to issue MountImage() varlink call: %s", error_id);
|
||||
}
|
||||
|
||||
r = sd_json_dispatch(reply, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &p);
|
||||
if (r < 0)
|
||||
@@ -5741,12 +5755,10 @@ int mountfsd_mount_directory_fd(
|
||||
}
|
||||
|
||||
sd_json_variant *reply = NULL;
|
||||
const char *error_id = NULL;
|
||||
r = varlink_callbo_and_log(
|
||||
vl,
|
||||
"io.systemd.MountFileSystem.MountDirectory",
|
||||
&reply,
|
||||
&error_id,
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("directoryFileDescriptor", 0),
|
||||
SD_JSON_BUILD_PAIR_CONDITION(userns_fd >= 0, "userNamespaceFileDescriptor", SD_JSON_BUILD_UNSIGNED(1)),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("readOnly", FLAGS_SET(flags, DISSECT_IMAGE_MOUNT_READ_ONLY)),
|
||||
|
||||
@@ -75,7 +75,7 @@ int pcrextend_pcr_now(unsigned pcr, const char *word, const struct iovec *secret
|
||||
log_debug("Measurement of '%s' into PCR %u completed.", word, pcr);
|
||||
return 1;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring.");
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ int pcrextend_nvpcr_now(const char *nvpcr, const char *word, const char *event)
|
||||
log_debug("Measurement of '%s' into NvPCR '%s' completed.", word, nvpcr);
|
||||
return 1;
|
||||
#else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring.");
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 support disabled, not measuring.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ at_exit() {
|
||||
mv -f /run/systemd/tpm2-pcr-signature.json.bak /run/systemd/tpm2-pcr-signature.json
|
||||
rm -f /tmp/tpm2-pcr-private-key.pem /tmp/tpm2-pcr-public-key.pem /tmp/tpm2-pcr-signature.json.valid
|
||||
rm -rf /run/nvpcr /tmp/nvpcr
|
||||
rm -f /var/tmp/nvpcr.raw /run/verity.d/test-70-nvpcr.crt
|
||||
rm -f /var/tmp/nvpcr.raw /var/tmp/nvpcr-untrusted.raw /run/verity.d/test-70-nvpcr.crt
|
||||
rm -f /run/systemd/nvpcr/test.auth /run/systemd/nvpcr/test2.auth /run/systemd/nvpcr/aaa.auth /run/systemd/nvpcr/zzz.auth /run/systemd/nvpcr/unauth.auth /run/systemd/nvpcr/unauth2.auth
|
||||
rm -f /tmp/test.policy
|
||||
rm -f /run/systemd/tpm2-nv-space-exhausted-orderly
|
||||
@@ -368,17 +368,9 @@ fi
|
||||
mkdir -p /tmp/nvpcr/tree
|
||||
touch /tmp/nvpcr/tree/file
|
||||
|
||||
if machine_supports_verity_keyring; then
|
||||
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
|
||||
systemd-repart -P \
|
||||
-s /tmp/nvpcr/tree \
|
||||
--certificate=/usr/share/mkosi.crt \
|
||||
--private-key=/usr/share/mkosi.key \
|
||||
/var/tmp/nvpcr.raw
|
||||
else
|
||||
OPENSSL_CONFIG="/tmp/nvpcr/opensslconfig"
|
||||
# Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
|
||||
cat >"${OPENSSL_CONFIG:?}" <<EOF
|
||||
OPENSSL_CONFIG="/tmp/nvpcr/opensslconfig"
|
||||
# Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
|
||||
cat >"${OPENSSL_CONFIG:?}" <<EOF
|
||||
[ req ]
|
||||
prompt = no
|
||||
distinguished_name = req_distinguished_name
|
||||
@@ -393,6 +385,14 @@ CN = Common Name
|
||||
emailAddress = test@email.com
|
||||
EOF
|
||||
|
||||
if machine_supports_verity_keyring; then
|
||||
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
|
||||
systemd-repart -P \
|
||||
-s /tmp/nvpcr/tree \
|
||||
--certificate=/usr/share/mkosi.crt \
|
||||
--private-key=/usr/share/mkosi.key \
|
||||
/var/tmp/nvpcr.raw
|
||||
else
|
||||
openssl req -config "$OPENSSL_CONFIG" -subj="/CN=waldo" \
|
||||
-x509 -sha256 -nodes -days 365 -newkey rsa:4096 \
|
||||
-keyout /tmp/nvpcr/test-70-nvpcr.key -out /tmp/nvpcr/test-70-nvpcr.crt
|
||||
@@ -412,5 +412,23 @@ cp /run/log/systemd/tpm2-measure.log /tmp/nvpcr/log-before
|
||||
|
||||
systemd-dissect --image-policy='root=signed:=absent+unused' --mtree /var/tmp/nvpcr.raw
|
||||
|
||||
# The record of a validated signature ends with the serial and the issuer of the signer.
|
||||
set +o pipefail
|
||||
diff /tmp/nvpcr/log-before /run/log/systemd/tpm2-measure.log | grep -F '"content":{"nvIndexName":"verity","string":"verity:'
|
||||
diff /tmp/nvpcr/log-before /run/log/systemd/tpm2-measure.log | grep -E '"content":\{"nvIndexName":"verity","string":"verity:[^"]*:[0-9a-f]+:[0-9a-f]+/[^"]+"'
|
||||
|
||||
# If neither the kernel nor userspace can validate the signature, only the root hash is measured, without
|
||||
# the signer. Neither the kernel keyring nor /run/verity.d/ contains the certificate of the untrusted key.
|
||||
openssl req -config "$OPENSSL_CONFIG" -subj="/CN=untrusted" \
|
||||
-x509 -sha256 -nodes -days 365 -newkey rsa:4096 \
|
||||
-keyout /tmp/nvpcr/untrusted.key -out /tmp/nvpcr/untrusted.crt
|
||||
|
||||
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
|
||||
systemd-repart -P \
|
||||
-s /tmp/nvpcr/tree \
|
||||
--certificate=/tmp/nvpcr/untrusted.crt \
|
||||
--private-key=/tmp/nvpcr/untrusted.key \
|
||||
/var/tmp/nvpcr-untrusted.raw
|
||||
|
||||
cp /run/log/systemd/tpm2-measure.log /tmp/nvpcr/log-before
|
||||
systemd-dissect --image-policy='root=verity+signed:=absent+unused' --mtree /var/tmp/nvpcr-untrusted.raw
|
||||
diff /tmp/nvpcr/log-before /run/log/systemd/tpm2-measure.log | grep -E '"content":\{"nvIndexName":"verity","string":"verity:[^"]*:"'
|
||||
Reference in new issue
Block a user