From 855814666e24bce39c92c90b2e05e4cf901b5fae Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 10 Oct 2020 13:21:23 -0400 Subject: mostly old uncommitted changes committing everything without discretion rebase -i from me --- Makefile | 19 ++++++++++-- fsmgr | 2 +- initramfs-tools/scripts/samizdat | 28 +++++++++++++++--- rootfs/samizdat.patch.yaml | 7 +++++ src/initrd.sh | 6 ++++ src/initrd/btrfs-create.sh | 63 +++++++++++++++++++++++++++++++--------- src/initrd/grok-block | 40 ++++++++++++++++++------- src/parted-usb.sh | 35 +++++++++++++++------- 8 files changed, 158 insertions(+), 42 deletions(-) diff --git a/Makefile b/Makefile index 35294b4..53c643b 100644 --- a/Makefile +++ b/Makefile @@ -162,6 +162,7 @@ $(btrfs_images): FORCE $(MAKE) -C rootfs $(notdir $@) boot: rootfs + sudo initrd.sh sudo SLOW_BOOT=y qemu.sh fastboot: rootfs @@ -203,12 +204,26 @@ get_loop_dev="$$(sudo losetup -n -O name -j $@~tmp)" get_backing_file="$$(sudo losetup -n -O back-file -j $@~tmp)" get_min_size="$$(btrfs inspect-internal min-dev-size --id 1 $@.mnt | (read b _; echo $$b))" +%.verity.sh: %.verity + h=$$(sed -ne 's/^Root hash:[ \t]*//p' $<.log) && [ "$$h" ] && \ + printf 'verity_root_hash=%s\nverity_hash_offset=%s\n' "$$h" $(shell stat -c %s $(basename $<)) > $@ + +%.verity.log: %.verity %.verity: % - sudo veritysetup format $< $@~tmp > $@.log~tmp + cp --reflink $< $@~tmp + sudo veritysetup --hash-offset=$(shell stat -c %s $<) format $@~tmp $@~tmp > $@.log~tmp mv $@.log~tmp $@.log mv $@~tmp $@ sudo chmod 644 $@ - h=$$(sed -ne 's/^Root hash:[ \t]*//p' $@.log) && [ "$$h" ] + + +root_hash = $(shell sed -ne 's/^Root hash: *//p' < $<.log) + +veritymount: rootfs/samizdat.seed.btrfs.verity.sh + @sudo veritysetup remove samizverity >/dev/null 2>&1 || true + set -x && . $< && sudo veritysetup --ignore-corruption --hash-offset=$$verity_hash_offset \ + create samizverity $(basename $<) $(basename $<) $$verity_root_hash + sudo veritysetup remove samizverity %.verity.log.asc: %.verity.log sudo gpg --armor --detach-sign $^ diff --git a/fsmgr b/fsmgr index ea6de9a..f49e4f8 160000 --- a/fsmgr +++ b/fsmgr @@ -1 +1 @@ -Subproject commit ea6de9aeee6173363384b3b3a1dc4d37a900f961 +Subproject commit f49e4f88d55b0340ea69091a2f1a91882f199940 diff --git a/initramfs-tools/scripts/samizdat b/initramfs-tools/scripts/samizdat index 51f7cec..93c84d2 100644 --- a/initramfs-tools/scripts/samizdat +++ b/initramfs-tools/scripts/samizdat @@ -16,6 +16,28 @@ my_configure_networking() fi } +read_nbd_variables() +{ + NBDCLIENT=: + . /scripts/local-top/nbd + unset NBDCLIENT +} + +run_nbd_client() +{ + (debug_log samizdat.nbd + read_nbd_variables + for DEVNAME in /dev/nbd0 /dev/nbd1 + do + case "$DEVNAME" in + /dev/nbd0) nbdpath=samizdat.btrfs ;; + /dev/nbd1) nbdpath=samizdat.patch.btrfs ;; + esac + nbd-client $nbdsrv -N $nbdpath $nbdport $DEVNAME -swap -persist -systemd-mark + done + bootdone nbd-script) +} + mountroot() { openvt -c 13 sh @@ -24,10 +46,7 @@ mountroot() if [ "$nbdroot" ]; then my_configure_networking - - (debug_log samizdat.nbd - . /scripts/local-top/nbd - bootdone nbd-script) + run_nbd_client wait_for_gnupghome_tar (sleep 5; echo ) & @@ -56,6 +75,7 @@ wait_for_gnupghome_tar() done mv /gnupghome.tar.$$ /gnupghome.tar) echo ' done.' > /dev/tty1 + bootdone gnupg-tar } samizdat_restart_udev() diff --git a/rootfs/samizdat.patch.yaml b/rootfs/samizdat.patch.yaml index 98c6fc8..c9f3874 100644 --- a/rootfs/samizdat.patch.yaml +++ b/rootfs/samizdat.patch.yaml @@ -9,4 +9,11 @@ chroot-commands: - "/usr/local/bin/samizdat-update-apt-cache.sh" - "/usr/local/bin/samizdat-patch-root.sh" - "/usr/local/bin/samizdat-hostname.sh" +packages: +- ../openssh-client_8.3p1-1_$(debarch).deb +- ../openssh-server_8.3p1-1_$(debarch).deb +- ../openssh-sftp-server_8.3p1-1_$(debarch).deb +# ../openssh-tests_8.3p1-1_$(debarch).deb +- ../ssh_8.3p1-1_all.deb +- ../ssh-askpass-gnome_8.3p1-1_$(debarch).deb diff --git a/src/initrd.sh b/src/initrd.sh index 5bf19cf..e363c83 100755 --- a/src/initrd.sh +++ b/src/initrd.sh @@ -2,8 +2,14 @@ . samizdat-paths.sh +if [ -d "$1" ] +then + samizdat_linux_dir=$1 +fi + initrd=${samizdat_linux_dir}/initrd.img vmlinuz=${samizdat_linux_dir}/vmlinuz + conf_dir=$samizdat_initramfs_conf_dir apt_dependencies=$samizdat_initrd_files_dir/initrd-dependencies.txt diff --git a/src/initrd/btrfs-create.sh b/src/initrd/btrfs-create.sh index 39c89ca..cdf73ef 100644 --- a/src/initrd/btrfs-create.sh +++ b/src/initrd/btrfs-create.sh @@ -27,16 +27,41 @@ ceil4() printf '%d\n' "$x" } +kernel_commandline_has() +{ + local v="$1" c + read c < /proc/cmdline + for c in $c + do + case "$c" in + "$v"|"$v"=*) true; return;; + esac + done + false +} + +netbooted() +{ + kernel_commandline_has BOOTIF +} + cdrom_has_rootfs() { - [ ! "$BOOTIF" ] || return - bootwait samizdat-cdrom - [ -d /cdrom/rootfs ] + if netbooted + then + false + else + bootwait samizdat-cdrom + [ -d /cdrom/rootfs ] + fi } losetup_layers() { if cdrom_has_rootfs; then + # TODO: This is some kind of shortcut or short circuit to find these + # files, that ought to be found through the grok-block system (i.e., + # event-driven rather than polling). local fs fs_rw for fs in /cdrom/rootfs/*.btrfs; do fs_rw=/"${fs##*/}".rw @@ -45,8 +70,11 @@ losetup_layers() done else bootwait samizdat-nbd-dev - dd if=/dev/zero of=/nbd0.rw bs=1M count=10 - dm_snapshot /dev/nbd0 /nbd0.rw + local dev + for dev in nbd0 nbd1; do + dd if=/dev/zero of=/$dev.rw bs=1M count=10 + dm_snapshot /dev/$dev /$dev.rw + done return fi } @@ -210,15 +238,24 @@ filesystem_incomplete() partition_new_hard_drive_DESTROYING_EVERYTHING() { - local target="$1" + # TODO: get the actual size of the btrfs master and actually triple it. The empty + # space can be left available to allow the local machine to boot a + # locally-regenerated rootfs seed. + sz=3 + u=GiB + actual_sz=$sz$u + tripled_sz=$((sz * 3))$u + pct=100% # TODO: use 50% + + local target="$1" sz=6GiB # [ "$(parted -sm "$target" print | grep -c :)" = 1 ] || return - parted "$target" -sm \ - unit B \ - mklabel gpt \ - mkpart samizdat-grub-incomplete 32KiB 8160KiB \ - set 1 bios_grub on \ - mkpart samizdat-plaintext-incomplete btrfs 8MiB 1GiB \ - mkpart samizdat-luks-encrypted-incomplete 1GiB 100% \ + parted "$target" -sm \ + unit B \ + mklabel gpt \ + mkpart samizdat-grub-incomplete 32KiB 8MiB \ + set 1 bios_grub on \ + mkpart samizdat-plaintext-incomplete btrfs 64MiB $actual_sz \ + mkpart samizdat-luks-encrypted-incomplete $tripled_sz $pct \ && udevadm settle } diff --git a/src/initrd/grok-block b/src/initrd/grok-block index 86ff499..ee23b38 100755 --- a/src/initrd/grok-block +++ b/src/initrd/grok-block @@ -167,18 +167,29 @@ grok_block() # Avoid mouting this multiple times in case this script gets called multiple times, # because while it's mounted, the dmsetup stuff will fail with device busy. /dev/nbd0) - if [ -e /bootwait/samizdat-nbd-dev ] - then - return - else - bootwait nbd-script - wait_for_files_ /sys/block/nbd0/pid - fi + bootdone nbd0-dev + return ;; + /dev/nbd1) + bootwait nbd-script nbd0-dev + wait_for_files_ /sys/block/nbd0/pid /sys/block/nbd1/pid ;; esac case "$ID_PART_ENTRY_NAME" in samizdat-grub-incomplete|samizdat-plaintext-incomplete|samizdat-luks-encrypted-incomplete) return ;; - samizdat-grub|samizdat-luks-encrypted) return ;; + samizdat-plaintext) + . /verity.sh + cp /verity.sh /run/initramfs/samizdat/ + veritysetup --hash-offset="$verity_hash_offset" \ + create samizverity \ + "$DEVNAME" "$DEVNAME" "$verity_root_hash" + bootdone veritysetup + return + ;; + samizdat-grub) return ;; + samizdat-luks-encrypted) + menu-select boot-native "$(parent_device "$DEVNAME")" + return + ;; esac if [ "$ID_FS_TYPE" = hfsplus ] && ! fsck.hfsplus -q "$DEVNAME"; then @@ -191,7 +202,11 @@ grok_block() fi if ! mountpoint -q "$mountpoint"; then - retry_mount $mount_type -o ro "$DEVNAME" "$mountpoint" + if [ "$DEVNAME" = /dev/nbd1 ] + then OPTIONS='-o device=/dev/nbd0' + else OPTIONS= + fi + retry_mount $mount_type -r $OPTIONS "$DEVNAME" "$mountpoint" fi if ! mountpoint -q "$mountpoint"; then @@ -206,10 +221,13 @@ grok_block() elif [ "$ID_PART_ENTRY_NAME" = samizdat-plaintext ]; then if gpg_verify "$mountpoint"/disk.key && gpg_can_decrypt "$mountpoint"/disk.key; then addmenu_choose_native_root "$(parent_device "$DEVNAME")" + umount "$mountpoint" + bootdone key-mounted + else + umount "$mountpoint" fi - umount "$mountpoint" - elif [ "$DEVNAME" = /dev/nbd0 ]; then + elif [ "$DEVNAME" = /dev/nbd1 ]; then # This is our rootfs, over the network umount "$mountpoint" rmdir "$mountpoint" diff --git a/src/parted-usb.sh b/src/parted-usb.sh index bb63070..e688473 100755 --- a/src/parted-usb.sh +++ b/src/parted-usb.sh @@ -16,17 +16,29 @@ MiB() initialize_target() { rm -f "$target" - fallocate -l $(($(KiB 17) + $(MiB $end_keys))) "$target" + if [ "$ROOTFS" ] + then + fallocate -l $(($(KiB 17) + $(MiB $end_keys) + $(MiB $rootfs_size))) "$target" + else + fallocate -l $(($(KiB 17) + $(MiB $end_keys))) "$target" + fi } +# TODO: Use GUID type tags for each Samizdat partition type. partition_target() { - parted "$target" -sm -a optimal \ - unit B \ - mklabel gpt \ - mkpart samizdat-grub 1MiB 8MiB \ - set 1 bios_grub on \ - mkpart samizdat-plaintext btrfs ${start_keys}MiB ${end_keys}MiB + parted "$target" -sm -a optimal \ + unit MiB \ + mklabel gpt \ + mkpart samizdat-grub 1 8 \ + set 1 bios_grub on \ + mkpart samizdat-keys btrfs ${start_keys} ${end_keys} + + if [ "$ROOTFS" ] + then + parted "$target" -sm -a optimal \ + mkpart samizdat-rootfs btrfs ${end_keys}MiB 100% + fi } make_target_bootable() @@ -74,12 +86,13 @@ with_target() add_keys() { - rsync -a --info=STATS "$GPG_INPUT_DIR"/ "$mnt"/gnupghome/ + rsync -a --info=STATS "$GPG_INPUT_DIR"/ "$mnt"/gnupghome/ } +initrd_suffix=.samizdat add_initrd() { - rsync -aL --info=STATS "$samizdat_linux_dir"/vmlinuz${version} "$samizdat_linux_dir"/initrd.img${version} "$mnt"/linux/ + rsync -aL --info=STATS "${1}vmlinuz${2}" "${1}initrd.img${2}${initrd_suffix}" "$mnt"/linux/ } add_grub_cfg() @@ -91,7 +104,7 @@ add_grub_cfg() add_all() { add_keys - add_initrd + add_initrd "$samizdat_linux_dir"/ "${version_suffix}" add_grub_cfg } @@ -128,7 +141,7 @@ fi if [ "$1" ] then - version=-$1 + version_suffix=-$1 fi cp --reflink=always "$target" "$target".keyed with_target "$target".keyed add_all -- cgit v1.2.3