]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: add test coverage for homed+fscrypt
authorLuca Boccassi <luca.boccassi@gmail.com>
Fri, 24 Apr 2026 18:16:36 +0000 (19:16 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 19 May 2026 11:36:44 +0000 (12:36 +0100)
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
test/units/TEST-46-HOMED.sh

index 5afa42d73968e602d07145311501fa4e627a2f38..0a6f02cc81b0a381bfe91d2276258f60a4b0b70a 100755 (executable)
@@ -984,4 +984,86 @@ testcase_match() {
     homectl remove matchtest
 }
 
+testcase_fscrypt() {
+    if ! command -v mkfs.ext4 >/dev/null; then
+        echo "e2fsprogs not installed, skipping fscrypt test."
+        return 0
+    fi
+
+    local IMAGE MNT
+    IMAGE="$(mktemp /tmp/fscrypt.XXXXXX.img)"
+    MNT="$(mktemp -d /tmp/fscrypt-mnt.XXXXXX)"
+    # shellcheck disable=SC2064
+    trap "homectl deactivate fscrypttest 2>/dev/null || true; homectl remove fscrypttest 2>/dev/null || true; umount '$MNT' 2>/dev/null || true; rm -rf '$MNT' '$IMAGE'" RETURN ERR
+
+    truncate -s 64M "$IMAGE"
+    if ! mkfs.ext4 -q -O encrypt "$IMAGE"; then
+        echo "mkfs.ext4 -O encrypt unsupported, skipping fscrypt test."
+        return 0
+    fi
+
+    if ! mount -o loop "$IMAGE" "$MNT"; then
+        echo "Cannot loop-mount fscrypt-capable ext4, skipping fscrypt test."
+        return 0
+    fi
+
+    if ! NEWPASSWORD=fsfsfs1234 homectl create fscrypttest \
+            --storage=fscrypt \
+            --image-path="$MNT/fscrypttest" \
+            --rate-limit-interval=1s --rate-limit-burst=1000; then
+        echo "homed fscrypt backend not usable on this kernel, skipping."
+        return 0
+    fi
+
+    inspect fscrypttest
+
+    (! PASSWORD=wrongpass timeout 10s homectl authenticate fscrypttest </dev/null)
+
+    PASSWORD=fsfsfs1234 homectl authenticate fscrypttest
+    PASSWORD=fsfsfs1234 homectl activate fscrypttest
+    inspect fscrypttest
+
+    fscrypt_run0() {
+        run0 --property=SetCredential=pam.authtok.systemd-run0:"$1" -u fscrypttest \
+            bash -c 'keyctl link @u @s; eval "$1"' -- "$2"
+    }
+
+    fscrypt_run0 fsfsfs1234 'echo "hello fscrypt" > /home/fscrypttest/file1'
+    [[ "$(fscrypt_run0 fsfsfs1234 'cat /home/fscrypttest/file1')" == "hello fscrypt" ]]
+    fscrypt_run0 fsfsfs1234 'mkdir /home/fscrypttest/subdir'
+    fscrypt_run0 fsfsfs1234 'dd if=/dev/urandom of=/home/fscrypttest/subdir/blob bs=4096 count=8 status=none'
+    fscrypt_run0 fsfsfs1234 'cp /home/fscrypttest/subdir/blob /home/fscrypttest/subdir/blob.copy && cmp /home/fscrypttest/subdir/blob /home/fscrypttest/subdir/blob.copy'
+    fscrypt_run0 fsfsfs1234 'echo appended >> /home/fscrypttest/file1 && grep -F appended /home/fscrypttest/file1 >/dev/null'
+    fscrypt_run0 fsfsfs1234 'rm /home/fscrypttest/subdir/blob.copy && test ! -e /home/fscrypttest/subdir/blob.copy'
+
+    systemctl stop user@"$(id -u fscrypttest)".service 2>/dev/null || true
+    homectl deactivate fscrypttest 2>/dev/null || true
+    wait_for_state fscrypttest inactive
+
+    # After deactivation the fscrypt-encrypted directory is locked, so cleartext file names should not be visible
+    [[ ! -e "$MNT/fscrypttest/file1" ]]
+
+    PASSWORD=fsfsfs1234 homectl activate fscrypttest
+    [[ "$(fscrypt_run0 fsfsfs1234 'head -n1 /home/fscrypttest/file1')" == "hello fscrypt" ]]
+    systemctl stop user@"$(id -u fscrypttest)".service 2>/dev/null || true
+    homectl deactivate fscrypttest 2>/dev/null || true
+    wait_for_state fscrypttest inactive
+
+    homectl update fscrypttest --real-name="Fscrypt Test" --offline
+    inspect fscrypttest | grep "Real Name: Fscrypt Test" >/dev/null
+
+    PASSWORD=fsfsfs1234 NEWPASSWORD=newfsfs5678 homectl passwd fscrypttest
+    PASSWORD=newfsfs5678 homectl authenticate fscrypttest
+    (! PASSWORD=fsfsfs1234 timeout 10s homectl authenticate fscrypttest </dev/null)
+
+    PASSWORD=newfsfs5678 homectl activate fscrypttest
+    [[ "$(fscrypt_run0 newfsfs5678 'head -n1 /home/fscrypttest/file1')" == "hello fscrypt" ]]
+    fscrypt_run0 newfsfs5678 'rm -r /home/fscrypttest/subdir /home/fscrypttest/file1'
+    systemctl stop user@"$(id -u fscrypttest)".service 2>/dev/null || true
+    homectl deactivate fscrypttest 2>/dev/null || true
+    wait_for_state fscrypttest inactive
+
+    homectl remove fscrypttest
+}
+
 run_testcases