1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
summary: Check that a broken kernel snap automatically rolls itself back
details: |
Check the trigger for a broken kernel installation (there are 7 different
kernel corruptions) adds an install change error and that the initial kernel revision
remains installed and we don't have leftover bootenv.
# TODO:UC20: write equivalent test for base snap failover
systems: [ubuntu-2*]
environment:
PROBLEM_TYPE/crash: crash
PROBLEM_TYPE/empty: empty
PROBLEM_TYPE/zeros: zeros
PROBLEM_TYPE/nolink: nolink
# bad-text produces a bad systemd efi stub (.text section in the binary)
PROBLEM_TYPE/bad_text: bad-text
PROBLEM_TYPE/bad_linux: bad-linux
PROBLEM_TYPE/bad_initrd: bad-initrd
prepare: |
echo "Build a broken kernel snap where the initramfs panic's"
# shellcheck source=tests/lib/prepare.sh
. "$TESTSLIB/prepare.sh"
# use the kernel snap from the nested VM and repack it so that it panic's in
# the initramfs and rolls back to the original version
# TODO:UC20: this doesn't work for some reason when we copy it from the
# running system, we should look into that, but for now just
# re-download the snap
version="$(tests.nested show version)"
snap download pc-kernel --channel="$version/beta" --basename=pc-kernel
case "$PROBLEM_TYPE" in
crash)
if [ "$version" -le 22 ]; then
uc20_build_initramfs_kernel_snap pc-kernel.snap "$PWD" --inject-kernel-panic-in-initramfs
else
uc24_build_initramfs_kernel_snap pc-kernel.snap "$PWD" --inject-kernel-panic-in-initramfs
fi
;;
nolink)
# Failure will be forced by removing the try-kernel.efi link later,
# do not modify the downloaded kernel (just change name so it is picked
# up by the move command later)
mv pc-kernel.snap pc-kernel_.snap
;;
*)
uc20_build_corrupt_kernel_snap pc-kernel.snap "$PWD" --"$PROBLEM_TYPE"
;;
esac
mv pc-kernel_*.snap panicking-initramfs-kernel.snap
execute: |
echo "Copy the broken initramfs kernel snap to the UC20 VM"
remote.push panicking-initramfs-kernel.snap
echo "Wait for snapd to be available"
remote.wait-for snap-command
echo "Wait for snapd to be seeded"
remote.exec sudo snap wait system seed.loaded
# Get the current revision of the kernel snap
# TODO:UC20: enable for pi-kernel, etc. when used with external systems
startRevision=$(remote.exec sudo snap list pc-kernel | grep pc-kernel | awk '{print $3}')
if [ -z "${startRevision}" ]; then
echo "missing pc-kernel revision"
exit 1
fi
boot_id="$( tests.nested boot-id )"
echo "Install it and get the ID for the change"
REMOTE_CHG_ID=$(remote.exec sudo snap install --dangerous panicking-initramfs-kernel.snap --no-wait)
if [ "$PROBLEM_TYPE" = "nolink" ]; then
remote.exec "retry --wait 1 -n 100 sh -c 'sudo rm /run/mnt/ubuntu-boot/EFI/ubuntu/try-kernel.efi'"
fi
# wait for a reboot. Note that failure is immediate for kernel.efi
# files with invalid PE headers in the FDE case, as snapd is not
# able to unseal the encryption key in that case ("cannot compute
# load verification event").
if [ "$PROBLEM_TYPE" != "empty" ] && [ "$PROBLEM_TYPE" != "zeros" ]; then
remote.wait-for reboot "${boot_id}"
fi
# Wait for the change to finish - note it will exit with non-zero since the
# change will fail, so don't let that kill the test here
if remote.exec sudo snap watch "${REMOTE_CHG_ID}"; then
echo "remote snap change ${REMOTE_CHG_ID} for broken kernel snap refresh should have failed!"
exit 1
fi
echo "Check that the refresh failed"
remote.exec sudo snap changes | grep "${REMOTE_CHG_ID}" | MATCH Error
case "$PROBLEM_TYPE" in
empty)
remote.exec sudo snap tasks "${REMOTE_CHG_ID}" | MATCH "cannot decode image: EOF"
;;
zeros)
remote.exec sudo snap tasks "${REMOTE_CHG_ID}" | MATCH "cannot measure secure boot event:"
;;
*)
remote.exec sudo snap tasks "${REMOTE_CHG_ID}" | MATCH "cannot finish .* installation, there was a rollback across reboot"
;;
esac
echo "Check We should be on the same revision of the kernel snap"
if [ "$(remote.exec sudo snap list pc-kernel | grep pc-kernel | awk '{print $3}')" != "${startRevision}" ]; then
echo "pc-kernel is on the wrong revision"
exit 1
fi
echo "Check we don't have leftover bootenv"
remote.exec sudo snap debug boot-vars --uc20 | MATCH '^kernel_status=$'
echo "Check that we don't have extra assets in the ubuntu-boot dir and that the currently enabled kernel is the original kernel"
# kernel.efi symlink should point to the original kernel
remote.exec readlink /run/mnt/ubuntu-boot/EFI/ubuntu/kernel.efi | MATCH "pc-kernel_${startRevision}.snap/kernel.efi"
# should still have pc-kernel_$rev.snap dir
remote.exec test -d "/run/mnt/ubuntu-boot/EFI/ubuntu/pc-kernel_${startRevision}.snap"
if [ "$(remote.exec ls /run/mnt/ubuntu-boot/EFI/ubuntu/pc-kernel_*.snap | wc -l)" != 1 ]; then
echo "Extra leftover pc-kernel assets in ubuntu-boot:"
remote.exec ls /run/mnt/ubuntu-boot/EFI/ubuntu/pc-kernel_*.snap
exit 1
fi
|