Skip to content

0.12.0 — a program that needs an interpreter could not be started at all - #25

Merged
Sunrisepeak merged 1 commit into
mainfrom
an-interpreter-could-not-be-reached
Aug 31, 2026
Merged

0.12.0 — a program that needs an interpreter could not be started at all#25
Sunrisepeak merged 1 commit into
mainfrom
an-interpreter-could-not-be-reached

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

⚠️⚠️ A defect this implementation has shipped, on every architecture, for as
long as kal_process_spawn has used execveat.

execveat with a directory descriptor and a relative name gives the kernel the
program's name as /dev/fd/<dirfd>/<name>. For an ordinary executable that
spelling never surfaces — the kernel holds the file open already. For a program
that needs an INTERPRETER it does: the kernel starts the interpreter and hands
it that name TO OPEN, after the replacement, by which time a close-on-exec
descriptor is gone. The interpreter is told the file does not exist.

Two kinds of program need one, and both were refused:

a `#!' script                      on every architecture
a binary of another architecture   through binfmt_misc

⭐ Isolated in twenty lines of ordinary C with nothing of openkal in it:

dirfd WITH O_CLOEXEC       execveat -> ENOENT
dirfd WITHOUT O_CLOEXEC    STARTED ok

The base descriptor is now duplicated in the STARTED image, where clearing
close-on-exec costs the caller nothing: its own descriptors stay as they were,
which is what every other operation here relies upon.

⚠️⚠️ HOW IT WAS NEARLY MISSED, which is worth more than the fix. It surfaced on
aarch64 under emulation, where every foreign binary needs the binfmt interpreter
and so every start failed at once — and three true observations pointed the
wrong way: the previous release failed identically, a consumer's 108 tests
passed on both architectures, and native binaries started fine in the same run.
Each was true; "therefore it is the emulator" was not. Reproducing it natively
with a `#!' script took one probe.

⚠️⚠️ A defect this implementation has shipped, on every architecture, for as
long as `kal_process_spawn` has used `execveat`.

`execveat` with a directory descriptor and a relative name gives the kernel the
program's name as `/dev/fd/<dirfd>/<name>`. For an ordinary executable that
spelling never surfaces — the kernel holds the file open already. For a program
that needs an INTERPRETER it does: the kernel starts the interpreter and hands
it that name TO OPEN, after the replacement, by which time a close-on-exec
descriptor is gone. The interpreter is told the file does not exist.

Two kinds of program need one, and both were refused:

    a `#!' script                      on every architecture
    a binary of another architecture   through binfmt_misc

⭐ Isolated in twenty lines of ordinary C with nothing of openkal in it:

    dirfd WITH O_CLOEXEC       execveat -> ENOENT
    dirfd WITHOUT O_CLOEXEC    STARTED ok

The base descriptor is now duplicated in the STARTED image, where clearing
close-on-exec costs the caller nothing: its own descriptors stay as they were,
which is what every other operation here relies upon.

⚠️⚠️ HOW IT WAS NEARLY MISSED, which is worth more than the fix. It surfaced on
aarch64 under emulation, where every foreign binary needs the binfmt interpreter
and so every start failed at once — and three true observations pointed the
wrong way: the previous release failed identically, a consumer's 108 tests
passed on both architectures, and native binaries started fine in the same run.
Each was true; "therefore it is the emulator" was not. Reproducing it natively
with a `#!' script took one probe.
@Sunrisepeak
Sunrisepeak merged commit 34f7668 into main Aug 31, 2026
2 checks passed
@Sunrisepeak
Sunrisepeak deleted the an-interpreter-could-not-be-reached branch August 31, 2026 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant