Skip to content

0.10.0 — the exec search, and the family of answers that were not true

Choose a tag to compare

@Sunrisepeak Sunrisepeak released this 30 Aug 06:09
· 8 commits to main since this release
2601979

openkal-linux#13, fifth round.

A consumer measured that execvp could not get past the first PATH entry that
missed — one libc path accounting for nine of their nineteen failures, plus
four sections silently skipped because bwrap, installed at /usr/bin/bwrap,
was reported as not installed. That is fixed, and reading it out found six more
of the same family
.

⭐⭐ What they have in common

Every probe in this repository asked whether an operation worked. None asked
whether an answer was true. OPENKAL_MUSL_TRACE=enosys reports what reaches
the default arm, and not one of these reaches it — they are operations that are
present and answer wrongly. examples/surface is new, and is the probe that asks
the other question.

⚠️⚠️ The heaviest one was not in the report

fcntl(F_SETLK), F_SETLKW and F_GETLK answered 0 and did nothing. Measured
against the host: two programs took one exclusive lock and both were told they
had it.
F_GETLK pointed the other way — it left the caller's word untouched,
which reads as "somebody holds this", for ever, so a loop waiting for a lock
never left it. All three now report ENOSYS.

⭐ That refusal is temporary in a way the permission one is not: every
environment beneath openkal can lock a byte range, and what is missing is a word
in the specification — asked for as mcpplibs/openkal#22.

Answered

  • execve returns when the program cannot be started, so execvp can search
    a PATH. posix_spawn reports ENOENT/EACCES instead of success.
  • posix_spawnp searches PATH at all — musl's source is replaced, the tenth.
  • getppid no longer hands back -38 as an identifier (the defect getpgrp
    had one release earlier, three lines away, and that was not looked for).
  • A copy made by fork names itself instead of reporting its parent.
  • setpgid(0,0)0 and setsid()EPERM, the failure POSIX writes down.
    Every daemonising library handles EPERM; none handles ENOSYS.
  • sigaltstack refuses instead of reporting an installation it did not perform.
  • sysconf(_SC_OPEN_MAX) answers the bound this library sets, not 0.
  • A directory's modification time can be set where the implementation can
    open a directory (Linux, macOS; not Windows). Reading it was never broken — the
    consumer reported it as a read failure because libc++ gives both overloads of
    last_write_time one name.

⚠️ Not answered, and now recorded

kill does not reach a program started by fork + execve — it reaches the
copy that is waiting for it. Measured with the host as control: identical status
words, opposite outcomes. Use posix_spawn, system or popen where you need
to stop what you started. Asked for as mcpplibs/openkal#23.

README.md and musl/PATCHES.md claimed a caller cannot distinguish
execve-as-spawn+wait from a real replacement. That claim was false, and is what
kept anyone from looking. Both now list the three known differences.

Also recorded: access(X_OK) answers yes for anything that exists; descriptors
above 2 do not cross into a started program; sched_getaffinity is absent so
hardware_concurrency() answers 1 silently; statvfs, link, mkfifo and
socketpair have no operation beneath.

Criteria

examples/surface fails eleven of its observations on 0.9.0 and none here.
examples/subprocess gains the exec search and the identity, and on 0.9.0 it
does not merely fail — it stops, at the execve observation, which is the
defect itself.