1
0
mirror of https://github.com/systemd/systemd synced 2026-03-02 19:24:46 +01:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Oblivionsage
b3a2444ba5 pe-binary: wrap remaining LE fields with byte-swap macros
Follow-up to 02cab70acf5ca67e838d0d34860baacbf9fc3b6c. pe_hash(),
section_offset_cmp() and uki_hash() still had a bunch of raw accesses
to LE fields (e_lfanew, SizeOfHeaders, PointerToRawData, SizeOfRawData,
VirtualSize, certificate_table->Size) without le32toh(), so they'd
produce garbage on big-endian.

Also wrap VirtualSize in bootspec.c for consistency.
2026-02-19 07:34:44 +09:00
Daan De Meyer
81cef494a6 vpick: Make suffix a single string again instead of a strv
This was made a strv to handle either directories or raw images but
since we now handle that via multiple PickFilter instances, we don't
need suffixes to be a strv anymore.
2026-02-18 23:14:11 +01:00
David Santamaría Rogado
17a3b387ae udev: rules: integration add spi bus for input dev
This bus is used for internal input devices let's set the ID_BUS
property accordingly to tag devices over SPI as internal.

Follow-up for a4381cae8bfacb1160967ac499c2919da7ff8c2b.
2026-02-19 06:45:13 +09:00
Luca Boccassi
9204838724 test: skip dnf signature checks in TEST-88-UPGRADE
Fixes failure on Rawhide:

TEST-88-UPGRADE.sh[512]: Transaction failed: Rpm transaction failed.
TEST-88-UPGRADE.sh[512]: Warning: skipped OpenPGP checks for 15 packages from repository: @commandline
TEST-88-UPGRADE.sh[512]:   - package systemd-shared-260~devel-20260218150812.fc45.x86_64 does not verify: no signature
2026-02-18 21:41:49 +00:00
Luca Boccassi
db73f1b4c6
test: assorted fixes for integration tests (#40737) 2026-02-18 20:42:15 +00:00
Luca Boccassi
af9a5121a1 test: cover both verity verification mechanisms in TEST-70-TPM2-nvpcr
Follow-up for 521a523ce0cdcf0d529bd566f3d64ae93f10419d
2026-02-18 16:20:33 +00:00
Luca Boccassi
b9813d6c95 test: move check for verity kernel keyring support to util.sh 2026-02-18 16:11:34 +00:00
Luca Boccassi
7112e4755e test: do not fail TEST-86-MULTI-PROFILE-UKI if full TPM2 support not available
On a mkosi run on GHA:

[    9.547863] TEST-86-MULTI-PROFILE-UKI.sh[458]: + /usr/lib/systemd/systemd-measure --current
[    9.552790] TEST-86-MULTI-PROFILE-UKI.sh[463]: Measuring boot phases: enter-initrd, enter-initrd:leave-initrd, enter-initrd:leave-initrd:sysinit, enter-initrd:leave-initrd:sysinit:ready
[    9.553086] TEST-86-MULTI-PROFILE-UKI.sh[463]: Found container virtualization none.
[    9.553308] TEST-86-MULTI-PROFILE-UKI.sh[463]: Reading EFI variable /sys/firmware/efi/efivars/LoaderTpm2ActivePcrBanks-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f.
[    9.553486] TEST-86-MULTI-PROFILE-UKI.sh[463]: Loaded shared library 'libtss2-esys.so.0' via dlopen().
[    9.553676] TEST-86-MULTI-PROFILE-UKI.sh[463]: Loaded shared library 'libtss2-rc.so.0' via dlopen().
[    9.553867] TEST-86-MULTI-PROFILE-UKI.sh[463]: Loaded shared library 'libtss2-mu.so.0' via dlopen().
[    9.554050] TEST-86-MULTI-PROFILE-UKI.sh[463]: Sorry, system lacks full TPM2 support.
[FAILED] Failed to start TEST-86-MULTI-PROFILE-UKI.service - TEST-86-MULTI-PROFILE-UKI.
2026-02-18 15:39:13 +00:00
14 changed files with 79 additions and 60 deletions

View File

@ -11,6 +11,7 @@ SUBSYSTEMS=="platform", ENV{ID_BUS}="platform"
SUBSYSTEMS=="i2c", ENV{ID_BUS}="i2c"
SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi"
SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042"
SUBSYSTEMS=="spi", ENV{ID_BUS}="spi"
SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id"

View File

@ -6,8 +6,8 @@
ACTION=="remove", GOTO="integration_end"
ENV{ID_BUS}=="", GOTO="integration_end"
# ACPI, platform, PS/2, I2C, RMI and PCI devices: Internal by default.
ENV{ID_BUS}=="acpi|platform|i8042|i2c|rmi|pci", ENV{ID_INTEGRATION}="internal"
# ACPI, platform, PS/2, I2C, RMI, SPI and PCI devices: Internal by default.
ENV{ID_BUS}=="acpi|platform|i8042|i2c|rmi|spi|pci", ENV{ID_INTEGRATION}="internal"
# Bluetooth devices: External by default.
ENV{ID_BUS}=="bluetooth", ENV{ID_INTEGRATION}="external"

View File

@ -1020,7 +1020,7 @@ static int pe_find_uki_sections(
}
/* Permit "masking" of sections in the base profile */
if (found->VirtualSize == 0)
if (le32toh(found->VirtualSize) == 0)
continue;
r = pe_read_section_data(fd, found, PE_SECTION_SIZE_MAX, (void**) t->data, /* ret_size= */ NULL);

View File

@ -883,7 +883,7 @@ int image_find(RuntimeScope scope,
.type_mask = endswith(suffix, ".raw") ? (UINT32_C(1) << DT_REG) | (UINT32_C(1) << DT_BLK) : (UINT32_C(1) << DT_DIR),
.basename = name,
.architecture = _ARCHITECTURE_INVALID,
.suffix = STRV_MAKE(suffix),
.suffix = suffix,
};
_cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL;
@ -1100,7 +1100,7 @@ int image_discover(
.type_mask = endswith(suffix, ".raw") ? (UINT32_C(1) << DT_REG) | (UINT32_C(1) << DT_BLK) : (UINT32_C(1) << DT_DIR),
.basename = pretty,
.architecture = _ARCHITECTURE_INVALID,
.suffix = STRV_MAKE(suffix),
.suffix = suffix,
};
_cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL;

View File

@ -336,7 +336,7 @@ static int hash_file(int fd, EVP_MD_CTX *md_ctx, uint64_t offset, uint64_t size)
}
static int section_offset_cmp(const IMAGE_SECTION_HEADER *a, const IMAGE_SECTION_HEADER *b) {
return CMP(ASSERT_PTR(a)->PointerToRawData, ASSERT_PTR(b)->PointerToRawData);
return CMP(le32toh(ASSERT_PTR(a)->PointerToRawData), le32toh(ASSERT_PTR(b)->PointerToRawData));
}
int pe_hash(int fd,
@ -384,7 +384,7 @@ int pe_hash(int fd,
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest.");
/* Everything from beginning of file to CheckSum field in PE header */
p = (uint64_t) dos_header->e_lfanew +
p = (uint64_t) le32toh(dos_header->e_lfanew) +
offsetof(PeHeader, optional.CheckSum);
r = hash_file(fd, mdctx, 0, p);
if (r < 0)
@ -392,7 +392,7 @@ int pe_hash(int fd,
p += sizeof(le32_t);
/* Everything between the CheckSum field and the Image Data Directory Entry for the Certification Table */
q = (uint64_t) dos_header->e_lfanew +
q = (uint64_t) le32toh(dos_header->e_lfanew) +
PE_HEADER_OPTIONAL_FIELD_OFFSET(pe_header, DataDirectory[IMAGE_DATA_DIRECTORY_INDEX_CERTIFICATION_TABLE]);
r = hash_file(fd, mdctx, p, q - p);
if (r < 0)
@ -400,7 +400,7 @@ int pe_hash(int fd,
q += sizeof(IMAGE_DATA_DIRECTORY);
/* The rest of the header + the section table */
p = pe_header->optional.SizeOfHeaders;
p = le32toh(pe_header->optional.SizeOfHeaders);
if (p < q)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "SizeOfHeaders too short.");
r = hash_file(fd, mdctx, q, p - q);
@ -411,19 +411,19 @@ int pe_hash(int fd,
typesafe_qsort(sections, le16toh(pe_header->pe.NumberOfSections), section_offset_cmp);
FOREACH_ARRAY(section, sections, le16toh(pe_header->pe.NumberOfSections)) {
r = hash_file(fd, mdctx, section->PointerToRawData, section->SizeOfRawData);
r = hash_file(fd, mdctx, le32toh(section->PointerToRawData), le32toh(section->SizeOfRawData));
if (r < 0)
return r;
p += section->SizeOfRawData;
p += le32toh(section->SizeOfRawData);
}
if ((uint64_t) st.st_size > p) {
if (st.st_size - p < certificate_table->Size)
if ((uint64_t) st.st_size - p < le32toh(certificate_table->Size))
return log_debug_errno(errno, "No space for certificate table, refusing.");
r = hash_file(fd, mdctx, p, st.st_size - p - certificate_table->Size);
r = hash_file(fd, mdctx, p, st.st_size - p - le32toh(certificate_table->Size));
if (r < 0)
return r;
@ -560,13 +560,13 @@ int uki_hash(int fd,
if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest.");
r = hash_file(fd, mdctx, section->PointerToRawData, MIN(section->VirtualSize, section->SizeOfRawData));
r = hash_file(fd, mdctx, le32toh(section->PointerToRawData), MIN(le32toh(section->VirtualSize), le32toh(section->SizeOfRawData)));
if (r < 0)
return r;
if (section->SizeOfRawData < section->VirtualSize) {
if (le32toh(section->SizeOfRawData) < le32toh(section->VirtualSize)) {
uint8_t zeroes[1024] = {};
size_t remaining = section->VirtualSize - section->SizeOfRawData;
size_t remaining = le32toh(section->VirtualSize) - le32toh(section->SizeOfRawData);
while (remaining > 0) {
size_t sz = MIN(sizeof(zeroes), remaining);

View File

@ -13,7 +13,6 @@
#include "recurse-dir.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "vpick.h"
void pick_result_done(PickResult *p) {
@ -86,8 +85,6 @@ static int format_fname(
if (FLAGS_SET(flags, PICK_TRIES) || !filter->version) /* Underspecified? */
return -ENOEXEC;
if (strv_length(filter->suffix) > 1) /* suffix is not deterministic? */
return -ENOEXEC;
/* The format for names we match goes like this:
*
@ -139,8 +136,8 @@ static int format_fname(
return -ENOMEM;
}
if (!strv_isempty(filter->suffix))
if (!strextend(&fn, filter->suffix[0]))
if (!isempty(filter->suffix))
if (!strextend(&fn, filter->suffix))
return -ENOMEM;
if (!filename_is_valid(fn))
@ -407,8 +404,8 @@ static int make_choice(
} else
e = dname;
if (!strv_isempty(filter->suffix)) {
char *sfx = endswith_strv(e, filter->suffix);
if (!isempty(filter->suffix)) {
char *sfx = endswith(e, filter->suffix);
if (!sfx)
continue;
@ -511,7 +508,6 @@ static int path_pick_one(
PickResult *ret) {
_cleanup_free_ char *filter_bname = NULL, *dir = NULL, *parent = NULL, *fname = NULL;
char * const *filter_suffix_strv = NULL;
const char *filter_suffix = NULL, *enumeration_path;
uint32_t filter_type_mask;
int r;
@ -569,11 +565,13 @@ static int path_pick_one(
return -ENOMEM;
/* Chop off suffix, if specified */
char *f = endswith_strv(filter_bname, filter->suffix);
if (f)
*f = 0;
if (!isempty(filter->suffix)) {
char *f = endswith(filter_bname, filter->suffix);
if (f)
*f = 0;
}
filter_suffix_strv = filter->suffix;
filter_suffix = filter->suffix;
filter_type_mask = filter->type_mask;
enumeration_path = path;
@ -633,7 +631,7 @@ static int path_pick_one(
.basename = filter_bname,
.version = filter->version,
.architecture = filter->architecture,
.suffix = filter_suffix_strv ?: STRV_MAKE(filter_suffix),
.suffix = filter_suffix,
},
flags,
ret);
@ -790,7 +788,7 @@ const PickFilter pick_filter_image_raw[1] = {
{
.type_mask = (UINT32_C(1) << DT_REG) | (UINT32_C(1) << DT_BLK),
.architecture = _ARCHITECTURE_INVALID,
.suffix = STRV_MAKE(".raw"),
.suffix = ".raw",
},
};

View File

@ -17,7 +17,7 @@ typedef struct PickFilter {
const char *basename; /* Can be overridden by search pattern */
const char *version;
Architecture architecture;
char * const *suffix; /* Can be overridden by search pattern */
const char *suffix; /* Can be overridden by search pattern */
} PickFilter;
typedef struct PickResult {

View File

@ -44,7 +44,7 @@ TEST(path_pick) {
PickFilter filter = {
.architecture = _ARCHITECTURE_INVALID,
.suffix = STRV_MAKE(".raw"),
.suffix = ".raw",
};
if (IN_SET(native_architecture(), ARCHITECTURE_X86, ARCHITECTURE_X86_64)) {

View File

@ -245,7 +245,7 @@ static int run(int argc, char *argv[]) {
.basename = arg_filter_basename,
.version = arg_filter_version,
.architecture = arg_filter_architecture,
.suffix = STRV_MAKE(arg_filter_suffix),
.suffix = arg_filter_suffix,
.type_mask = arg_filter_type_mask,
},
/* n_filters= */ 1,

View File

@ -37,13 +37,7 @@ trap at_exit EXIT
# For unprivileged tests
loginctl enable-linger testuser
# Requires kernel built with certain kconfigs, as listed in README:
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
( . /etc/os-release; [ "$ID" != "debian" ] || [ -z "${VERSION_ID:-}" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
if machine_supports_verity_keyring; then
export VERITY_SIG_SUPPORTED=1
else
export VERITY_SIG_SUPPORTED=0

View File

@ -54,11 +54,20 @@ DIGEST_MEASURED2="$(echo -n "schnurz" | openssl dgst -sha256 -hex -r | cut -d' '
DIGEST_EXPECTED2="$(echo "$DIGEST_EXPECTED$DIGEST_MEASURED2" | tr '[:lower:]' '[:upper:]' | basenc --base16 -d | openssl dgst -sha256 -hex -r | cut -d' ' -f1)"
test "$DIGEST_ACTUAL2" = "$DIGEST_EXPECTED2"
mkdir /tmp/nvpcr
mkdir -p /tmp/nvpcr/tree
touch /tmp/nvpcr/tree/file
OPENSSL_CONFIG="/tmp/nvpcr/opensslconfig"
# Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
cat >"${OPENSSL_CONFIG:?}" <<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_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
@ -73,22 +82,20 @@ CN = Common Name
emailAddress = test@email.com
EOF
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
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
mkdir /tmp/nvpcr/tree
touch /tmp/nvpcr/tree/file
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
systemd-repart -P \
-s /tmp/nvpcr/tree \
--certificate=/tmp/nvpcr/test-70-nvpcr.crt \
--private-key=/tmp/nvpcr/test-70-nvpcr.key \
/var/tmp/nvpcr.raw
SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs \
systemd-repart -P \
-s /tmp/nvpcr/tree \
--certificate=/tmp/nvpcr/test-70-nvpcr.crt \
--private-key=/tmp/nvpcr/test-70-nvpcr.key \
/var/tmp/nvpcr.raw
mkdir -p /run/verity.d
cp /tmp/nvpcr/test-70-nvpcr.crt /run/verity.d/
mkdir -p /run/verity.d
cp /tmp/nvpcr/test-70-nvpcr.crt /run/verity.d/
fi
cp /run/log/systemd/tpm2-measure.log /tmp/nvpcr/log-before

View File

@ -5,6 +5,11 @@ set -o pipefail
export SYSTEMD_LOG_LEVEL=debug
if ! systemd-analyze has-tpm2; then
echo "Full TPM2 support not available, skipping the test"
exit 0
fi
bootctl
CURRENT_UKI=$(bootctl --print-stub-path)

View File

@ -84,7 +84,7 @@ timer2=$(systemctl show -P NextElapseUSecRealtime upgrade_timer_test.timer)
# FIXME: See https://github.com/systemd/systemd/pull/39293
systemctl stop systemd-networkd-resolve-hook.socket || true
dnf downgrade -y --allowerasing --disablerepo '*' "$pkgdir"/distro/*.rpm
dnf downgrade --no-gpgchecks -y --allowerasing --disablerepo '*' "$pkgdir"/distro/*.rpm
# Some distros don't ship networkd, so the test will always fail
if command -v networkctl >/dev/null; then
@ -105,7 +105,7 @@ fi
check_sd
# Finally test the upgrade
dnf -y upgrade --disablerepo '*' "$pkgdir"/devel/*.rpm
dnf -y upgrade --no-gpgchecks --disablerepo '*' "$pkgdir"/devel/*.rpm
# TODO: sanity checks
check_sd

View File

@ -285,6 +285,20 @@ kernel_supports_lsm() {
return 1
}
machine_supports_verity_keyring() {
# Requires kernel built with certain kconfigs, as listed in README:
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
( . /etc/os-release; [ "$ID" != "debian" ] || [ -z "${VERSION_ID:-}" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
return 0
fi
return 1
}
install_extension_images() {
local os_release
os_release="$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)"