Summary
On Shadowfetch 2.1.1, every install attempt dies at ~57% progress ("Running shell processes…", job 23 of 43). The entire live session is terminated mid-install — the desktop vanishes, SDDM restarts and presents a login prompt for the live user (shadow) — taking Calamares down with it. The target system is left half-installed in a specific and dangerous state (details below).
Root cause: /usr/local/sbin/sf-remove-live-user runs pkill -KILL -u shadow. The script executes inside the target chroot as designed (dontChroot: false), but chroot does not isolate the process table — pkill matches against the kernel's global PID list, and the live session's user is shadow (uid 1000). The SIGKILL lands on every process of the running desktop session. Calamares itself (running as root) survives the pkill but dies seconds later when its display server connection disappears with the compositor.
The bug is deterministic — 100% reproduction across 4 attempts — and because the executed script is the pristine copy unpacked from the squashfs into the target, patching the live system's copy of the script does not help. The only user-side workaround is editing the Calamares module config (below).
The irony is painful and worth stating plainly: this script is a security hardening (its comments explain it was rewritten to fail loudly rather than silently ship the shadow/shadow NOPASSWD account). The pkill added as "obstacle clearing" is what prevents the removal from ever completing — and the resulting aborted install ships the exact exposure the script exists to prevent (see Impact).
Environment
- Shadowfetch 2.1.1 "Umbra" ISO, SHA-256 verified (
f5fe0f...afdba), GPG signature verified
- KVM/QEMU via virt-manager on a Linux host: Q35 chipset, OVMF UEFI (Secure Boot disabled), VirtIO disk (qcow2, ~110 GB), VirtIO NIC, 21 GB RAM, 4 vCPU host-passthrough
- Erase Disk → Btrfs → Swap (no Hibernate)
- Reproduced under: Wayland session and X11 session; virtio-gpu with 3D acceleration on and off; screen locking disabled; sleep targets masked; mouse actively moving at crash time. None of these change the outcome — ruling out graphics, idle, power management, and screen-locking as causes.
Symptom
At job 23/43 the session dies. ~/.cache/calamares/session.log (root's copy) and a calamares -d tee capture end identically every time:
13:47:57 [6]: virtual void Calamares::JobThread::run()
Starting job "Running shell processes…" ( 23 / 43 )
.. Running QList("/bin/sh", "-c", "sh /usr/local/sbin/sf-remove-live-user")
Nothing after. The journal at the same moment shows the session being torn down with no crash of any individual component logged:
10:50:49 systemd-logind: Removed session 7.
10:50:52 systemd[11080]: drkonqi-coredump-launcher.socket: ... not starting since we tried this too often recently.
10:50:52 sddm: Greeter stopped. SDDM::Auth::HELPER_DISPLAYSERVER_ERROR
10:50:52 sddm: Failed to launch the display server, falling back to DisplayServer=x11-user
10:50:52 systemd: session-11.scope: Deactivated successfully.
Impact — state of the target after the aborted install
Jobs 24–43 never run. The resulting on-disk system:
- has no bootloader — boots to the OVMF UEFI shell (no
EFI/BOOT/BOOTX64.EFI, no NVRAM entry, empty ESP)
- has no user account from the installer — the username/password entered in Calamares are silently discarded
- retains the live
shadow account with its published password, NOPASSWD:ALL sudoers file, and SDDM autologin — i.e. the precise "known credential" exposure sf-remove-live-user was written to close
- retains the "Install Shadowfetch Linux" desktop shortcut and other live artefacts (cleanup module never runs)
- locale/timezone/hwclock configuration is incomplete
A user who manually repairs the bootloader (as I initially did, before diagnosing the root cause) gets a bootable system that looks installed but is running the live account with the known credential.
Reproduction
- Boot the 2.1.1 ISO (VM or presumably bare metal — nothing in the mechanism is VM-specific).
- Run the installer, any reasonable options (tested: Erase Disk, Btrfs, swap-no-hibernate).
- Wait for job 23/43 (~57% on the progress bar). The session dies within seconds of the job starting.
Note for anyone re-testing: after the crash, re-running the installer in the same session offers only Manual partitioning — the crashed run's target mounts under /tmp/calamares-root-* are still held, and Calamares silently withholds Erase Disk when the target disk has mounted partitions. sudo umount -R /tmp/calamares-root-* (or a reboot) restores the option. This considerably worsens the first-run failure: the natural "just try again" path fails in a second, unexplained way.
Root cause detail
/etc/calamares/modules/shellprocess.conf:
dontChroot: false
timeout: 60
script:
- "sh /usr/local/sbin/sf-remove-live-user"
sf-remove-live-user, step 1 ("clear the three known obstacles"):
pkill -KILL -u "$USER" 2>/dev/null || true
With dontChroot: false the script runs chrooted into the target — but pkill reads the global process table via the (bind-mounted) /proc and signals by uid. uid 1000 (shadow) inside the chroot and uid 1000 running the live desktop are the same uid to the kernel. Every session process gets SIGKILL; logind removes the session; the compositor's death severs Calamares's display connection and it exits, aborting the queue.
In a freshly unpacked target there are, by construction, no processes to kill — the pkill can only ever act on the live session. (The timeout: 60 comment in shellprocess.conf notes the timeout was raised specifically to give the pkill time to run.)
Why users cannot work around it by editing the script
The chrooted command resolves /usr/local/sbin/sf-remove-live-user inside the target — the pristine copy that unpackfs extracted from the squashfs minutes earlier. Editing the live system's copy has no effect (empirically confirmed: attempt 4 crashed identically with the live copy patched). The workaround must go through the Calamares config, which is read from the live system:
sudo tee /etc/calamares/modules/shellprocess.conf > /dev/null <<'EOF'
---
dontChroot: false
timeout: 60
script:
- "sed -i 's/^pkill -KILL/: pkill-disabled/' /usr/local/sbin/sf-remove-live-user"
- "sh /usr/local/sbin/sf-remove-live-user"
EOF
Both entries run chrooted; the sed disables the pkill in the target's copy immediately before execution. With this in place, the install completes normally: the script's userdel/cleanup/verification all succeed (job 23 passes its own verification — account, hash, home, sudoers, and autologin all removed from the target), and jobs 24–43 run. Verified working: user account created, no shadow in /home, no autologin, bootloader installed, desktop clean.
Suggested fix
The minimal fix is deleting the pkill line — in the target chroot it has no legitimate targets. If the defensive intent is worth keeping, scope it to processes actually rooted in the target:
for pid in $(pgrep -u "$USER"); do
[ "$(readlink /proc/$pid/root)" = "/" ] || kill -KILL "$pid" 2>/dev/null
done
(In the chroot, /proc/$pid/root for live-session processes resolves outside the chroot; only processes whose root is the chroot itself would be killed. In practice the loop will match nothing, which is the correct outcome.)
chattr -R -i and the rest of the script are chroot-safe and can stay as-is.
Secondary findings from the same debugging session
- Erase Disk silently unavailable on retry (described under Reproduction) — if Calamares can detect mounted target partitions, a user-visible message ("disk has mounted partitions — unmount or reboot to enable automatic partitioning") would prevent the second-order confusion.
- Installed system has no time sync:
systemd-timesyncd is not installed/enabled, so timedatectl reports the clock never synchronizes and KDE's Date & Time panel fails with "Unable to change NTP settings". Additionally the hwclock is configured as local time (RTC in local TZ: yes), which in VMs (where the host supplies UTC) yields a clock offset equal to the timezone offset. Suggest shipping timesyncd enabled and defaulting RTC to UTC.
- Docs: the hardware page recommends enabling 3D acceleration in VMs. During diagnosis (before finding the real cause) we observed that virtio-gpu/virgl + Plasma 6 Wayland is a fragile combination in general; a caveat may save VM users some pain, though it was ultimately unrelated to this bug.
Happy to provide full logs (calamares -d captures of two crashed runs and the successful patched run, journal extracts) on request.
Summary
On Shadowfetch 2.1.1, every install attempt dies at ~57% progress ("Running shell processes…", job 23 of 43). The entire live session is terminated mid-install — the desktop vanishes, SDDM restarts and presents a login prompt for the live user (
shadow) — taking Calamares down with it. The target system is left half-installed in a specific and dangerous state (details below).Root cause:
/usr/local/sbin/sf-remove-live-userrunspkill -KILL -u shadow. The script executes inside the target chroot as designed (dontChroot: false), but chroot does not isolate the process table —pkillmatches against the kernel's global PID list, and the live session's user isshadow(uid 1000). The SIGKILL lands on every process of the running desktop session. Calamares itself (running as root) survives the pkill but dies seconds later when its display server connection disappears with the compositor.The bug is deterministic — 100% reproduction across 4 attempts — and because the executed script is the pristine copy unpacked from the squashfs into the target, patching the live system's copy of the script does not help. The only user-side workaround is editing the Calamares module config (below).
The irony is painful and worth stating plainly: this script is a security hardening (its comments explain it was rewritten to fail loudly rather than silently ship the
shadow/shadowNOPASSWD account). The pkill added as "obstacle clearing" is what prevents the removal from ever completing — and the resulting aborted install ships the exact exposure the script exists to prevent (see Impact).Environment
f5fe0f...afdba), GPG signature verifiedSymptom
At job 23/43 the session dies.
~/.cache/calamares/session.log(root's copy) and acalamares -dtee capture end identically every time:Nothing after. The journal at the same moment shows the session being torn down with no crash of any individual component logged:
Impact — state of the target after the aborted install
Jobs 24–43 never run. The resulting on-disk system:
EFI/BOOT/BOOTX64.EFI, no NVRAM entry, empty ESP)shadowaccount with its published password, NOPASSWD:ALL sudoers file, and SDDM autologin — i.e. the precise "known credential" exposuresf-remove-live-userwas written to closeA user who manually repairs the bootloader (as I initially did, before diagnosing the root cause) gets a bootable system that looks installed but is running the live account with the known credential.
Reproduction
Note for anyone re-testing: after the crash, re-running the installer in the same session offers only Manual partitioning — the crashed run's target mounts under
/tmp/calamares-root-*are still held, and Calamares silently withholds Erase Disk when the target disk has mounted partitions.sudo umount -R /tmp/calamares-root-*(or a reboot) restores the option. This considerably worsens the first-run failure: the natural "just try again" path fails in a second, unexplained way.Root cause detail
/etc/calamares/modules/shellprocess.conf:sf-remove-live-user, step 1 ("clear the three known obstacles"):With
dontChroot: falsethe script runs chrooted into the target — butpkillreads the global process table via the (bind-mounted)/procand signals by uid. uid 1000 (shadow) inside the chroot and uid 1000 running the live desktop are the same uid to the kernel. Every session process gets SIGKILL; logind removes the session; the compositor's death severs Calamares's display connection and it exits, aborting the queue.In a freshly unpacked target there are, by construction, no processes to kill — the pkill can only ever act on the live session. (The
timeout: 60comment in shellprocess.conf notes the timeout was raised specifically to give the pkill time to run.)Why users cannot work around it by editing the script
The chrooted command resolves
/usr/local/sbin/sf-remove-live-userinside the target — the pristine copy that unpackfs extracted from the squashfs minutes earlier. Editing the live system's copy has no effect (empirically confirmed: attempt 4 crashed identically with the live copy patched). The workaround must go through the Calamares config, which is read from the live system:Both entries run chrooted; the
seddisables the pkill in the target's copy immediately before execution. With this in place, the install completes normally: the script's userdel/cleanup/verification all succeed (job 23 passes its own verification — account, hash, home, sudoers, and autologin all removed from the target), and jobs 24–43 run. Verified working: user account created, noshadowin/home, no autologin, bootloader installed, desktop clean.Suggested fix
The minimal fix is deleting the pkill line — in the target chroot it has no legitimate targets. If the defensive intent is worth keeping, scope it to processes actually rooted in the target:
(In the chroot,
/proc/$pid/rootfor live-session processes resolves outside the chroot; only processes whose root is the chroot itself would be killed. In practice the loop will match nothing, which is the correct outcome.)chattr -R -iand the rest of the script are chroot-safe and can stay as-is.Secondary findings from the same debugging session
systemd-timesyncdis not installed/enabled, sotimedatectlreports the clock never synchronizes and KDE's Date & Time panel fails with "Unable to change NTP settings". Additionally the hwclock is configured as local time (RTC in local TZ: yes), which in VMs (where the host supplies UTC) yields a clock offset equal to the timezone offset. Suggest shipping timesyncd enabled and defaulting RTC to UTC.Happy to provide full logs (
calamares -dcaptures of two crashed runs and the successful patched run, journal extracts) on request.