systemd-tests-255.18-alt1.x86_64 unsafe-tmp-usage-in-scripts fail The test discovered scripts with errors which may be used by a user for damaging important system files. For example if a script uses in its work a temp file which is created in /tmp directory, then every user can create symlinks with the same name (pattern) in this directory in order to destroy or rewrite some system or another user's files. Scripts _must_ _use_ mktemp/tempfile or must use $TMPDIR. mktemp/tempfile is safest. $TMPDIR is safer than /tmp/ because libpam-tmpdir creates a subdirectory of /tmp that is only accessible by that user, and then sets TMPDIR and other variables to that. Hence, it doesn't matter nearly as much if you create a non-random filename, because nobody but you can access it. Found error in /usr/lib/systemd/tests/testdata/units/testsuite-82.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-82.sh test "$(systemctl show -P ActiveState testsuite-82-survive-argv.service)" = "active" test "$(systemctl show -P ActiveState testsuite-82-nosurvive-sigterm.service)" != "active" test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active" # This time we test the /run/nextroot/ root switching logic. (We synthesize a new rootfs from the old via overlayfs) mkdir -p /run/nextroot /tmp/nextroot-lower /original-root mount -t tmpfs tmpfs /tmp/nextroot-lower echo miep >/tmp/nextroot-lower/lower # Copy os-release away, so that we can manipulate it and check that it is updated in the propagate # directory across soft reboots. Try to cover corner cases by truncating it. mkdir -p /tmp/nextroot-lower/etc grep ID /etc/os-release >/tmp/nextroot-lower/etc/os-release echo MARKER=1 >>/tmp/nextroot-lower/etc/os-release cmp /etc/os-release /run/systemd/propagate/.os-release-stage/os-release (! grep -q MARKER=1 /etc/os-release) mount -t overlay nextroot /run/nextroot -o lowerdir=/tmp/nextroot-lower:/,ro # Bind our current root into the target so that we later can return to it mount --bind / /run/nextroot/original-root # Restart the unit that is not supposed to survive Found error in /usr/lib/systemd/tests/testdata/units/testsuite-81.system-update-generator.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-81.system-update-generator.sh # shellcheck source=test/units/generator-utils.sh . "$(dirname "$0")/generator-utils.sh" GENERATOR_BIN="/usr/lib/systemd/system-generators/systemd-system-update-generator" OUT_DIR="$(mktemp -d /tmp/system-update-generator-generator.XXX)" at_exit() { rm -frv "${OUT_DIR:?}" /system-update } -- link_endswith "$OUT_DIR/early/default.target" "/lib/systemd/system/system-update.target" : "system-update-generator: kernel cmdline warnings" # We should warn if the default target is overridden on the kernel cmdline # by a runlevel or systemd.unit=, but still generate the symlink SYSTEMD_PROC_CMDLINE="systemd.unit=foo.bar 3" run_and_list "$GENERATOR_BIN" "$OUT_DIR" |& tee /tmp/system-update-generator.log link_endswith "$OUT_DIR/early/default.target" "/lib/systemd/system/system-update.target" grep -qE "Offline system update overridden .* systemd.unit=" /tmp/system-update-generator.log grep -qE "Offline system update overridden .* runlevel" /tmp/system-update-generator.log Found error in /usr/lib/systemd/tests/testdata/units/testsuite-81.getty-generator.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-81.getty-generator.sh # shellcheck source=test/units/generator-utils.sh . "$(dirname "$0")/generator-utils.sh" GENERATOR_BIN="/usr/lib/systemd/system-generators/systemd-getty-generator" OUT_DIR="$(mktemp -d /tmp/getty-generator.XXX)" at_exit() { rm -frv "${OUT_DIR:?}" } -- done # Sneak in one "not-a-tty" console touch /dev/notatty99 # Temporarily replace /sys/class/tty/console/active with our list of dummy # consoles so getty-generator can process them echo -ne "${DUMMY_ACTIVE_CONSOLES[@]}" /dev/notatty99 >/tmp/dummy-active-consoles mount -v --bind /tmp/dummy-active-consoles /sys/class/tty/console/active : "getty-generator: no arguments" # Sneak in an invalid value for $SYSTEMD_GETTY_AUTO to test things out PID1_ENVIRON="SYSTEMD_GETTY_AUTO=foo" run_and_list "$GENERATOR_BIN" "$OUT_DIR" for console in "${DUMMY_ACTIVE_CONSOLES[@]}"; do Found error in /usr/lib/systemd/tests/testdata/units/testsuite-80.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-80.sh set -o pipefail # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh mkfifo /tmp/syncfifo1 /tmp/syncfifo2 sync_in() { read -r x < /tmp/syncfifo1 test "$x" = "$1" } sync_out() { echo "$1" > /tmp/syncfifo2 } export SYSTEMD_LOG_LEVEL=debug systemctl --no-block start notify.service -- assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "none" systemctl stop notify.service assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all" rm /tmp/syncfifo1 /tmp/syncfifo2 # Now test basic fdstore behaviour MYSCRIPT="/tmp/myscript$RANDOM.sh" cat >> "$MYSCRIPT" <<'EOF' #!/usr/bin/env bash set -eux set -o pipefail test "$FDSTORE" -eq 7 N="/tmp/$RANDOM" echo $RANDOM > "$N" systemd-notify --fd=4 --fdname=quux --pid=parent 4< "$N" rm "$N" systemd-notify --ready exec sleep infinity -- MYUNIT="myunit$RANDOM.service" systemd-run -u "$MYUNIT" -p Type=notify -p FileDescriptorStoreMax=7 "$MYSCRIPT" test "$(systemd-analyze fdstore "$MYUNIT" | wc -l)" -eq 2 systemd-analyze fdstore "$MYUNIT" --json=short systemd-analyze fdstore "$MYUNIT" --json=short | grep -P -q '\[{"fdname":"quux","type":.*,"devno":\[.*\],"inode":.*,"rdevno":null,"path":"/tmp/.*","flags":"ro"}\]' systemctl stop "$MYUNIT" rm "$MYSCRIPT" systemd-analyze log-level debug Found error in /usr/lib/systemd/tests/testdata/units/testsuite-76.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-76.sh # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh export SYSTEMD_LOG_LEVEL=debug echo "foo.bar=42" >/tmp/foo.conf assert_rc 0 /usr/lib/systemd/systemd-sysctl /tmp/foo.conf assert_rc 1 /usr/lib/systemd/systemd-sysctl --strict /tmp/foo.conf echo "-foo.foo=42" >/tmp/foo.conf assert_rc 0 /usr/lib/systemd/systemd-sysctl /tmp/foo.conf assert_rc 0 /usr/lib/systemd/systemd-sysctl --strict /tmp/foo.conf if ! systemd-detect-virt --quiet --container; then ip link add hoge type dummy udevadm wait /sys/class/net/hoge cat >/tmp/foo.conf </proc/sys/net/ipv4/conf/hoge/drop_gratuitous_arp echo 0 >/proc/sys/net/ipv4/conf/hoge/bootp_relay echo 0 >/proc/sys/net/ipv4/conf/hoge/disable_policy assert_rc 0 /usr/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/hoge /tmp/foo.conf assert_eq "$(cat /proc/sys/net/ipv4/conf/hoge/drop_gratuitous_arp)" "1" assert_eq "$(cat /proc/sys/net/ipv4/conf/hoge/bootp_relay)" "1" assert_eq "$(cat /proc/sys/net/ipv4/conf/hoge/disable_policy)" "0" fi Found error in /usr/lib/systemd/tests/testdata/units/testsuite-74.modules-load.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-74.modules-load.sh "$MODULES_LOAD_BIN" --version # Explicit config file modprobe -v --all --remove loop dummy printf "loop\ndummy" >"$CONFIG_FILE" "$MODULES_LOAD_BIN" "$CONFIG_FILE" |& tee /tmp/out.log grep -E "Inserted module .*loop" /tmp/out.log grep -E "Inserted module .*dummy" /tmp/out.log # Implicit config file modprobe -v --all --remove loop dummy printf "loop\ndummy" >"$CONFIG_FILE" "$MODULES_LOAD_BIN" |& tee /tmp/out.log grep -E "Inserted module .*loop" /tmp/out.log grep -E "Inserted module .*dummy" /tmp/out.log # Valid & invalid data mixed together modprobe -v --all --remove loop dummy cat >"$CONFIG_FILE" </tmp/core.redirected test -s /tmp/core.redirected coredumpctl dump -o /tmp/core.output "${CORE_TEST_BIN##*/}" test -s /tmp/core.output rm -f /tmp/core.{output,redirected} # Unprivileged stuff # Related issue: https://github.com/systemd/systemd/issues/26912 UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --) # Trigger a couple of coredumps as an unprivileged user -- "${UNPRIV_CMD[@]}" coredumpctl info "$CORE_TEST_UNPRIV_BIN" "${UNPRIV_CMD[@]}" coredumpctl info "${CORE_TEST_UNPRIV_BIN##*/}" (! "${UNPRIV_CMD[@]}" coredumpctl info --all "$CORE_TEST_BIN") (! "${UNPRIV_CMD[@]}" coredumpctl info --all "${CORE_TEST_BIN##*/}") # We should have a couple of externally stored coredumps "${UNPRIV_CMD[@]}" coredumpctl --field=COREDUMP_FILENAME | tee /tmp/coredumpctl.out grep "/var/lib/systemd/coredump/core" /tmp/coredumpctl.out rm -f /tmp/coredumpctl.out "${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true "$CORE_TEST_UNPRIV_BIN" "${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true --debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_UNPRIV_BIN##*/}" "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_UNPRIV_BIN" >/tmp/core.redirected test -s /tmp/core.redirected "${UNPRIV_CMD[@]}" coredumpctl dump -o /tmp/core.output "${CORE_TEST_UNPRIV_BIN##*/}" test -s /tmp/core.output rm -f /tmp/core.{output,redirected} (! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null) # --backtrace mode # Pass one of the existing journal coredump records to systemd-coredump and # use our PID as the source to make matching the coredump later easier Found error in /usr/lib/systemd/tests/testdata/units/testsuite-70.pcrlock.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-70.pcrlock.sh # means we'll fail consistency check, but at least we'll fail them consistently # (as the PCR values simply won't match the log). rm -f /run/log/systemd/tpm2-measure.log # Ensure a truncated log doesn't crash pcrlock echo -n -e \\x1e >/tmp/borked set +e SYSTEMD_MEASURE_LOG_USERSPACE=/tmp/borked "$SD_PCRLOCK" cel --no-pager --json=pretty ret=$? set -e # If it crashes the exit code will be 149 test $ret -eq 1 -- PIN=huhu "$SD_PCRLOCK" make-policy --pcr="$PCRS" --recovery-pin=yes # Repeat immediately (this call will have to reuse the nvindex, rather than create it) "$SD_PCRLOCK" make-policy --pcr="$PCRS" "$SD_PCRLOCK" make-policy --pcr="$PCRS" --force img="/tmp/pcrlock.img" truncate -s 20M "$img" echo -n hoho >/tmp/pcrlockpwd chmod 0600 /tmp/pcrlockpwd cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$img" /tmp/pcrlockpwd systemd-cryptenroll --unlock-key-file=/tmp/pcrlockpwd --tpm2-device=auto --tpm2-pcrlock=/var/lib/systemd/pcrlock.json --tpm2-public-key= --wipe-slot=tpm2 "$img" systemd-cryptsetup attach pcrlock "$img" - tpm2-device=auto,tpm2-pcrlock=/var/lib/systemd/pcrlock.json,headless systemd-cryptsetup detach pcrlock # Ensure systemd-pcrlock not crashing on empty variant directory mkdir -p /var/lib/pcrlock.d/123-empty.pcrlock.d -- (! "$SD_PCRLOCK" lock-pe /bin/true) (! "$SD_PCRLOCK" lock-uki /dev/full) (! "$SD_PCRLOCK" lock-uki /bin/true) (! "$SD_PCRLOCK" lock-file-system "") rm "$img" /tmp/pcrlockpwd Found error in /usr/lib/systemd/tests/testdata/units/testsuite-70.measure.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-70.measure.sh if [[ ! -x "${SD_MEASURE:?}" ]]; then echo "$SD_MEASURE not found, skipping the test" exit 0 fi IMAGE="$(mktemp /tmp/systemd-measure-XXX.image)" echo HALLO >/tmp/tpmdata1 echo foobar >/tmp/tpmdata2 cat >/tmp/result </tmp/result.json </tmp/result </tmp/result.json </dev/null; then MEASURE_BANKS+=("--bank=sha1") fi # Sign current PCR state with it "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: | tee "/tmp/pcrsign.sig" dd if=/dev/urandom of=/tmp/pcrtestdata bs=1024 count=64 systemd-creds encrypt /tmp/pcrtestdata /tmp/pcrtestdata.encrypted --with-key=host+tpm2-with-public-key --tpm2-public-key="/tmp/pcrsign-public.pem" systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" | cmp - /tmp/pcrtestdata # Invalidate PCR, decrypting should fail now tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000 (! systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig" >/dev/null) # Sign new PCR state, decrypting should work now. "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig2" systemd-creds decrypt /tmp/pcrtestdata.encrypted - --tpm2-signature="/tmp/pcrsign.sig2" | cmp - /tmp/pcrtestdata # Now, do the same, but with a cryptsetup binding truncate -s 20M "$IMAGE" cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/passphrase # Ensure that an unrelated signature, when not requested, is not used touch /run/systemd/tpm2-pcr-signature.json systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" "$IMAGE" # Reset and use the signature now rm -f /run/systemd/tpm2-pcr-signature.json systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE" systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto --tpm2-public-key="/tmp/pcrsign-public.pem" --tpm2-signature="/tmp/pcrsign.sig2" "$IMAGE" # Check if we can activate that (without the token module stuff) SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1 SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup detach test-volume2 # Check if we can activate that (and a second time with the token module stuff enabled) SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1 SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup detach test-volume2 # After extending the PCR things should fail tpm2_pcrextend 11:sha256=0000000000000000000000000000000000000000000000000000000000000000 (! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1) (! SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig2",headless=1) # But once we sign the current PCRs, we should be able to unlock again "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: >"/tmp/pcrsign.sig3" SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1 systemd-cryptsetup detach test-volume2 SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=1 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig3",headless=1 systemd-cryptsetup detach test-volume2 # Test --append mode and de-duplication. With the same parameters signing should not add a new entry "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig3" >"/tmp/pcrsign.sig4" cmp "/tmp/pcrsign.sig3" "/tmp/pcrsign.sig4" # Sign one more phase, this should "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig4" >"/tmp/pcrsign.sig5" (! cmp "/tmp/pcrsign.sig4" "/tmp/pcrsign.sig5") # Should still be good to unlock, given the old entry still exists SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE=0 systemd-cryptsetup attach test-volume2 "$IMAGE" - tpm2-device=auto,tpm2-signature="/tmp/pcrsign.sig5",headless=1 systemd-cryptsetup detach test-volume2 # Adding both signatures once more should not change anything, due to the deduplication "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=: --append="/tmp/pcrsign.sig5" >"/tmp/pcrsign.sig6" "$SD_MEASURE" sign --current "${MEASURE_BANKS[@]}" --private-key="/tmp/pcrsign-private.pem" --public-key="/tmp/pcrsign-public.pem" --phase=quux:waldo --append="/tmp/pcrsign.sig6" >"/tmp/pcrsign.sig7" cmp "/tmp/pcrsign.sig5" "/tmp/pcrsign.sig7" rm -f "$IMAGE" Found error in /usr/lib/systemd/tests/testdata/units/testsuite-70.cryptsetup.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-70.cryptsetup.sh } trap at_exit EXIT # Prepare a fresh disk image IMAGE="$(mktemp /tmp/systemd-cryptsetup-XXX.IMAGE)" truncate -s 20M "$IMAGE" echo -n passphrase >/tmp/passphrase # Change file mode to avoid "/tmp/passphrase has 0644 mode that is too permissive" messages chmod 0600 /tmp/passphrase cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/passphrase # Unlocking via keyfile systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto "$IMAGE" # Enroll unlock with default PCR policy PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto "$IMAGE" systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1 systemd-cryptsetup detach test-volume -- systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1 systemd-cryptsetup detach test-volume # Now the interesting part, enrolling using a hash value that doesn't match the current PCR value systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE" tpm2_pcrread -Q -o /tmp/pcr.dat sha256:12 CURRENT_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12) EXPECTED_PCR_VALUE=$(cat /tmp/pcr.dat /tmp/pcr.dat | openssl dgst -sha256 -r | cut -d ' ' -f 1) PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="12:sha256=$EXPECTED_PCR_VALUE" "$IMAGE" (! systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1) tpm2_pcrextend "12:sha256=$CURRENT_PCR_VALUE" systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1 systemd-cryptsetup detach test-volume # enroll TPM using device key instead of direct access, then verify unlock using TPM tpm2_pcrread -Q -o /tmp/pcr.dat sha256:12 CURRENT_PCR_VALUE=$(cat /sys/class/tpm/tpm0/pcr-sha256/12) tpm2_readpublic -c 0x81000001 -o /tmp/srk.pub systemd-analyze srk > /tmp/srk2.pub cmp /tmp/srk.pub /tmp/srk2.pub if [ -f /run/systemd/tpm2-srk-public-key.tpm2b_public ] ; then cmp /tmp/srk.pub /run/systemd/tpm2-srk-public-key.tpm2b_public fi # --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS if openssl_supports_kdf SSKDF; then PASSWORD=passphrase systemd-cryptenroll --tpm2-device-key=/tmp/srk.pub --tpm2-pcrs="12:sha256=$CURRENT_PCR_VALUE" "$IMAGE" systemd-cryptsetup attach test-volume "$IMAGE" - tpm2-device=auto,headless=1 systemd-cryptsetup detach test-volume fi rm -f /tmp/pcr.dat /tmp/srk.pub fi # Use default (0) seal key handle systemd-cryptenroll --wipe-slot=tpm2 "$IMAGE" PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0 "$IMAGE" -- (! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x02000001 "$IMAGE") # HMAC/loaded session (! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x03000001 "$IMAGE") # Policy/saved session (! PASSWORD=passphrase systemd-cryptenroll --tpm2-device=auto --tpm2-seal-key-handle=0x40000001 "$IMAGE") # Permanent # Use non-SRK persistent seal key handle (by creating/persisting new key) PRIMARY=/tmp/primary.ctx tpm2_createprimary -c "$PRIMARY" PERSISTENT_LINE=$(tpm2_evictcontrol -c "$PRIMARY" | grep persistent-handle) PERSISTENT_HANDLE="0x${PERSISTENT_LINE##*0x}" tpm2_flushcontext -t -- systemd-cryptsetup detach test-volume # --tpm2-device-key= requires OpenSSL >= 3 with KDF-SS if openssl_supports_kdf SSKDF; then # Make sure that --tpm2-device-key= also works with systemd-repart tpm2_readpublic -c 0x81000001 -o /tmp/srk.pub mkdir /tmp/dditest cat > /tmp/dditest/50-root.conf </tmp/cryptenroll.out systemd-cryptenroll "$@" |& tee /tmp/cryptenroll.out grep -qE "Wiped slot [[:digit:]]+" /tmp/cryptenroll.out )} # There is an external issue with libcryptsetup on ppc64 that hits 95% of Ubuntu ppc64 test runs, so skip it if [[ "$(uname -m)" == "ppc64le" ]]; then echo "Skipping systemd-cryptenroll tests on ppc64le, see https://github.com/systemd/systemd/issues/27716" exit 0 fi export SYSTEMD_LOG_LEVEL=debug IMAGE="$(mktemp /tmp/systemd-cryptenroll-XXX.image)" truncate -s 20M "$IMAGE" echo -n password >/tmp/password # Change file mode to avoid "/tmp/password has 0644 mode that is too permissive" messages chmod 0600 /tmp/password cryptsetup luksFormat -q --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --use-urandom "$IMAGE" /tmp/password # Enroll additional tokens, keys, and passwords to exercise the list and wipe stuff systemd-cryptenroll --unlock-key-file=/tmp/password --tpm2-device=auto "$IMAGE" NEWPASSWORD="" systemd-cryptenroll --unlock-key-file=/tmp/password --password "$IMAGE" NEWPASSWORD=foo systemd-cryptenroll --unlock-key-file=/tmp/password --password "$IMAGE" for _ in {0..9}; do systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$IMAGE" done PASSWORD="" NEWPIN=123456 systemd-cryptenroll --tpm2-device=auto --tpm2-with-pin=true "$IMAGE" # Do some basic checks before we start wiping stuff systemd-cryptenroll "$IMAGE" systemd-cryptenroll "$IMAGE" | grep password -- (! systemd-cryptenroll "$IMAGE" | grep recovery) # We shouldn't be able to wipe all keyslots without enrolling a new key first (! systemd-cryptenroll "$IMAGE" --wipe=all) PASSWORD=foo NEWPASSWORD=foo cryptenroll_wipe_and_check "$IMAGE" --password --wipe=all # Check if the newly (and only) enrolled password works (! systemd-cryptenroll --unlock-key-file=/tmp/password --recovery-key "$IMAGE") (! PASSWORD="" systemd-cryptenroll --recovery-key "$IMAGE") PASSWORD=foo systemd-cryptenroll --recovery-key "$IMAGE" systemd-cryptenroll --fido2-with-client-pin=false "$IMAGE" systemd-cryptenroll --fido2-with-user-presence=false "$IMAGE" systemd-cryptenroll --fido2-with-user-verification=false "$IMAGE" systemd-cryptenroll --tpm2-pcrs=8 "$IMAGE" systemd-cryptenroll --tpm2-pcrs=boot-loader-code+boot-loader-config "$IMAGE" (! systemd-cryptenroll --fido2-with-client-pin=false) (! systemd-cryptenroll --fido2-with-user-presence=f "$IMAGE" /tmp/foo) (! systemd-cryptenroll --fido2-with-client-pin=1234 "$IMAGE") (! systemd-cryptenroll --fido2-with-user-presence=1234 "$IMAGE") (! systemd-cryptenroll --fido2-with-user-verification=1234 "$IMAGE") (! systemd-cryptenroll --tpm2-with-pin=1234 "$IMAGE") (! systemd-cryptenroll --recovery-key --password "$IMAGE") (! systemd-cryptenroll --password --recovery-key "$IMAGE") (! systemd-cryptenroll --password --fido2-device=auto "$IMAGE") (! systemd-cryptenroll --password --pkcs11-token-uri=auto "$IMAGE") (! systemd-cryptenroll --password --tpm2-device=auto "$IMAGE") (! systemd-cryptenroll --unlock-fido2-device=auto --unlock-fido2-device=auto "$IMAGE") (! systemd-cryptenroll --unlock-fido2-device=auto --unlock-key-file=/tmp/unlock "$IMAGE") (! systemd-cryptenroll --fido2-credential-algorithm=es512 "$IMAGE") (! systemd-cryptenroll --tpm2-public-key-pcrs=key "$IMAGE") (! systemd-cryptenroll --tpm2-pcrs=key "$IMAGE") (! systemd-cryptenroll --tpm2-pcrs=44+8 "$IMAGE") (! systemd-cryptenroll --tpm2-pcrs=hello "$IMAGE") Found error in /usr/lib/systemd/tests/testdata/units/testsuite-70.creds.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-70.creds.sh set -o pipefail export SYSTEMD_LOG_LEVEL=debug # Ensure that sandboxing doesn't stop creds from being accessible echo "test" > /tmp/testdata systemd-creds encrypt /tmp/testdata /tmp/testdata.encrypted --with-key=tpm2 # LoadCredentialEncrypted systemd-run -p PrivateDevices=yes -p LoadCredentialEncrypted=testdata.encrypted:/tmp/testdata.encrypted --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata # SetCredentialEncrypted systemd-run -p PrivateDevices=yes -p SetCredentialEncrypted=testdata.encrypted:"$(cat /tmp/testdata.encrypted)" --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata rm -f /tmp/testdata Found error in /usr/lib/systemd/tests/testdata/units/testsuite-68.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-68.sh ExecStart=sh -c "exit 0" EOF # Script to check that when an OnSuccess= dependency fires, the correct # MONITOR* env variables are passed. cat >/tmp/check_on_success.sh <<"EOF" #!/bin/sh set -ex env | sort if [ "$MONITOR_SERVICE_RESULT" != "success" ]; then -- exit 1 fi exit 0 EOF chmod +x /tmp/check_on_success.sh cat >/run/systemd/system/testservice-success-exit-handler-68.service </run/systemd/system/testservice-success-exit-handler-68-template@.service </tmp/check_on_failure.sh <<"EOF" #!/bin/sh set -ex env | sort if [ "$MONITOR_SERVICE_RESULT" != "exit-code" ]; then -- exit 1 fi exit 0 EOF chmod +x /tmp/check_on_failure.sh cat >/run/systemd/system/testservice-failure-exit-handler-68.service </run/systemd/system/testservice-failure-exit-handler-68-template@.service </tmp/out1 chroot /tmp/root systemd-analyze cat-config systemd/system-preset >/tmp/out2 diff /tmp/out{1,2} fi # verify mkdir -p /tmp/img/usr/lib/systemd/system/ mkdir -p /tmp/img/opt/ touch /tmp/img/opt/script0.sh chmod +x /tmp/img/opt/script0.sh cat </tmp/img/usr/lib/systemd/system/testfile.service [Service] ExecStart = /opt/script0.sh EOF set +e # Default behaviour is to recurse through all dependencies when unit is loaded (! systemd-analyze verify --root=/tmp/img/ testfile.service) # As above, recurses through all dependencies when unit is loaded (! systemd-analyze verify --recursive-errors=yes --root=/tmp/img/ testfile.service) # Recurses through unit file and its direct dependencies when unit is loaded (! systemd-analyze verify --recursive-errors=one --root=/tmp/img/ testfile.service) set -e # zero exit status since dependencies are ignored when unit is loaded systemd-analyze verify --recursive-errors=no --root=/tmp/img/ testfile.service rm /tmp/img/usr/lib/systemd/system/testfile.service cat </tmp/testfile.service [Unit] foo = bar [Service] ExecStart = echo hello EOF cat </tmp/testfile2.service [Unit] Requires = testfile.service [Service] ExecStart = echo hello EOF # Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded systemd-analyze verify --recursive-errors=no /tmp/testfile2.service set +e # Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded (! systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service) set -e rm /tmp/testfile.service rm /tmp/testfile2.service cat </tmp/sample.service [Unit] Description = A Sample Service [Service] ExecStart = echo hello Slice=support.slice EOF # Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded systemd-analyze verify --recursive-errors=no /tmp/sample.service cat </tmp/testfile.service [Service] ExecStart = echo hello DeviceAllow=/dev/sda EOF # Prevent regression from #13380 and #20859 where we can't verify hidden files cp /tmp/testfile.service /tmp/.testfile.service systemd-analyze verify /tmp/.testfile.service rm /tmp/.testfile.service # Alias a unit file's name on disk (see #20061) cp /tmp/testfile.service /tmp/testsrvc (! systemd-analyze verify /tmp/testsrvc) systemd-analyze verify /tmp/testsrvc:alias.service # Zero exit status since the value used for comparison determine exposure to security threats is by default 100 systemd-analyze security --offline=true /tmp/testfile.service #The overall exposure level assigned to the unit is greater than the set threshold (! systemd-analyze security --threshold=90 --offline=true /tmp/testfile.service) # Ensure we print the list of ACLs, see https://github.com/systemd/systemd/issues/23185 systemd-analyze security --offline=true /tmp/testfile.service | grep -q -F "/dev/sda" rm /tmp/testfile.service cat </tmp/img/usr/lib/systemd/system/testfile.service [Service] ExecStart = echo hello PrivateNetwork = yes PrivateDevices = yes PrivateUsers = yes EOF # The new overall exposure level assigned to the unit is less than the set thresholds # Verifies that the --offline= option works with --root= systemd-analyze security --threshold=90 --offline=true --root=/tmp/img/ testfile.service cat </tmp/foo@.service [Service] ExecStart=ls EOF cat </tmp/hoge@test.service [Service] ExecStart=ls EOF # issue #30357 -- systemd-analyze verify tmp/hoge@test.service (! systemd-analyze verify tmp/hoge@nonexist.service) (! systemd-analyze verify tmp/hoge@.service) popd pushd /usr systemd-analyze verify ../tmp/foo@bar.service systemd-analyze verify ../tmp/foo@.service systemd-analyze verify ../tmp/hoge@test.service (! systemd-analyze verify ../tmp/hoge@nonexist.service) (! systemd-analyze verify ../tmp/hoge@.service) popd systemd-analyze verify /tmp/foo@bar.service systemd-analyze verify /tmp/foo@.service systemd-analyze verify /tmp/hoge@test.service (! systemd-analyze verify /tmp/hoge@nonexist.service) (! systemd-analyze verify /tmp/hoge@.service) # Added an additional "INVALID_ID" id to the .json to verify that nothing breaks when input is malformed # The PrivateNetwork id description and weight was changed to verify that 'security' is actually reading in # values from the .json file when required. The default weight for "PrivateNetwork" is 2500, and the new weight # assigned to that id in the .json file is 6000. This increased weight means that when the "PrivateNetwork" key is # set to 'yes' (as above in the case of testfile.service) in the content of the unit file, the overall exposure # level for the unit file should decrease to account for that increased weight. cat </tmp/testfile.json {"UserOrDynamicUser": {"description_bad": "Service runs as root user", "weight": 0, "range": 10 }, -- } EOF # Reads in custom security requirements from the parsed .json file and uses these for comparison systemd-analyze security --threshold=90 --offline=true \ --security-policy=/tmp/testfile.json \ --root=/tmp/img/ testfile.service # The strict profile adds a lot of sanboxing options systemd-analyze security --threshold=25 --offline=true \ --security-policy=/tmp/testfile.json \ --profile=strict \ --root=/tmp/img/ testfile.service # The trusted profile doesn't add any sanboxing options (! systemd-analyze security --threshold=25 --offline=true \ --security-policy=/tmp/testfile.json \ --profile=/usr/lib/systemd/portable/profile/trusted/service.conf \ --root=/tmp/img/ testfile.service) (! systemd-analyze security --threshold=50 --offline=true \ --security-policy=/tmp/testfile.json \ --root=/tmp/img/ testfile.service) rm /tmp/img/usr/lib/systemd/system/testfile.service if systemd-analyze --version | grep -q -F "+ELFUTILS"; then systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"' fi Found error in /usr/lib/systemd/tests/testdata/units/testsuite-63.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-63.sh systemctl log-level debug # Test that a path unit continuously triggering a service that fails condition checks eventually fails with # the trigger-limit-hit error. rm -f /tmp/nonexistent systemctl start test63.path touch /tmp/test63 # Make sure systemd has sufficient time to hit the trigger limit for test63.path. # shellcheck disable=SC2016 timeout 30 bash -c 'until test "$(systemctl show test63.path -P ActiveState)" = failed; do sleep .2; done' test "$(systemctl show test63.service -P ActiveState)" = inactive test "$(systemctl show test63.service -P Result)" = success test "$(systemctl show test63.path -P Result)" = trigger-limit-hit # Test that starting the service manually doesn't affect the path unit. rm -f /tmp/test63 systemctl reset-failed systemctl start test63.path systemctl start test63.service test "$(systemctl show test63.service -P ActiveState)" = inactive test "$(systemctl show test63.service -P Result)" = success test "$(systemctl show test63.path -P ActiveState)" = active test "$(systemctl show test63.path -P Result)" = success # Test that glob matching works too, with $TRIGGER_PATH systemctl start test63-glob.path touch /tmp/test63-glob-foo timeout 60 bash -c 'until systemctl -q is-active test63-glob.service; do sleep .2; done' test "$(systemctl show test63-glob.service -P ActiveState)" = active test "$(systemctl show test63-glob.service -P Result)" = success test "$(busctl --json=short get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/test63_2dglob_2eservice org.freedesktop.systemd1.Unit ActivationDetails)" = '{"type":"a(ss)","data":[["trigger_unit","test63-glob.path"],["trigger_path","/tmp/test63-glob-foo"]]}' systemctl stop test63-glob.path test63-glob.service test "$(busctl --json=short get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/test63_2dglob_2eservice org.freedesktop.systemd1.Unit ActivationDetails)" = '{"type":"a(ss)","data":[]}' # tests for issue https://github.com/systemd/systemd/issues/24577#issuecomment-1522628906 rm -f /tmp/hoge systemctl start test63-issue-24577.path systemctl status -n 0 test63-issue-24577.path systemctl status -n 0 test63-issue-24577.service || : systemctl list-jobs output=$(systemctl list-jobs --no-legend) assert_not_in "test63-issue-24577.service" "$output" assert_not_in "test63-issue-24577-dep.service" "$output" touch /tmp/hoge systemctl status -n 0 test63-issue-24577.path systemctl status -n 0 test63-issue-24577.service || : systemctl list-jobs output=$(systemctl list-jobs --no-legend) assert_in "test63-issue-24577.service" "$output" -- systemctl list-jobs output=$(systemctl list-jobs --no-legend) assert_in "test63-issue-24577.service" "$output" assert_in "test63-issue-24577-dep.service" "$output" rm -f /tmp/hoge systemctl stop test63-issue-24577.service systemctl status -n 0 test63-issue-24577.path systemctl status -n 0 test63-issue-24577.service || : systemctl list-jobs output=$(systemctl list-jobs --no-legend) -- assert_in "test63-issue-24577-dep.service" "$output" # Test for race condition fixed by https://github.com/systemd/systemd/pull/30768 # Here's the schedule of events that we to happen during this test: # (This test) (The service) # .path unit monitors /tmp/copyme for changes # Take lock on /tmp/noexeit ↓ # Write to /tmp/copyme ↓ # Wait for deactivating Started # ↓ Copies /tmp/copyme to /tmp/copied # ↓ Tells manager it's shutting down # Ensure service did the copy Tries to lock /tmp/noexit and blocks # Write to /tmp/copyme ↓ # # Now at this point the test can diverge. If we regress, this second write is # missed and we'll see: # ... (second write) ... (blocked) # Drop lock on /tmp/noexit ↓ # Wait for service to do copy Unblocks and exits # ↓ (dead) # ↓ # (timeout) # Test fails # # Otherwise, we'll see: # ... (second write) ... (blocked) # Drop lock on /tmp/noexit ↓ and .path unit queues a new start job # Wait for service to do copy Unblocks and exits # ↓ Starts again b/c of queued job # ↓ Copies again # Test Passes systemctl start test63-pr-30768.path exec {lock}<>/tmp/noexit flock -e $lock echo test1 > /tmp/copyme # shellcheck disable=SC2016 timeout 30 bash -c 'until test "$(systemctl show test63-pr-30768.service -P ActiveState)" = deactivating; do sleep .2; done' diff /tmp/copyme /tmp/copied echo test2 > /tmp/copyme exec {lock}<&- timeout 30 bash -c 'until diff /tmp/copyme /tmp/copied >/dev/null; do sleep .2; done' systemctl log-level info touch /testok Found error in /usr/lib/systemd/tests/testdata/units/testsuite-54.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-54.sh # Sanity checks # # Create a dummy "full" disk (similar to /dev/full) to check out-of-space # scenarios mkdir /tmp/full mount -t tmpfs -o size=1,nr_inodes=1 tmpfs /tmp/full # verb: setup # Run this first, otherwise any encrypted credentials wouldn't be decryptable # as we regenerate the host key rm -fv /var/lib/systemd/credential.secret -- echo foo >"$CRED_DIR/insecure" echo foo | systemd-creds --name="encrypted" encrypt - "$ENC_CRED_DIR/encrypted" echo foo | systemd-creds encrypt - "$ENC_CRED_DIR/encrypted-unnamed" chmod -R 0400 "$CRED_DIR" "$ENC_CRED_DIR" chmod -R 0444 "$CRED_DIR/insecure" mkdir /tmp/empty/ systemd-creds --system systemd-creds --no-pager --help systemd-creds --version systemd-creds has-tpm2 || : -- systemd-creds list --system ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --no-legend ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=pretty | jq ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=short | jq ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds list --json=off ENCRYPTED_CREDENTIALS_DIRECTORY="/tmp/empty/" CREDENTIALS_DIRECTORY="/tmp/empty/" systemd-creds list # verb: cat for cred in secure-or-weak insecure encrypted encrypted-unnamed; do ENCRYPTED_CREDENTIALS_DIRECTORY="$ENC_CRED_DIR" CREDENTIALS_DIRECTORY="$CRED_DIR" systemd-creds cat "$cred" done -- run_with_cred_compare "mycred:68656c6c6f0a776f726c64" "hello\nworld" --transcode=unhex cat mycred run_with_cred_compare 'mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' '{"foo":"bar","baz":[3,4]}\n' --json=short cat mycred systemd-run -p SetCredential='mycred:{ "foo" : "bar", "baz" : [ 3, 4 ] }' --wait --pipe -- systemd-creds --json=pretty cat mycred | jq # verb: encrypt/decrypt echo "According to all known laws of aviation..." >/tmp/cred.orig systemd-creds --with-key=host encrypt /tmp/cred.orig /tmp/cred.enc systemd-creds decrypt /tmp/cred.enc /tmp/cred.dec diff /tmp/cred.orig /tmp/cred.dec rm -f /tmp/cred.{enc,dec} # --pretty cred_name="fo'''o''bar" cred_option="$(systemd-creds --pretty --name="$cred_name" encrypt /tmp/cred.orig -)" mkdir -p /run/systemd/system cat >/run/systemd/system/test-54-pretty-cred.service </tmp/ts54-concat (cat /etc/passwd /etc/shadow && echo -n wuff) | cmp /tmp/ts54-concat rm /tmp/ts54-concat # Test that SetCredential= acts as fallback for LoadCredential= echo piff >/tmp/ts54-fallback [ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "piff" ] rm /tmp/ts54-fallback [ "$(systemd-run -p LoadCredential=paff:/tmp/ts54-fallback -p SetCredential=paff:poff --pipe --wait systemd-creds cat paff)" = "poff" ] if systemd-detect-virt -q -c ; then expected_credential=mynspawncredential expected_value=strangevalue elif [ -d /sys/firmware/qemu_fw_cfg/by_name ]; then -- # Verify that creating a user via sysusers via the kernel cmdline worked grep -q ^credtestuser: /etc/passwd # Verify that writing a file via tmpfiles worked [ "$(cat /tmp/sourcedfromcredential)" = "tmpfilessecret" ] [ "$(cat /etc/motd.d/50-provision.conf)" = "hello" ] [ "$(cat /etc/issue.d/50-provision.conf)" = "welcome" ] else echo "qemu_fw_cfg support missing in kernel. Sniff!" expected_credential="" -- --unit=test-54-immutable-rm.service \ --wait \ rm '${CREDENTIALS_DIRECTORY}/passwd') # Check directory-based loading mkdir -p /tmp/ts54-creds/sub echo -n a >/tmp/ts54-creds/foo echo -n b >/tmp/ts54-creds/bar echo -n c >/tmp/ts54-creds/baz echo -n d >/tmp/ts54-creds/sub/qux systemd-run -p LoadCredential=cred:/tmp/ts54-creds \ -p DynamicUser=1 \ --unit=test-54-dir.service \ --wait \ --pipe \ cat '${CREDENTIALS_DIRECTORY}/cred_foo' \ '${CREDENTIALS_DIRECTORY}/cred_bar' \ '${CREDENTIALS_DIRECTORY}/cred_baz' \ '${CREDENTIALS_DIRECTORY}/cred_sub_qux' >/tmp/ts54-concat cmp /tmp/ts54-concat <(echo -n abcd) rm /tmp/ts54-concat rm -rf /tmp/ts54-creds # Check that globs work as expected mkdir -p /run/credstore echo -n a >/run/credstore/test.creds.first echo -n b >/run/credstore/test.creds.second -- -p DynamicUser=1 \ --wait \ --pipe \ cat '${CREDENTIALS_DIRECTORY}/test.creds.first' \ '${CREDENTIALS_DIRECTORY}/test.creds.second' \ '${CREDENTIALS_DIRECTORY}/test.creds.third' >/tmp/ts54-concat cmp /tmp/ts54-concat <(echo -n abc) # Now test encrypted credentials (only supported when built with OpenSSL though) if systemctl --version | grep -q -- +OPENSSL ; then echo -n $RANDOM >/tmp/test-54-plaintext systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext systemd-run -p LoadCredentialEncrypted=test-54:/tmp/test-54-ciphertext \ --wait \ --pipe \ cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext echo -n $RANDOM >/tmp/test-54-plaintext systemd-creds encrypt --name=test-54 /tmp/test-54-plaintext /tmp/test-54-ciphertext systemd-creds decrypt --name=test-54 /tmp/test-54-ciphertext | cmp /tmp/test-54-plaintext systemd-run -p SetCredentialEncrypted=test-54:"$(cat /tmp/test-54-ciphertext)" \ --wait \ --pipe \ cat '${CREDENTIALS_DIRECTORY}/test-54' | cmp /tmp/test-54-plaintext rm /tmp/test-54-plaintext /tmp/test-54-ciphertext fi # https://github.com/systemd/systemd/issues/27275 systemd-run -p DynamicUser=yes -p 'LoadCredential=os:/etc/os-release' \ -p 'ExecStartPre=true' \ Found error in /usr/lib/systemd/tests/testdata/units/testsuite-50.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-50.sh RemainAfterExit=yes MountAPIVFS=yes PrivateTmp=yes ExecStart=/bin/sh -c ' \\ systemd-notify --ready; \\ while [ ! -f /tmp/img/usr/lib/os-release ] || ! grep -q -F MARKER /tmp/img/usr/lib/os-release; do \\ sleep 0.1; \\ done; \\ mount; \\ mount | grep -F "on /tmp/img type squashfs" | grep -q -F "nosuid"; \\ ' EOF systemctl start testservice-50d.service # Mount twice to exercise mount-beneath (on kernel 6.5+, on older kernels it will just overmount) mkdir -p /tmp/wrong/foo mksquashfs /tmp/wrong/foo /tmp/wrong.raw systemctl mount-image --mkdir testservice-50d.service /tmp/wrong.raw /tmp/img test "$(systemctl show -P SubState testservice-50d.service)" = "running" systemctl mount-image --mkdir testservice-50d.service "${image}.raw" /tmp/img root:nosuid while systemctl show -P SubState testservice-50d.service | grep -q running do sleep 0.1 done -- rm /var/lib/extensions/app-nodistro.raw mkdir -p /run/machines /run/portables /run/extensions touch /run/machines/a.raw /run/portables/b.raw /run/extensions/c.raw systemd-dissect --discover --json=short >/tmp/discover.json grep -q -F '{"name":"a","type":"raw","class":"machine","ro":false,"path":"/run/machines/a.raw"' /tmp/discover.json grep -q -F '{"name":"b","type":"raw","class":"portable","ro":false,"path":"/run/portables/b.raw"' /tmp/discover.json grep -q -F '{"name":"c","type":"raw","class":"sysext","ro":false,"path":"/run/extensions/c.raw"' /tmp/discover.json rm /tmp/discover.json /run/machines/a.raw /run/portables/b.raw /run/extensions/c.raw # Check that the /sbin/mount.ddi helper works T="/tmp/mounthelper.$RANDOM" mount -t ddi "${image}.gpt" "$T" -o ro,X-mount.mkdir,discard umount -R "$T" rmdir "$T" LOOP="$(systemd-dissect --attach --loop-ref=waldo "${image}.raw")" -- (! /etc/testscript) systemd-confext status systemd-confext unmerge rm -rf /run/confexts/ unsquashfs -no-xattrs -d /tmp/img "${image}.raw" systemd-run --unit=test-root-ephemeral \ -p RootDirectory=/tmp/img \ -p RootEphemeral=yes \ -p Type=exec \ bash -c "touch /abc && sleep infinity" test -n "$(ls -A /var/lib/systemd/ephemeral-trees)" systemctl stop test-root-ephemeral # shellcheck disable=SC2016 timeout 10 bash -c 'until test -z "$(ls -A /var/lib/systemd/ephemeral-trees)"; do sleep .5; done' test ! -f /tmp/img/abc systemd-dissect --mtree /tmp/img systemd-dissect --list /tmp/img read -r SHA256SUM1 _ < <(systemd-dissect --copy-from /tmp/img etc/os-release | sha256sum) test "$SHA256SUM1" != "" echo abc > abc systemd-dissect --copy-to /tmp/img abc /abc test -f /tmp/img/abc # Test for dissect tool support with systemd-sysext mkdir -p /run/extensions/ testkit/usr/lib/extension-release.d/ echo "ID=_any" >testkit/usr/lib/extension-release.d/extension-release.testkit echo "ARCHITECTURE=_any" >>testkit/usr/lib/extension-release.d/extension-release.testkit -- rm /var/lib/extensions/app-reload.raw # Test systemd-repart --make-ddi=: if command -v mksquashfs >/dev/null 2>&1; then openssl req -config "$OPENSSL_CONFIG" -subj="/CN=waldo" -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout /tmp/test-50-privkey.key -out /tmp/test-50-cert.crt mkdir -p /tmp/test-50-confext/etc/extension-release.d/ echo "foobar50" > /tmp/test-50-confext/etc/waldo ( grep -e '^\(ID\|VERSION_ID\)=' /etc/os-release ; echo IMAGE_ID=waldo ; echo IMAGE_VERSION=7 ) > /tmp/test-50-confext/etc/extension-release.d/extension-release.waldo mkdir -p /run/confexts SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs systemd-repart -C -s /tmp/test-50-confext --certificate=/tmp/test-50-cert.crt --private-key=/tmp/test-50-privkey.key /run/confexts/waldo.confext.raw rm -rf /tmp/test-50-confext mkdir -p /run/verity.d cp /tmp/test-50-cert.crt /run/verity.d/ systemd-dissect --mtree /run/confexts/waldo.confext.raw systemd-confext refresh read -r X < /etc/waldo -- systemd-confext refresh (! test -f /etc/waldo ) mkdir -p /tmp/test-50-sysext/usr/lib/extension-release.d/ # Make sure the sysext is big enough to not fit in the minimum partition size of repart so we know the # Minimize= logic is working. truncate --size=50M /tmp/test-50-sysext/usr/waldo ( grep -e '^\(ID\|VERSION_ID\)=' /etc/os-release ; echo IMAGE_ID=waldo ; echo IMAGE_VERSION=7 ) > /tmp/test-50-sysext/usr/lib/extension-release.d/extension-release.waldo mkdir -p /run/extensions SYSTEMD_REPART_OVERRIDE_FSTYPE=squashfs systemd-repart -S -s /tmp/test-50-sysext --certificate=/tmp/test-50-cert.crt --private-key=/tmp/test-50-privkey.key /run/extensions/waldo.sysext.raw systemd-dissect --mtree /run/extensions/waldo.sysext.raw systemd-sysext refresh test -f /usr/waldo rm /run/verity.d/test-50-cert.crt /run/extensions/waldo.sysext.raw /tmp/test-50-cert.crt /tmp/test-50-privkey.key systemd-sysext refresh (! test -f /usr/waldo) fi Found error in /usr/lib/systemd/tests/testdata/units/testsuite-46.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-46.sh # filesystems, let's drop these fields before comparing the outputs to # avoid unexpected fails. To see the full outputs of both homectl & # userdbctl (for debugging purposes) drop the fields just before the # comparison. local USERNAME="${1:?}" homectl inspect "$USERNAME" | tee /tmp/a userdbctl user "$USERNAME" | tee /tmp/b # diff uses the grep BREs for pattern matching diff -I '^\s*Disk \(Size\|Free\|Floor\|Ceiling\|Usage\):' /tmp/{a,b} rm /tmp/{a,b} homectl inspect --json=pretty "$USERNAME" } wait_for_state() { -- varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"uid":2000000,"service":"io.systemd.Multiplexer"}' (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"","service":"io.systemd.Multiplexer"}') (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"🐱","service":"io.systemd.Multiplexer"}') (! varlinkctl call /run/systemd/userdb/io.systemd.Multiplexer io.systemd.UserDatabase.GetUserRecord '{"userName":"i-do-not-exist","service":"io.systemd.Multiplexer"}') userdbctl ssh-authorized-keys dropinuser | tee /tmp/authorized-keys grep "ssh-ed25519" /tmp/authorized-keys grep "ecdsa-sha2-nistp256" /tmp/authorized-keys echo "my-top-secret-key 🐱" >/tmp/my-top-secret-key userdbctl ssh-authorized-keys dropinuser --chain /bin/cat /tmp/my-top-secret-key | tee /tmp/authorized-keys grep "ssh-ed25519" /tmp/authorized-keys grep "ecdsa-sha2-nistp256" /tmp/authorized-keys grep "my-top-secret-key 🐱" /tmp/authorized-keys (! userdbctl ssh-authorized-keys 🐱) (! userdbctl ssh-authorized-keys dropin-user --chain) (! userdbctl ssh-authorized-keys dropin-user --chain '') (! SYSTEMD_LOG_LEVEL=debug userdbctl ssh-authorized-keys dropin-user --chain /bin/false) Found error in /usr/lib/systemd/tests/testdata/units/testsuite-44.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-44.sh systemd-analyze log-level debug systemd-run --wait -p LogNamespace=foobar echo "hello world" journalctl --namespace=foobar --sync journalctl -o cat --namespace=foobar >/tmp/hello-world journalctl -o cat >/tmp/no-hello-world grep "^hello world$" /tmp/hello-world (! grep "^hello world$" /tmp/no-hello-world) systemd-analyze log-level info touch /testok Found error in /usr/lib/systemd/tests/testdata/units/testsuite-29.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-29.sh portablectl list | grep -q -F "No images." busctl tree org.freedesktop.portable1 --no-pager | grep -q -F '/org/freedesktop/portable1/image/minimal_5f1' && exit 1 # portablectl also works with directory paths rather than images unsquashfs -dest /tmp/minimal_0 /usr/share/minimal_0.raw unsquashfs -dest /tmp/minimal_1 /usr/share/minimal_1.raw portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/minimal_0 minimal-app0 systemctl is-active minimal-app0.service systemctl is-active minimal-app0-foo.service systemctl is-active minimal-app0-bar.service && exit 1 portablectl "${ARGS[@]}" reattach --now --enable --runtime /tmp/minimal_1 minimal-app0 systemctl is-active minimal-app0.service systemctl is-active minimal-app0-bar.service systemctl is-active minimal-app0-foo.service && exit 1 portablectl list | grep -q -F "minimal_1" busctl tree org.freedesktop.portable1 --no-pager | grep -q -F '/org/freedesktop/portable1/image/minimal_5f1' portablectl detach --now --enable --runtime /tmp/minimal_1 minimal-app0 portablectl list | grep -q -F "No images." busctl tree org.freedesktop.portable1 --no-pager | grep -q -F '/org/freedesktop/portable1/image/minimal_5f1' && exit 1 portablectl "${ARGS[@]}" attach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_0.raw app0 -- portablectl detach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_1.raw app0 # Ensure versioned images are accepted without needing to use --force to override the extension-release # matching cp /usr/share/app0.raw /tmp/app0_1.0.raw portablectl "${ARGS[@]}" attach --now --runtime --extension /tmp/app0_1.0.raw /usr/share/minimal_0.raw app0 systemctl is-active app0.service status="$(portablectl is-attached --extension app0_1 minimal_0)" [[ "${status}" == "running-runtime" ]] portablectl detach --now --runtime --extension /tmp/app0_1.0.raw /usr/share/minimal_1.raw app0 rm -f /tmp/app0_1.0.raw portablectl "${ARGS[@]}" attach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1 systemctl is-active app1.service status="$(portablectl is-attached --extension app1 minimal_0)" [[ "${status}" == "running-runtime" ]] # Ensure that adding or removing a version to the image doesn't break reattaching cp /usr/share/app1.raw /tmp/app1_2.raw portablectl "${ARGS[@]}" reattach --now --runtime --extension /tmp/app1_2.raw /usr/share/minimal_1.raw app1 systemctl is-active app1.service status="$(portablectl is-attached --extension app1_2 minimal_1)" [[ "${status}" == "running-runtime" ]] -- # after the service is attached before the file appears. grep -q -F bar "${STATE_DIRECTORY}/app0/foo" grep -q -F baz "${STATE_DIRECTORY}/app1/foo" # Ensure that we can override the check on extension-release.NAME cp /usr/share/app0.raw /tmp/app10.raw portablectl "${ARGS[@]}" attach --force --now --runtime --extension /tmp/app10.raw /usr/share/minimal_0.raw app0 systemctl is-active app0.service status="$(portablectl is-attached --extension /tmp/app10.raw /usr/share/minimal_0.raw)" [[ "${status}" == "running-runtime" ]] portablectl inspect --force --cat --extension /tmp/app10.raw /usr/share/minimal_0.raw app0 | grep -q -F "Extension Release: /tmp/app10.raw" # Ensure that we can detach even when an image has been deleted already (stop the unit manually as # portablectl won't find it) rm -f /tmp/app10.raw systemctl stop app0.service portablectl detach --force --runtime --extension /tmp/app10.raw /usr/share/minimal_0.raw app0 # portablectl also accepts confexts portablectl "${ARGS[@]}" attach --now --runtime --extension /usr/share/app0.raw --extension /usr/share/conf0.raw /usr/share/minimal_0.raw app0 systemctl is-active app0.service -- portablectl detach --now --runtime --extension /usr/share/app0.raw --extension /usr/share/conf0.raw /usr/share/minimal_0.raw app0 # portablectl also works with directory paths rather than images mkdir /tmp/rootdir /tmp/app0 /tmp/app1 /tmp/overlay /tmp/os-release-fix /tmp/os-release-fix/etc mount /usr/share/app0.raw /tmp/app0 mount /usr/share/app1.raw /tmp/app1 mount /usr/share/minimal_0.raw /tmp/rootdir # Fix up os-release to drop the valid PORTABLE_SERVICES field (because we are # bypassing the sysext logic in portabled here it will otherwise not see the # extensions additional valid prefix) grep -v "^PORTABLE_PREFIXES=" /tmp/rootdir/etc/os-release >/tmp/os-release-fix/etc/os-release mount -t overlay overlay -o lowerdir=/tmp/os-release-fix:/tmp/app1:/tmp/rootdir /tmp/overlay grep . /tmp/overlay/usr/lib/extension-release.d/* grep . /tmp/overlay/etc/os-release portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/overlay app1 systemctl is-active app1.service portablectl detach --now --runtime overlay app1 -- [Unit] Description=App 1 EOF systemctl daemon-reload portablectl "${ARGS[@]}" attach --force --copy=symlink --now --runtime /tmp/overlay app1 systemctl is-active app1.service portablectl detach --now --runtime overlay app1 umount /tmp/overlay portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime --extension /tmp/app0 --extension /tmp/app1 /tmp/rootdir app0 app1 systemctl is-active app0.service systemctl is-active app1.service portablectl inspect --cat --extension app0 --extension app1 rootdir app0 app1 | grep -q -f /tmp/rootdir/usr/lib/os-release portablectl inspect --cat --extension app0 --extension app1 rootdir app0 app1 | grep -q -f /tmp/app0/usr/lib/extension-release.d/extension-release.app0 portablectl inspect --cat --extension app0 --extension app1 rootdir app0 app1 | grep -q -f /tmp/app1/usr/lib/extension-release.d/extension-release.app2 portablectl inspect --cat --extension app0 --extension app1 rootdir app0 app1 | grep -q -f /tmp/app1/usr/lib/systemd/system/app1.service portablectl inspect --cat --extension app0 --extension app1 rootdir app0 app1 | grep -q -f /tmp/app0/usr/lib/systemd/system/app0.service grep -q -F "LogExtraFields=PORTABLE=app0" /run/systemd/system.attached/app0.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_ROOT=rootdir" /run/systemd/system.attached/app0.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_EXTENSION=app0" /run/systemd/system.attached/app0.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_EXTENSION_NAME_AND_VERSION=app" /run/systemd/system.attached/app0.service.d/20-portable.conf -- grep -q -F "LogExtraFields=PORTABLE_EXTENSION=app0" /run/systemd/system.attached/app1.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_EXTENSION_NAME_AND_VERSION=app" /run/systemd/system.attached/app1.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_EXTENSION=app1" /run/systemd/system.attached/app1.service.d/20-portable.conf grep -q -F "LogExtraFields=PORTABLE_EXTENSION_NAME_AND_VERSION=app_1" /run/systemd/system.attached/app1.service.d/20-portable.conf portablectl detach --now --runtime --extension /tmp/app0 --extension /tmp/app1 /tmp/rootdir app0 app1 # Attempt to disable the app unit during detaching. Requires --copy=symlink to reproduce. # Provides coverage for https://github.com/systemd/systemd/issues/23481 portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/rootdir minimal-app0 portablectl detach --now --runtime --enable /tmp/rootdir minimal-app0 # attach and detach again to check if all drop-in configs are removed even if the main unit files are removed portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/rootdir minimal-app0 portablectl detach --now --runtime --enable /tmp/rootdir minimal-app0 # The wrong file should be ignored, given the right one has the xattr set trap 'rm -rf /var/cache/wrongext' EXIT mkdir -p /var/cache/wrongext/usr/lib/extension-release.d /var/cache/wrongext/usr/lib/systemd/system/ echo "[Service]" > /var/cache/wrongext/usr/lib/systemd/system/app0.service touch /var/cache/wrongext/usr/lib/extension-release.d/extension-release.wrongext_somethingwrong.txt cp /tmp/rootdir/usr/lib/os-release /var/cache/wrongext/usr/lib/extension-release.d/extension-release.app0 setfattr -n user.extension-release.strict -v "false" /var/cache/wrongext/usr/lib/extension-release.d/extension-release.app0 portablectl "${ARGS[@]}" attach --runtime --extension /var/cache/wrongext /tmp/rootdir app0 status="$(portablectl is-attached --extension wrongext rootdir)" [[ "${status}" == "attached-runtime" ]] portablectl detach --runtime --extension /var/cache/wrongext /tmp/rootdir app0 umount /tmp/rootdir umount /tmp/app0 umount /tmp/app1 # Lack of ID field in os-release should be rejected, but it caused a crash in the past instead mkdir -p /tmp/emptyroot/usr/lib mkdir -p /tmp/emptyext/usr/lib/extension-release.d touch /tmp/emptyroot/usr/lib/os-release touch /tmp/emptyext/usr/lib/extension-release.d/extension-release.emptyext # Remote peer disconnected -> portabled crashed res="$(! portablectl attach --extension /tmp/emptyext /tmp/emptyroot 2> >(grep "Remote peer disconnected"))" test -z "${res}" touch /testok Found error in /usr/lib/systemd/tests/testdata/units/testsuite-24.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-24.sh at_exit() { set +e mountpoint -q /proc/cmdline && umount /proc/cmdline rm -f /etc/crypttab [[ -e /tmp/crypttab.bak ]] && cp -fv /tmp/crypttab.bak /etc/crypttab [[ -n "${STORE_LOOP:-}" ]] && losetup -d "$STORE_LOOP" [[ -n "${WORKDIR:-}" ]] && rm -rf "$WORKDIR" systemctl daemon-reload } -- cp "$IMAGE_DETACHED_KEYFILE2" /mnt/keyfile umount /mnt udevadm settle --timeout=30 # Prepare our test crypttab [[ -e /etc/crypttab ]] && cp -fv /etc/crypttab /tmp/crypttab.bak cat >/etc/crypttab </tmp/cmdline.tmp mount --bind /tmp/cmdline.tmp /proc/cmdline # Run the systemd-cryptsetup-generator once explicitly, to collect coverage, # as during daemon-reload we run generators in a sandbox mkdir -p /tmp/systemd-cryptsetup-generator.out /usr/lib/systemd/system-generators/systemd-cryptsetup-generator /tmp/systemd-cryptsetup-generator.out/ systemctl daemon-reload systemctl list-unit-files "systemd-cryptsetup@*" cryptsetup_start_and_check empty_key test -e "$IMAGE_EMPTY_KEYFILE_ERASE" Found error in /usr/lib/systemd/tests/testdata/units/testsuite-23.ExecStopPost.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-23.ExecStopPost.sh (! systemd-run --unit=exec2.service --wait -p StandardOutput=tty -p StandardError=tty -p Type=exec \ -p ExecStopPost='/bin/touch /run/exec2' sh -c 'sleep 1; false') test -f /run/exec2 cat >/tmp/forking1.sh </tmp/forking2.sh </tmp/notify1.sh </tmp/testsuite-23.counter if [ "$counter" -eq 5 ] ; then systemctl kill --kill-whom=main -sUSR1 testsuite-23.service fi Found error in /usr/lib/systemd/tests/testdata/units/testsuite-22.03.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-22.03.sh # # Basic tests for types creating/writing files set -eux set -o pipefail rm -fr /tmp/{f,F,w} mkdir /tmp/{f,F,w} touch /tmp/file-owned-by-root # # 'f' # systemd-tmpfiles --create - </tmp/F/truncated echo "This should be truncated" >/tmp/F/truncated-with-content systemd-tmpfiles --create - </tmp/F/rw-fs/foo (! systemd-tmpfiles --create -) </tmp/F/rw-fs/foo (! systemd-tmpfiles --create -) < fails. (! systemd-tmpfiles --create -) < /tmp/C/3/f1 systemd-tmpfiles --create - </tmp/test19-exit-cgroup.sh < sleep sleep infinity & -- (sleep 1; \$1) & # process tree: systemd -> bash -> sleep sleep infinity EOF chmod +x /tmp/test19-exit-cgroup.sh # service should be stopped cleanly systemd-run --wait \ --unit=one \ --property="Type=notify" \ --property="ExitType=cgroup" \ /tmp/test19-exit-cgroup.sh 'systemctl stop one' # same thing with a truthy exec condition systemd-run --wait \ --unit=two \ --property="Type=notify" \ --property="ExitType=cgroup" \ --property="ExecCondition=true" \ /tmp/test19-exit-cgroup.sh 'systemctl stop two' # false exec condition: systemd-run should exit immediately with status code: 1 (! systemd-run --wait \ --unit=three \ --property="Type=notify" \ --property="ExitType=cgroup" \ --property="ExecCondition=false" \ /tmp/test19-exit-cgroup.sh) # service should exit uncleanly (main process exits with SIGKILL) (! systemd-run --wait \ --unit=four \ --property="Type=notify" \ --property="ExitType=cgroup" \ /tmp/test19-exit-cgroup.sh 'systemctl kill --signal 9 four') # Multiple level process tree, parent process exits quickly cat >/tmp/test19-exit-cgroup-parentless.sh < sleep sleep infinity & -- systemd-notify --ready # Run the stop/kill command after this bash process exits (sleep 1; \$1) & EOF chmod +x /tmp/test19-exit-cgroup-parentless.sh # service should be stopped cleanly systemd-run --wait \ --unit=five \ --property="Type=notify" \ --property="ExitType=cgroup" \ /tmp/test19-exit-cgroup-parentless.sh 'systemctl stop five' # service should still exit cleanly despite SIGKILL (the main process already exited cleanly) systemd-run --wait \ --unit=six \ --property="Type=notify" \ --property="ExitType=cgroup" \ /tmp/test19-exit-cgroup-parentless.sh 'systemctl kill --signal 9 six' systemd-analyze log-level info Found error in /usr/lib/systemd/tests/testdata/units/testsuite-15.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-15.sh testcase_symlink_dropin_directory() { # For issue #21920. echo "Testing symlink drop-in directory..." create_services test15-a rmdir /{etc,run,usr/lib}/systemd/system/test15-a.service.d mkdir -p /tmp/testsuite-15-test15-a-dropin-directory ln -s /tmp/testsuite-15-test15-a-dropin-directory /etc/systemd/system/test15-a.service.d cat >/tmp/testsuite-15-test15-a-dropin-directory/override.conf </tmp/cred.path systemd-nspawn --directory="$root" \ --load-credential=cred.path:/tmp/cred.path \ --set-credential="cred.set:hello world" \ bash -xec '[[ "$(/tmp/bind systemd-nspawn --register=no \ --directory="$root" \ --bind=/tmp/bind \ bash -c 'test -e /tmp/bind' rm -fr "$root" /tmp/bind } testcase_norbind() { # https://github.com/systemd/systemd/issues/13170 local root root="$(mktemp -d /var/lib/machines/testsuite-13.norbind-path.XXX)" mkdir -p /tmp/binddir/subdir echo -n "outer" >/tmp/binddir/subdir/file mount -t tmpfs tmpfs /tmp/binddir/subdir echo -n "inner" >/tmp/binddir/subdir/file create_dummy_container "$root" systemd-nspawn --register=no \ --directory="$root" \ --bind=/tmp/binddir:/mnt:norbind \ bash -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; exit 1; fi' umount /tmp/binddir/subdir rm -fr "$root" /tmp/binddir/ } rootidmap_cleanup() { local dir="${1:?}" -- local root cmd permissions local owner=1000 root="$(mktemp -d /var/lib/machines/testsuite-13.rootidmap-path.XXX)" # Create ext4 image, as ext4 supports idmapped-mounts. mkdir -p /tmp/rootidmap/bind dd if=/dev/zero of=/tmp/rootidmap/ext4.img bs=4k count=2048 mkfs.ext4 /tmp/rootidmap/ext4.img mount /tmp/rootidmap/ext4.img /tmp/rootidmap/bind trap "rootidmap_cleanup /tmp/rootidmap/" RETURN touch /tmp/rootidmap/bind/file chown -R "$owner:$owner" /tmp/rootidmap/bind create_dummy_container "$root" cmd='PERMISSIONS=$(stat -c "%u:%g" /mnt/file); if [[ $PERMISSIONS != "0:0" ]]; then echo "*** wrong permissions: $PERMISSIONS"; return 1; fi; touch /mnt/other_file' if ! SYSTEMD_LOG_TARGET=console \ systemd-nspawn --register=no \ --directory="$root" \ --bind=/tmp/rootidmap/bind:/mnt:rootidmap \ bash -c "$cmd" |& tee nspawn.out; then if grep -q "Failed to map ids for bind mount.*: Function not implemented" nspawn.out; then echo "idmapped mounts are not supported, skipping the test..." return 0 fi return 1 fi permissions=$(stat -c "%u:%g" /tmp/rootidmap/bind/other_file) if [[ $permissions != "$owner:$owner" ]]; then echo "*** wrong permissions: $permissions" [[ "$IS_USERNS_SUPPORTED" == "yes" ]] && return 1 fi } -- create_dummy_container "$root" entrypoint="$root/entrypoint.sh" cat >"$entrypoint" <<\EOF #!/usr/bin/bash -ex . /tmp/os-release [[ -n "${ID:-}" && "$ID" != "$container_host_id" ]] && exit 1 [[ -n "${VERSION_ID:-}" && "$VERSION_ID" != "$container_host_version_id" ]] && exit 1 [[ -n "${BUILD_ID:-}" && "$BUILD_ID" != "$container_host_build_id" ]] && exit 1 [[ -n "${VARIANT_ID:-}" && "$VARIANT_ID" != "$container_host_variant_id" ]] && exit 1 -- echo MARKER=1 >>/etc/os-release fi systemd-nspawn --register=no \ --directory="$root" \ --bind="$os_release_source:/tmp/os-release" \ "${entrypoint##"$root"}" if grep -q MARKER /etc/os-release; then ln -svrf /usr/lib/os-release /etc/os-release fi -- rm -fr "$root" } testcase_machinectl_bind() { local service_path service_name root container_name ec local cmd='for i in $(seq 1 20); do if test -f /tmp/marker; then exit 0; fi; sleep .5; done; exit 1;' root="$(mktemp -d /var/lib/machines/testsuite-13.machinectl-bind.XXX)" create_dummy_container "$root" container_name="$(basename "$root")" -- ExecStart=systemd-nspawn --directory="$root" --notify-ready=no /usr/bin/bash -xec "$cmd" EOF systemctl daemon-reload systemctl start "$service_name" touch /tmp/marker machinectl bind --mkdir "$container_name" /tmp/marker timeout 10 bash -c "while [[ '\$(systemctl show -P SubState $service_name)' == running ]]; do sleep .2; done" ec="$(systemctl show -P ExecMainStatus "$service_name")" systemctl stop "$service_name" -- mkdir -p /run/systemd/nspawn/ rm -f "/etc/systemd/nspawn/$container_name.nspawn" cat >"/run/systemd/nspawn/$container_name.nspawn" <"/var/lib/machines/$NSPAWN_FRAGMENT" </tmp/fragment.nspawn </tmp/test-mainpid.sh <<\EOF #!/usr/bin/env bash set -eux set -o pipefail -- sleep infinity & disown echo $MAINPID >/run/mainpidsh/pid EOF chmod +x /tmp/test-mainpid.sh systemd-run --unit=test-mainpidsh.service \ -p StandardOutput=tty \ -p StandardError=tty \ -p Type=forking \ -p RuntimeDirectory=mainpidsh \ -p PIDFile=/run/mainpidsh/pid \ /tmp/test-mainpid.sh test "$(systemctl show -P MainPID test-mainpidsh.service)" -eq "$(cat /run/mainpidsh/pid)" cat >/tmp/test-mainpid2.sh <<\EOF #!/usr/bin/env bash set -eux set -o pipefail -- disown echo $MAINPID >/run/mainpidsh2/pid chown 1001:1001 /run/mainpidsh2/pid EOF chmod +x /tmp/test-mainpid2.sh systemd-run --unit=test-mainpidsh2.service \ -p StandardOutput=tty \ -p StandardError=tty \ -p Type=forking \ -p RuntimeDirectory=mainpidsh2 \ -p PIDFile=/run/mainpidsh2/pid \ /tmp/test-mainpid2.sh test "$(systemctl show -P MainPID test-mainpidsh2.service)" -eq "$(cat /run/mainpidsh2/pid)" cat >/dev/shm/test-mainpid3.sh </tmp/output [[ $(wc -l /dev/null # -b always behaves like -b0 journalctl -q -b-1 -b0 | head -1 >/tmp/expected journalctl -q -b-1 -b | head -1 >/tmp/output diff /tmp/expected /tmp/output # ... even when another option follows (both of these should fail due to -m) { journalctl -ball -b0 -m 2>&1 || :; } | head -1 >/tmp/expected { journalctl -ball -b -m 2>&1 || :; } | head -1 >/tmp/output diff /tmp/expected /tmp/output # https://github.com/systemd/systemd/issues/13708 ID=$(systemd-id128 new) systemd-cat -t "$ID" bash -c 'echo parent; (echo child) & wait' & PID=$! wait $PID journalctl --sync # We can drop this grep when https://github.com/systemd/systemd/issues/13937 # has a fix. journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/tmp/output [[ $(wc -l /tmp/expected systemd-cat -t "$ID" /bin/sh -c 'env echo -n "This will";echo;env echo -n "usually fail";echo;env echo -n "and be truncated";echo;' journalctl --sync journalctl -b -o cat -t "$ID" >/tmp/output diff /tmp/expected /tmp/output [[ $(journalctl -b -o cat -t "$ID" --output-fields=_TRANSPORT | grep -Pc "^stdout$") -eq 3 ]] [[ $(journalctl -b -o cat -t "$ID" --output-fields=_LINE_BREAK | grep -Pc "^pid-change$") -eq 3 ]] [[ $(journalctl -b -o cat -t "$ID" --output-fields=_PID | sort -u | grep -c "^.*$") -eq 3 ]] [[ $(journalctl -b -o cat -t "$ID" --output-fields=MESSAGE | grep -Pc "^(This will|usually fail|and be truncated)$") -eq 3 ]] -- systemctl start forever-print-hola sleep 3 systemctl restart systemd-journald sleep 3 systemctl stop forever-print-hola [[ ! -f "/tmp/i-lose-my-logs" ]] # https://github.com/systemd/systemd/issues/4408 rm -f /tmp/i-lose-my-logs systemctl start forever-print-hola sleep 3 systemctl kill --signal=SIGKILL systemd-journald sleep 3 [[ ! -f "/tmp/i-lose-my-logs" ]] systemctl stop forever-print-hola set +o pipefail # https://github.com/systemd/systemd/issues/15528 journalctl --follow --file=/var/log/journal/*/* | head -n1 | grep . # https://github.com/systemd/systemd/issues/24565 journalctl --follow --merge | head -n1 | grep . set -o pipefail # https://github.com/systemd/systemd/issues/26746 rm -f /tmp/issue-26746-log /tmp/issue-26746-cursor ID="$(systemd-id128 new)" journalctl -t "$ID" --follow --cursor-file=/tmp/issue-26746-cursor | tee /tmp/issue-26746-log & systemd-cat -t "$ID" /bin/sh -c 'echo hogehoge' # shellcheck disable=SC2016 timeout 10 bash -c 'until [[ -f /tmp/issue-26746-log && "$(cat /tmp/issue-26746-log)" =~ hogehoge ]]; do sleep .5; done' pkill -TERM journalctl timeout 10 bash -c 'until test -f /tmp/issue-26746-cursor; do sleep .5; done' CURSOR_FROM_FILE="$(cat /tmp/issue-26746-cursor)" CURSOR_FROM_JOURNAL="$(journalctl -t "$ID" --output=export MESSAGE=hogehoge | sed -n -e '/__CURSOR=/ { s/__CURSOR=//; p }')" test "$CURSOR_FROM_FILE" = "$CURSOR_FROM_JOURNAL" # Check that the seqnum field at least superficially works systemd-cat echo "ya" -- while read -r file; do filename="${file##*/}" unzstd "$file" -o "$JOURNAL_DIR/${filename%*.zst}" done < <(find /test-journals/no-rtc -name "*.zst") journalctl --directory="$JOURNAL_DIR" --list-boots --output=json >/tmp/lb1 diff -u /tmp/lb1 - <<'EOF' [{"index":-3,"boot_id":"5ea5fc4f82a14186b5332a788ef9435e","first_entry":1666569600994371,"last_entry":1666584266223608},{"index":-2,"boot_id":"bea6864f21ad4c9594c04a99d89948b0","first_entry":1666569601005945,"last_entry":1666584347230411},{"index":-1,"boot_id":"4c708e1fd0744336be16f3931aa861fb","first_entry":1666569601017222,"last_entry":1666584354649355},{"index":0,"boot_id":"35e8501129134edd9df5267c49f744a4","first_entry":1666569601009823,"last_entry":1666584438086856}] EOF rm -rf "$JOURNAL_DIR" /tmp/lb1 # v255-only: skip the following test case, as it suffers from systemd/systemd#30886 exit 0 # Check that using --after-cursor/--cursor-file= together with journal filters doesn't Found error in /usr/lib/systemd/tests/testdata/units/testsuite-04.journal-remote.sh: $ grep -A5 -B5 /tmp/ /usr/lib/systemd/tests/testdata/units/testsuite-04.journal-remote.sh # Generate a self-signed certificate for systemd-journal-remote # # Note: older OpenSSL requires a config file with some extra options, unfortunately # Note2: /run here is used on purpose, since the systemd-journal-remote service uses PrivateTmp=yes mkdir -p /run/systemd/journal-remote-tls cat >/tmp/openssl.conf </tmp/openssl.conf < /tmp/syncfifo1 } export SYSTEMD_LOG_LEVEL=debug echo "toplevel PID: $BASHPID"; udev-255.18-alt1.x86_64 sisyphus_check-check-dirlist warn sisyphus_check --check-dirlist failed: package contains a directory /etc/udev/rules.d that exclusively belongs to package udev-rules;