Cap LUKS Argon2id memory to avoid SIGKILL on live install - #96
Cap LUKS Argon2id memory to avoid SIGKILL on live install#96vincenzopalazzo wants to merge 5 commits into
Conversation
19d85a8 to
487573c
Compare
|
Reviewed this on a disposable VM; Pushed: Worth knowing why that guard matters more than it looks: both call sites gate on The memory cap costs more than Deriving the parameter from The floor breaks the 1/8 promise exactly where it matters. With 256 MiB available the helper asks for 64 MiB, which is a quarter, not an eighth; with 64 MiB available it asks for all of it. The clamp is doing the opposite of its stated job on the most constrained machines — the ones this PR is for — so those can still be OOM-killed. If 64 MiB is a security floor rather than a safety fraction, the helper probably needs to say so and fail (or warn) when the floor doesn't fit, rather than return a number that cannot work. The archinstall patch fails open on every path. The test doesn't test the helper. It runs the helper once against the real No header-compatibility problem: The branch is conflicting and the rebase is yours. The single conflict is the |
cryptsetup default argon2id memory cost (~1 GiB) OOMs on constrained live/PXE
boots, killing luksFormat with Signals.SIGKILL: 9.
- Add omarchy-luks-pbkdf-memory with a fixed 256 MiB Omarchy default. Step
down to the RFC 9106 64 MiB floor only when that default cannot fit, and
refuse to format when even the floor cannot. MemAvailable is not a
hardness knob: Argon2id attacker cost scales with memory squared times
passes, so --iter-time does not make up for a lower --pbkdf-memory.
- Use it in the protected-mode configurator luksFormat path, inside
run_partition_execute's existing disk_abort_hook / 2>&1 pipeline.
- Patch archinstall Luks2.encrypt before encrypted full-disk installs.
Locate luks.py via sys.path (do not importlib.util.find_spec), require
helper exit 0 plus numeric stdout, and fail closed if the patch misses.
Reproduction
- Desktop install of Omarchy 3.8.40 via LAN/PXE (USB boot unavailable)
- Client: ASRock-like NIC MAC d0:50:99:5a:3e:5e, target disk /dev/sda
- Live image ships archinstall on Python 3.14; full-disk encrypted layout
- Installer progressed through keyring sync, wiped /dev/sda, created
partitions, then died during LUKS format of /dev/sda2
Failure log (from installer screen)
subprocess.CalledProcessError: Command
['cryptsetup', '--batch-mode', '--verbose', ... 'luksFormat', '/dev/sda2']
died with <Signals.SIGKILL: 9>.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bin/omarchy-iso-make runs lint_file_permissions before the build and exits when an executable under configs/airootfs/{usr/local/bin,root} is missing from profiledef.sh, so the new helper failed the ISO build outright. mkarchiso does not carry the source mode across, and the callers guard on `command -v`, which in bash succeeds for a non-executable file in PATH — so a helper that shipped 0644 would be invoked and die with status 126 rather than falling back to 262144.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Codex XHigh <noreply@openai.com>
af859a7 to
517d960
Compare
|
@omarchybot thanks for the review — every point held. Pushed a rebase onto current Rebase / conflict. The luksFormat conflict was exactly Helper contract. Dropped the MemAvailable/8 sliding scale. Omarchy default is a fixed 256 MiB (262144 KiB) so every install gets the same KDF params. We only step down to the RFC 9106 64 MiB floor when that default cannot fit ( Patcher. Encrypted full-disk path is fail-closed: missing/unwritable Callers. Both Tests. Happy to drop the 256 MiB default to something else if that's the Omarchy number you want — 256 was the value you sketched. |
install_is_encrypted() gated the patch on user_encrypt_installation.txt, but nothing about that file decides whether luksFormat runs: archinstall_adapter.is_encrypted() reads disk_config.disk_encryption out of user_configuration.json, and README says outright that the flag file drives the encrypted install's autologin and boot validation, "not the encryption". An autoinstall drive whose config carries a disk_encryption block while the flag file says false — or True, or 1, both of which context.py:109 accepts and this did not — skipped the patch and left cryptsetup at the ~1 GiB default, which is the SIGKILL this branch exists to prevent. Ask disk_config.disk_encryption first, exactly as phases_impl.py:1237 already does, and keep the flag file as the fallback for when the config cannot be read. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The already-patched branch exited before rewriting, so a second run of omarchy-iso-install in the same live session left whatever value the first run chose. The helper re-reads MemAvailable each time and can land on the other side of the 128 MiB floor between attempts, so a retry after a failed install could log "capping archinstall LUKS Argon2id memory to 262144 KiB" and hand archinstall the 65536 it wrote earlier — or the reverse, which is the SIGKILL this branch exists to prevent, arriving on the retry. Substitute the value in place: still idempotent, still one --pbkdf-memory, and the number in the log is the number archinstall uses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-Authored-By: Codex XHigh <noreply@openai.com>
|
Re-reviewed the rebase on a disposable VM. The conflict resolution is right, and I checked it rather than took your word for it. Both guards survived: Pushed 9e2cec8 — the new Pushed 9b6ee70 — the already-patched branch kept the first run's number. It exited before rewriting, so a second run of One left for you: the locator only knows 4.x. The comment at While verifying, two things I could confirm for you: archinstall already passes The 256 MiB itself is still the maintainer's number to pick, not mine and not yours — it is a permanent, silent reduction from cryptsetup's ~1 GiB for every Omarchy encrypted install, about 4x cheaper to brute-force. Nothing else is blocking. |
The locator only walked lib/disk/luks.py, which is the 4.x home. 3.x kept the class at lib/luks.py, and the comment claiming a "3.x/4.x shape" for that path was wrong. The shipped ISO is 4.x so nothing was broken, but the patch is fail-closed: a miss aborts every encrypted install rather than quietly under-protecting one. Prefer 4.x, fall back to 3.x, still exit 1 when neither file is on sys.path.
|
@omarchybot thanks — both of the commits you pushed check out, and I took the remaining locator item. 9e2cec8. Gating on 9b6ee70. Exiting on the already-patched branch kept the first run's number. The helper re-reads Locator. Widened the walk in b4d3eaf: 256 MiB remains the maintainer's number to pick. |
|
Re-reviewed the delta only — b4d3eaf, the widened locator. Nothing found in it. Your push is a fast-forward and nothing of ours was lost. b4d3eaf's parent is exactly 9b6ee70, so there was no force-push and no partial revert. One thing worth stating plainly because it looks alarming in a log: af859a7 is not in the history any more — it was rebased away in the earlier round and survives as 517d960, and the two have an identical patch-id, so the The 3.x claim checks out, and I checked it against the real upstream file rather than the commit message. archinstall 3.0.15 does have The loop nesting is right, and it is right for a reason the comment doesn't say. The walk is outer over On the low-memory path the cap cannot be bypassed. The helper's only two successful outputs are 262144 and 65536, both below cryptsetup's ~1 GiB default; there is no branch that returns "use the default". Below 128 MiB One thing the second reviewer contributed that I had not reasoned about: Still the maintainer's call and still the only thing outstanding: 256 MiB as Omarchy's Argon2id cost for every encrypted install, down from cryptsetup's ~1 GiB. Nothing else is blocking. |
Summary
cryptsetup luksFormatwithSignals.SIGKILL: 9andCould not encrypt volumeon memory-constrained live/PXE boots--pbkdf-memoryfromMemAvailable(min 64 MiB, max 1 GiB, target 1/8 available) while keeping--iter-time 2000as the PBKDF hardness controlReproduction
What I was doing:
d0:50:99:5a:3e:5e(ASRock-like desktop)/dev/sdaas the install disk and confirmed overwrite/dev/sda, create partitions/dev/sda2Live environment notes:
OMARCHY_202607, airootfs ~7.1G squashfs over HTTP/PXE/usr/lib/python3.14/site-packages/archinstall/...)disk_encryptionwithencryption_type: luksanditer_time: 2000(no--pbkdf-memory)Failure log
Captured from the installer TTY when it crashed:
cryptsetupis SIGKILL'd mid-luksFormatwith no cryptsetup stderr — classic OOM of the Argon2id memory cost on a RAM-tight live session.What changed
omarchy-luks-pbkdf-memoryhelper picks a safe memory costluksFormatnow passes--pbkdf argon2id --pbkdf-memory … --iter-time 2000omarchy-iso-installpatches archinstallLuks2.encryptbefore Python imports it so the same cap appliestest/luks-pbkdf-memory-test.shTest plan
bash test/luks-pbkdf-memory-test.shluks.pyandpy_compilesucceededbash -non modified shell scriptsluksFormatsucceeds without SIGKILL