Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -999,3 +999,39 @@ func TestCTCreate_PortsFlag(t *testing.T) {
t.Errorf("ctPorts = %v, want [8080 3000]", ctPorts)
}
}

func TestLocalBootcScript_UsesTempDirMounts(t *testing.T) {
script := localBootcScript("/dev/loop7", "")

if !strings.Contains(script, "DISK=/dev/loop7") {
t.Errorf("script missing DISK=/dev/loop7:\n%s", script)
}
if !strings.Contains(script, "MNT_ESP=$(mktemp -d)") {
t.Errorf("script should use mktemp -d for ESP mount:\n%s", script)
}
if !strings.Contains(script, "MNT_ROOT=$(mktemp -d)") {
t.Errorf("script should use mktemp -d for composefs root mount:\n%s", script)
}
if !strings.Contains(script, "MNT=$(mktemp -d)") {
t.Errorf("script should use mktemp -d for post-install mount check:\n%s", script)
}

// Must not contain hardcoded /mnt paths that break on dangling symlinks (#389)
for _, forbidden := range []string{"/mnt/esp", "/mnt/root", "mkdir -p /mnt", "mount \"${DISK}p3\" /mnt ", "chroot /mnt"} {
if strings.Contains(script, forbidden) {
t.Errorf("script contains forbidden hardcoded /mnt path %q (#389):\n%s", forbidden, script)
}
}
}

func TestLocalBootcScript_WithProvisionScript(t *testing.T) {
script := localBootcScript("/dev/loop7", "echo test-provision")

wantChroot := `cat /output/provision.sh | chroot "$MNT" /bin/bash`
if !strings.Contains(script, wantChroot) {
t.Errorf("script missing chroot into temp mount %q:\n%s", wantChroot, script)
}
if strings.Contains(script, "chroot /mnt") {
t.Errorf("script contains forbidden chroot /mnt:\n%s", script)
}
}
93 changes: 52 additions & 41 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,14 +663,12 @@ func runLocalBootcCreate(name string) error {
}
defer exec.Command("sudo", "losetup", "-d", loopDev).Run()

var provisionArg string
if createProvisionScript != "" {
provFile := filepath.Join(vmDir, "provision.sh")
if err := os.WriteFile(provFile, []byte(createProvisionScript), 0755); err != nil {
return err
}
defer os.Remove(provFile)
provisionArg = "&& cat /output/provision.sh | chroot /mnt /bin/bash"
}

sshKey := kubevirt.LoadSSHPublicKey()
Expand All @@ -696,45 +694,7 @@ func runLocalBootcCreate(name string) error {
cmd := exec.Command("sudo", "podman", "run", "--privileged", "--pid=host", "--security-opt", "label=disable",
"-v", "/dev:/dev", "-v", vmDir+":/output:Z",
createBootc, "sh", "-c",
fmt.Sprintf(`set -e
DISK=%s
if ls /usr/lib/bootupd/updates/EFI/*/grub*.efi >/dev/null 2>&1 \
|| { [ -f /usr/lib/bootupd/updates/EFI.json ] \
&& find /usr/lib/efi/grub2 -type f -name 'grub*.efi' -print -quit 2>/dev/null | grep -q . \
&& find /usr/lib/efi/shim -type f -name 'shim*.efi' -print -quit 2>/dev/null | grep -q .; }; then
COMPOSEFS=0; FS=xfs; BACKEND=--generic-image
elif [ -f /usr/lib/systemd/boot/efi/systemd-bootx64.efi ] || [ -f /usr/lib/systemd/boot/efi/systemd-bootaa64.efi ]; then
COMPOSEFS=1; FS=btrfs; BACKEND=--composefs-backend
if command -v mkfs.ext4 >/dev/null 2>&1; then FS=ext4; fi
else
COMPOSEFS=0; FS=xfs; BACKEND=--generic-image
fi
echo "corral: install backend composefs=$COMPOSEFS fs=$FS"
bootc install to-disk $BACKEND --filesystem "$FS" --wipe --root-ssh-authorized-keys /output/id_rsa.pub "$DISK"
udevadm settle
if [ "$COMPOSEFS" = 1 ]; then
mkdir -p /mnt/esp
for P in 1 2 3; do
if mount "${DISK}p${P}" /mnt/esp 2>/dev/null; then
if [ -d /mnt/esp/EFI ]; then break; fi
umount /mnt/esp
fi
done
KVER=$(ls /usr/lib/modules | head -1)
D=$(ls -d /mnt/esp/EFI/Linux/bootc_composefs-* 2>/dev/null | head -1)
if [ -n "$D" ]; then
cp -f "/usr/lib/modules/$KVER/vmlinuz" "$D/vmlinuz"
cp -f "/usr/lib/modules/$KVER/initramfs.img" "$D/initrd"
fi
sync; umount /mnt/esp 2>/dev/null || true
mkdir -p /mnt/root; mount "${DISK}p3" /mnt/root
SSHDIR=/mnt/root/state/os/default/var/roothome/.ssh
mkdir -p "$SSHDIR"; chmod 700 "$SSHDIR"
cp /output/id_rsa.pub "$SSHDIR/authorized_keys"; chmod 600 "$SSHDIR/authorized_keys"; chown -R 0:0 "$SSHDIR"
sync; umount /mnt/root
fi
udevadm settle
mkdir -p /mnt && mount "${DISK}p3" /mnt %s && umount /mnt`, loopDev, provisionArg))
localBootcScript(loopDev, createProvisionScript))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
Expand Down Expand Up @@ -792,3 +752,54 @@ func maybeStartAndWait(name string) error {
}
return qemu.WaitSSH(name, createSSHUser, time.Duration(createTimeout)*time.Second)
}

func localBootcScript(disk, provisionScript string) string {
var provisionArg string
if provisionScript != "" {
provisionArg = `&& cat /output/provision.sh | chroot "$MNT" /bin/bash`
}
return fmt.Sprintf(`set -e
DISK=%s
if ls /usr/lib/bootupd/updates/EFI/*/grub*.efi >/dev/null 2>&1 \
|| { [ -f /usr/lib/bootupd/updates/EFI.json ] \
&& find /usr/lib/efi/grub2 -type f -name 'grub*.efi' -print -quit 2>/dev/null | grep -q . \
&& find /usr/lib/efi/shim -type f -name 'shim*.efi' -print -quit 2>/dev/null | grep -q .; }; then
COMPOSEFS=0; FS=xfs; BACKEND=--generic-image
elif [ -f /usr/lib/systemd/boot/efi/systemd-bootx64.efi ] || [ -f /usr/lib/systemd/boot/efi/systemd-bootaa64.efi ]; then
COMPOSEFS=1; FS=btrfs; BACKEND=--composefs-backend
if command -v mkfs.ext4 >/dev/null 2>&1; then FS=ext4; fi
else
COMPOSEFS=0; FS=xfs; BACKEND=--generic-image
fi
echo "corral: install backend composefs=$COMPOSEFS fs=$FS"
bootc install to-disk $BACKEND --filesystem "$FS" --wipe --root-ssh-authorized-keys /output/id_rsa.pub "$DISK"
udevadm settle
if [ "$COMPOSEFS" = 1 ]; then
MNT_ESP=$(mktemp -d)
for P in 1 2 3; do
if mount "${DISK}p${P}" "$MNT_ESP" 2>/dev/null; then
if [ -d "$MNT_ESP/EFI" ]; then break; fi
umount "$MNT_ESP"
fi
done
KVER=$(ls /usr/lib/modules | head -1)
D=$(ls -d "$MNT_ESP"/EFI/Linux/bootc_composefs-* 2>/dev/null | head -1)
if [ -n "$D" ]; then
cp -f "/usr/lib/modules/$KVER/vmlinuz" "$D/vmlinuz"
cp -f "/usr/lib/modules/$KVER/initramfs.img" "$D/initrd"
fi
sync; umount "$MNT_ESP" 2>/dev/null || true
rm -rf "$MNT_ESP"
MNT_ROOT=$(mktemp -d)
mount "${DISK}p3" "$MNT_ROOT"
SSHDIR="$MNT_ROOT/state/os/default/var/roothome/.ssh"
mkdir -p "$SSHDIR"; chmod 700 "$SSHDIR"
cp /output/id_rsa.pub "$SSHDIR/authorized_keys"; chmod 600 "$SSHDIR/authorized_keys"; chown -R 0:0 "$SSHDIR"
sync; umount "$MNT_ROOT"
rm -rf "$MNT_ROOT"
fi
udevadm settle
MNT=$(mktemp -d)
mount "${DISK}p3" "$MNT" %s && umount "$MNT"
rm -rf "$MNT"`, disk, provisionArg)
}
Loading