From fc7c3f858b4a56a17149d1b435443c546563d2ab Mon Sep 17 00:00:00 2001 From: veilor-org Date: Sat, 2 May 2026 03:42:15 +0100 Subject: [PATCH] v0.5.0-beta: fix 4 installer blockers found during lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bugs found by agent linter on v0.5.0-alpha: 1. logvol missing --size: ksvalidator rejected. Added --size=8192 --grow. 2. bootloader --location=mbr on UEFI: conflicts with /boot/efi part. Switched to --location=none (anaconda auto-detects EFI vs BIOS). 3. lsblk awk truncated multi-word disk models ("WD PC SN740" → "WD"). Now collapses model spaces to underscores, preserves full string. Also added mmcblk to disk regex (eMMC support). 4. Heredoc with $VAR expansion + passwords containing $/`/" corrupted generated ks. Now: single-quoted heredoc + sed placeholder substitution. Plus input validator rejects "$\` chars in passwords. ksvalidator clean on sample generated ks. bash -n clean. CI build still in flight (3328ffb). This pushes a new commit; CI will run again with these fixes. Net delay: zero (3328ffb's installer was broken anyway, so its ISO unusable for install path). --- overlay/usr/local/sbin/veilor-installer | 69 ++++++++++++++++++------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/overlay/usr/local/sbin/veilor-installer b/overlay/usr/local/sbin/veilor-installer index 4112974..eab8337 100644 --- a/overlay/usr/local/sbin/veilor-installer +++ b/overlay/usr/local/sbin/veilor-installer @@ -58,7 +58,10 @@ collect_answers() { local disks_list # ── Disk ── - disks_list=$(lsblk -dpno NAME,SIZE,MODEL | grep -E '^/dev/(sd|nvme|vd)' | awk '{print $1, $2"_"$3}') + # Build "tag description" pairs for whiptail. Model strings have spaces + # (e.g. "WD PC SN740"), so collapse model to underscores for menu. + disks_list=$(lsblk -dpno NAME,SIZE,MODEL | grep -E '^/dev/(sd|nvme|vd|mmcblk)' | \ + awk '{name=$1; size=$2; $1=""; $2=""; sub(/^ +/,""); gsub(/ /,"_"); model=$0; if(model=="")model="unknown"; print name, size"_"model}') if [[ -z $disks_list ]]; then whiptail --title "veilor-os" --msgbox "No installable disks found." 8 50 return 1 @@ -72,23 +75,34 @@ collect_answers() { --inputbox "Set hostname:" 10 60 "veilor" \ 3>&1 1>&2 2>&3) || return 1 + # Reject shell-special chars in passwords. Generated kickstart writes + # them via heredoc + sed substitution; bare $, ", \, ` would corrupt + # the ks line or partially expand. 8-char min for entropy. + validate_pw() { + local pw=$1 label=$2 + if [[ ${#pw} -lt 8 ]]; then + whiptail --title "Weak $label" --msgbox "Min 8 chars." 8 40 + return 1 + fi + if [[ $pw =~ [\"\$\\\`] ]]; then + whiptail --title "Invalid $label" --msgbox \ + "Cannot contain: \" \$ \\ \`" 8 50 + return 1 + fi + return 0 + } + # ── LUKS passphrase ── luks_pw=$(whiptail --title "Disk encryption" \ --passwordbox "LUKS passphrase (full-disk encryption):" 10 60 \ 3>&1 1>&2 2>&3) || return 1 - [[ ${#luks_pw} -lt 8 ]] && { - whiptail --title "Weak passphrase" --msgbox "Min 8 chars." 8 40 - return 1 - } + validate_pw "$luks_pw" "passphrase" || return 1 # ── Admin password ── admin_pw=$(whiptail --title "Admin password" \ --passwordbox "Admin user password (login after install):" 10 60 \ 3>&1 1>&2 2>&3) || return 1 - [[ ${#admin_pw} -lt 8 ]] && { - whiptail --title "Weak password" --msgbox "Min 8 chars." 8 40 - return 1 - } + validate_pw "$admin_pw" "password" || return 1 # ── Locale ── locale=$(whiptail --title "Locale" \ @@ -125,8 +139,12 @@ generate_ks() { # NOTE: passwords go in via --plaintext to avoid storing crypted hash # collisions; anaconda hashes per /etc/login.defs at install time. local out=/run/install/veilor-generated.ks + local disk_basename + disk_basename=$(basename "$SEL_DISK") mkdir -p /run/install - cat > "$out" << EOF + # Single-quoted heredoc → no shell expansion. Substitute placeholders + # via sed afterwards. Bulletproof against $/`/" in passwords. + cat > "$out" << 'KSEOF' || return 1 # veilor-os installer-generated kickstart # DO NOT commit this file — secrets inline. url --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-43&arch=x86_64" @@ -134,7 +152,7 @@ repo --name=fedora --baseurl="https://download.fedoraproject.org/pub/fedora/linu repo --name=updates --baseurl="https://download.fedoraproject.org/pub/fedora/linux/updates/43/Everything/x86_64/" --install keyboard --xlayouts='us' -lang $SEL_LOCALE +lang __LOCALE__ timezone Europe/London --utc firstboot --disable @@ -142,23 +160,24 @@ eula --agreed selinux --enforcing services --enabled=sshd,fail2ban,usbguard,tuned,auditd,firewalld,chronyd,sddm -network --bootproto=dhcp --device=link --activate --hostname=$SEL_HOSTNAME +network --bootproto=dhcp --device=link --activate --hostname=__HOSTNAME__ firewall --enabled --service=ssh rootpw --lock -user --name=admin --groups=wheel --gecos="veilor admin" --password="$SEL_ADMIN_PW" --plaintext +user --name=admin --groups=wheel --gecos="veilor admin" --password=__ADMIN_PW__ --plaintext # Full hardening cmdline (installed system, not live): -bootloader --location=mbr --append="lockdown=integrity slab_nomerge init_on_alloc=1 init_on_free=1 randomize_kstack_offset=on vsyscall=none" +# --location=none: anaconda auto-places bootloader (UEFI grub2-efi or BIOS). +bootloader --location=none --append="lockdown=integrity slab_nomerge init_on_alloc=1 init_on_free=1 randomize_kstack_offset=on vsyscall=none" # Disk: zero, LUKS2 (argon2id), btrfs subvolumes zerombr -clearpart --all --initlabel --drives=$(basename "$SEL_DISK") -part /boot/efi --fstype=efi --size=600 --asprimary -part /boot --fstype=ext4 --size=1024 --asprimary -part pv.veilor --grow --encrypted --luks-version=luks2 --pbkdf=argon2id --passphrase="$SEL_LUKS_PW" +clearpart --all --initlabel --drives=__DISK_BASENAME__ +part /boot/efi --fstype=efi --size=600 +part /boot --fstype=ext4 --size=1024 +part pv.veilor --grow --encrypted --luks-version=luks2 --pbkdf=argon2id --passphrase=__LUKS_PW__ volgroup veilor pv.veilor -logvol / --vgname=veilor --name=root --fstype=btrfs --grow +logvol / --vgname=veilor --name=root --fstype=btrfs --size=8192 --grow %packages --excludedocs @^kde-desktop-environment @@ -194,7 +213,17 @@ zram-generator # Reboot when done reboot -EOF +KSEOF + # Substitute placeholders. Use | as sed delimiter (passwords might + # contain /). Forbidden chars in passwords (validated upstream): "$\` + # — sed safe. + sed -i \ + -e "s|__LOCALE__|$SEL_LOCALE|" \ + -e "s|__HOSTNAME__|$SEL_HOSTNAME|" \ + -e "s|__DISK_BASENAME__|$disk_basename|" \ + -e "s|__LUKS_PW__|$SEL_LUKS_PW|" \ + -e "s|__ADMIN_PW__|$SEL_ADMIN_PW|" \ + "$out" echo "[INFO] generated kickstart at $out" return 0 }