]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysupdate: Use sector size for partition size calculations
authorMichael A Cassaniti <michael@cassaniti.id.au>
Fri, 11 Aug 2023 12:05:45 +0000 (22:05 +1000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 15 Aug 2023 07:17:12 +0000 (09:17 +0200)
src/sysupdate/sysupdate-partition.c
test/units/testsuite-72.sh

index fa4453d66517b5fe87e9d4c056cbc6d925d57a59..6f8e07227799a19e735ae01672b57cd7127ff1a7 100644 (file)
@@ -28,6 +28,7 @@ int read_partition_info(
         const char *label;
         struct fdisk_partition *p;
         uint64_t start, size, flags;
+        unsigned long ssz;
         sd_id128_t ptid, id;
         GptPartitionType type;
         size_t partno;
@@ -54,12 +55,13 @@ int read_partition_info(
         partno = fdisk_partition_get_partno(p);
 
         start = fdisk_partition_get_start(p);
-        assert(start <= UINT64_MAX / 512U);
-        start *= 512U;
+        ssz = fdisk_get_sector_size(c);
+        assert(start <= UINT64_MAX / ssz);
+        start *= ssz;
 
         size = fdisk_partition_get_size(p);
-        assert(size <= UINT64_MAX / 512U);
-        size *= 512U;
+        assert(size <= UINT64_MAX / ssz);
+        size *= ssz;
 
         label = fdisk_partition_get_name(p);
         if (!label)
index 36c9712a0950f63f73e55d53671ebc29f682e28a..e428e902b1a2deeef7707b9e30f36e5c0e8bd7e6 100755 (executable)
@@ -6,22 +6,113 @@ set -eux
 set -o pipefail
 
 SYSUPDATE=/lib/systemd/systemd-sysupdate
+SECTOR_SIZES="512 4096"
+BACKING_FILE=/var/tmp/72-joined.raw
+export SYSTEMD_ESP_PATH=/var/tmp/72-esp
+export SYSTEMD_XBOOTLDR_PATH=/var/tmp/72-xbootldr
+export SYSTEMD_PAGER=cat
+export SYSTEMD_LOG_LEVEL=debug
 
 if ! test -x "$SYSUPDATE"; then
     echo "no systemd-sysupdate" >/skipped
     exit 0
 fi
 
-export SYSTEMD_PAGER=cat
-export SYSTEMD_LOG_LEVEL=debug
+# Loopback devices may not be supported. They are used because sfdisk cannot
+# change the sector size of a file, and we want to test both 512 and 4096 byte
+# sectors. If loopback devices are not supported, we can only test one sector
+# size, and the underlying device is likely to have a sector size of 512 bytes.
+if ! losetup --find >/dev/null 2>&1; then
+    echo "No loopback device support"
+    SECTOR_SIZES="512"
+fi
 
-rm -f /var/tmp/72-joined.raw
-truncate -s 10M /var/tmp/72-joined.raw
+trap cleanup ERR
+cleanup() {
+    set +o pipefail
+    blockdev="$( losetup --list --output NAME,BACK-FILE | grep $BACKING_FILE | cut -d' ' -f1)"
+    [ -n "$blockdev" ] && losetup --detach "$blockdev"
+    rm -f "$BACKING_FILE"
+    rm -rf /var/tmp/72-{dirs,defs,source,xbootldr,esp}
+    rm -f /testok
+}
+
+new_version() {
+    # Inputs:
+    # $1: sector size
+    # $2: version
+
+    # Create a pair of random partition payloads, and compress one
+    dd if=/dev/urandom of="/var/tmp/72-source/part1-$2.raw" bs="$1" count=2048
+    dd if=/dev/urandom of="/var/tmp/72-source/part2-$2.raw" bs="$1" count=2048
+    gzip -k -f "/var/tmp/72-source/part2-$2.raw"
+
+    # Create a random "UKI" payload
+    echo $RANDOM >"/var/tmp/72-source/uki-$2.efi"
+
+    # Create tarball of a directory
+    mkdir -p "/var/tmp/72-source/dir-$2"
+    echo $RANDOM >"/var/tmp/72-source/dir-$2/foo.txt"
+    echo $RANDOM >"/var/tmp/72-source/dir-$2/bar.txt"
+    tar --numeric-owner -C "/var/tmp/72-source/dir-$2/" -czf "/var/tmp/72-source/dir-$2.tar.gz" .
+
+    ( cd /var/tmp/72-source/ && sha256sum uki* part* dir-*.tar.gz >SHA256SUMS )
+}
 
-sfdisk /var/tmp/72-joined.raw <<EOF
+update_now() {
+    # Update to newest version. First there should be an update ready, then we
+    # do the update, and then there should not be any ready anymore
+
+    "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no check-new
+    "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no update
+    ( ! "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no check-new )
+}
+
+verify_version() {
+    # Inputs:
+    # $1: block device
+    # $2: sector size
+    # $3: version
+    # $4: partiton number of part1
+    # $5: partiton number of part2
+
+    gpt_reserved_sectors=$(( 1024 * 1024 / $2 ))
+    part1_offset=$(( ( $4 - 1 ) * 2048 + gpt_reserved_sectors ))
+    part2_offset=$(( ( $5 - 1 ) * 2048 + gpt_reserved_sectors ))
+
+    # Check the partitions
+    dd if="$1" bs="$2" skip="$part1_offset" count=2048 | cmp "/var/tmp/72-source/part1-$3.raw"
+    dd if="$1" bs="$2" skip="$part2_offset" count=2048 | cmp "/var/tmp/72-source/part2-$3.raw"
+
+    # Check the UKI
+    cmp "/var/tmp/72-source/uki-$3.efi" "/var/tmp/72-xbootldr/EFI/Linux/uki_$3+3-0.efi"
+    test -z "$(ls -A /var/tmp/72-esp/EFI/Linux)"
+
+    # Check the directories
+    cmp "/var/tmp/72-source/dir-$3/foo.txt" /var/tmp/72-dirs/current/foo.txt
+    cmp "/var/tmp/72-source/dir-$3/bar.txt" /var/tmp/72-dirs/current/bar.txt
+}
+
+for sector_size in $SECTOR_SIZES ; do
+    # Disk size of:
+    # - 1MB for GPT
+    # - 4 partitions of 2048 sectors each
+    # - 1MB for backup GPT
+    disk_size=$(( sector_size * 2048 * 4 + 1024 * 1024 * 2 ))
+    rm -f "$BACKING_FILE"
+    truncate -s "$disk_size" "$BACKING_FILE"
+
+    if losetup --find >/dev/null 2>&1; then
+        # shellcheck disable=SC2086
+        blockdev="$(losetup --find --show --sector-size $sector_size $BACKING_FILE)"
+    else
+        blockdev="$BACKING_FILE"
+    fi
+
+    sfdisk "$blockdev" <<EOF
 label: gpt
 unit: sectors
-sector-size: 512
+sector-size: $sector_size
 
 size=2048, type=4f68bce3-e8cd-4db1-96e7-fbcaf984b709, name=_empty
 size=2048, type=4f68bce3-e8cd-4db1-96e7-fbcaf984b709, name=_empty
@@ -29,13 +120,13 @@ size=2048, type=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5, name=_empty
 size=2048, type=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5, name=_empty
 EOF
 
-rm -rf /var/tmp/72-dirs
-mkdir -p /var/tmp/72-dirs
+    rm -rf /var/tmp/72-dirs
+    mkdir -p /var/tmp/72-dirs
 
-rm -rf /var/tmp/72-defs
-mkdir -p /var/tmp/72-defs
+    rm -rf /var/tmp/72-defs
+    mkdir -p /var/tmp/72-defs
 
-cat >/var/tmp/72-defs/01-first.conf <<"EOF"
+    cat >/var/tmp/72-defs/01-first.conf <<EOF
 [Source]
 Type=regular-file
 Path=/var/tmp/72-source
@@ -43,12 +134,12 @@ MatchPattern=part1-@v.raw
 
 [Target]
 Type=partition
-Path=/var/tmp/72-joined.raw
+Path=$blockdev
 MatchPattern=part1-@v
 MatchPartitionType=root-x86-64
 EOF
 
-cat >/var/tmp/72-defs/02-second.conf <<"EOF"
+    cat >/var/tmp/72-defs/02-second.conf <<EOF
 [Source]
 Type=regular-file
 Path=/var/tmp/72-source
@@ -56,12 +147,12 @@ MatchPattern=part2-@v.raw.gz
 
 [Target]
 Type=partition
-Path=/var/tmp/72-joined.raw
+Path=$blockdev
 MatchPattern=part2-@v
 MatchPartitionType=root-x86-64-verity
 EOF
 
-cat >/var/tmp/72-defs/03-third.conf <<"EOF"
+    cat >/var/tmp/72-defs/03-third.conf <<EOF
 [Source]
 Type=directory
 Path=/var/tmp/72-source
@@ -75,7 +166,7 @@ MatchPattern=dir-@v
 InstancesMax=3
 EOF
 
-cat >/var/tmp/72-defs/04-fourth.conf <<"EOF"
+    cat >/var/tmp/72-defs/04-fourth.conf <<EOF
 [Source]
 Type=regular-file
 Path=/var/tmp/72-source
@@ -86,90 +177,45 @@ Type=regular-file
 Path=/EFI/Linux
 PathRelativeTo=boot
 MatchPattern=uki_@v+@l-@d.efi \
-             uki_@v+@l.efi \
-             uki_@v.efi
+            uki_@v+@l.efi \
+            uki_@v.efi
 Mode=0444
 TriesLeft=3
 TriesDone=0
 InstancesMax=2
 EOF
 
-rm -rf /var/tmp/72-esp /var/tmp/72-xbootldr
-mkdir -p /var/tmp/72-esp/EFI/Linux /var/tmp/72-xbootldr/EFI/Linux
-export SYSTEMD_ESP_PATH=/var/tmp/72-esp
-export SYSTEMD_XBOOTLDR_PATH=/var/tmp/72-xbootldr
-
-rm -rf /var/tmp/72-source
-mkdir -p /var/tmp/72-source
-
-new_version() {
-    # Create a pair of random partition payloads, and compress one
-    dd if=/dev/urandom of="/var/tmp/72-source/part1-$1.raw" bs=1024 count=1024
-    dd if=/dev/urandom of="/var/tmp/72-source/part2-$1.raw" bs=1024 count=1024
-    gzip -k -f "/var/tmp/72-source/part2-$1.raw"
-
-    # Create a random "UKI" payload
-    echo $RANDOM >"/var/tmp/72-source/uki-$1.efi"
-
-    # Create tarball of a directory
-    mkdir -p "/var/tmp/72-source/dir-$1"
-    echo $RANDOM >"/var/tmp/72-source/dir-$1/foo.txt"
-    echo $RANDOM >"/var/tmp/72-source/dir-$1/bar.txt"
-    tar --numeric-owner -C "/var/tmp/72-source/dir-$1/" -czf "/var/tmp/72-source/dir-$1.tar.gz" .
-
-    ( cd /var/tmp/72-source/ && sha256sum uki* part* dir-*.tar.gz >SHA256SUMS )
-}
-
-update_now() {
-    # Update to newest version. First there should be an update ready, then we
-    # do the update, and then there should not be any ready anymore
-
-    "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no check-new
-    "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no update
-    ( ! "$SYSUPDATE" --definitions=/var/tmp/72-defs --verify=no check-new )
-}
-
-verify_version() {
-    # Expects: version ID + sector offset of both partitions to compare
-
-    # Check the partitions
-    dd if=/var/tmp/72-joined.raw bs=1024 skip="$2" count=1024 | cmp "/var/tmp/72-source/part1-$1.raw"
-    dd if=/var/tmp/72-joined.raw bs=1024 skip="$3" count=1024 | cmp "/var/tmp/72-source/part2-$1.raw"
-
-    # Check the UKI
-    cmp "/var/tmp/72-source/uki-$1.efi" "/var/tmp/72-xbootldr/EFI/Linux/uki_$1+3-0.efi"
-    test -z "$(ls -A /var/tmp/72-esp/EFI/Linux)"
-
-    # Check the directories
-    cmp "/var/tmp/72-source/dir-$1/foo.txt" /var/tmp/72-dirs/current/foo.txt
-    cmp "/var/tmp/72-source/dir-$1/bar.txt" /var/tmp/72-dirs/current/bar.txt
-}
-
-# Install initial version and verify
-new_version v1
-update_now
-verify_version v1 1024 3072
-
-# Create second version, update and verify that it is added
-new_version v2
-update_now
-verify_version v2 2048 4096
-
-# Create third version, update and verify it replaced the first version
-new_version v3
-update_now
-verify_version v3 1024 3072
-test ! -f "/var/tmp/72-xbootldr/EFI/Linux/uki_v1+3-0.efi"
-
-# Create fourth version, and update through a file:// URL. This should be
-# almost as good as testing HTTP, but is simpler for us to set up. file:// is
-# abstracted in curl for us, and since our main goal is to test our own code
-# (and not curl) this test should be quite good even if not comprehensive. This
-# will test the SHA256SUMS logic at least (we turn off GPG validation though,
-# see above)
-new_version v4
-
-cat >/var/tmp/72-defs/02-second.conf <<"EOF"
+    rm -rf /var/tmp/72-esp /var/tmp/72-xbootldr
+    mkdir -p /var/tmp/72-esp/EFI/Linux /var/tmp/72-xbootldr/EFI/Linux
+
+    rm -rf /var/tmp/72-source
+    mkdir -p /var/tmp/72-source
+
+    # Install initial version and verify
+    new_version "$sector_size" v1
+    update_now
+    verify_version "$blockdev" "$sector_size" v1 1 3
+
+    # Create second version, update and verify that it is added
+    new_version "$sector_size" v2
+    update_now
+    verify_version "$blockdev" "$sector_size" v2 2 4
+
+    # Create third version, update and verify it replaced the first version
+    new_version "$sector_size" v3
+    update_now
+    verify_version "$blockdev" "$sector_size" v3 1 3
+    test ! -f "/var/tmp/72-xbootldr/EFI/Linux/uki_v1+3-0.efi"
+
+    # Create fourth version, and update through a file:// URL. This should be
+    # almost as good as testing HTTP, but is simpler for us to set up. file:// is
+    # abstracted in curl for us, and since our main goal is to test our own code
+    # (and not curl) this test should be quite good even if not comprehensive. This
+    # will test the SHA256SUMS logic at least (we turn off GPG validation though,
+    # see above)
+    new_version "$sector_size" v4
+
+    cat >/var/tmp/72-defs/02-second.conf <<EOF
 [Source]
 Type=url-file
 Path=file:///var/tmp/72-source
@@ -177,12 +223,12 @@ MatchPattern=part2-@v.raw.gz
 
 [Target]
 Type=partition
-Path=/var/tmp/72-joined.raw
+Path=$blockdev
 MatchPattern=part2-@v
 MatchPartitionType=root-x86-64-verity
 EOF
 
-cat >/var/tmp/72-defs/03-third.conf <<"EOF"
+    cat >/var/tmp/72-defs/03-third.conf <<EOF
 [Source]
 Type=url-tar
 Path=file:///var/tmp/72-source
@@ -196,10 +242,14 @@ MatchPattern=dir-@v
 InstancesMax=3
 EOF
 
-update_now
-verify_version v4 2048 4096
+    update_now
+    verify_version "$blockdev" "$sector_size" v4 2 4
+
+    # Cleanup
+    [ -b "$blockdev" ] && losetup --detach "$blockdev"
+    rm "$BACKING_FILE"
+done
 
-rm  /var/tmp/72-joined.raw
 rm -r /var/tmp/72-{dirs,defs,source,xbootldr,esp}
 
 touch /testok