Repository navigation
Step 9's file half: the kernel keeps no working directory; a spawn states it in the child's PWD - #1182
Conversation
…'s PWD Step 9's file half left SYS_GETCWD (21): the kernel copied each spawn's starting directory out of SpawnArgs, judged it absolute and at most MAX_PATH (kernel/pure/cwd.rs), kept it in ProcessData for the process's life and answered it once to the SDK. The working directory has been the SDK's own state since #1152; the kernel only carried its first value. That value now travels in data the parent already hands the child, its environment, under POSIX's own name for it, PWD. The SDK's helper spawn, which std's Command, libc's posix_spawn and the supervisor's launcher all go through, writes PWD=<dir> in place of any PWD the environment held (toyos::files::starting_in) and refuses a directory that is not absolute, is past MAX_PATH or holds a NUL, as the kernel refused it before. The child's SDK reads its spawn-time environment once and starts there (starting_directory); a spawn that states none, such as the kernel's start of the supervisor, starts its child at the root of its view, which is where every raw-syscall spawn in the tree put it. Deleted: SYS_GETCWD, syscall::getcwd, SpawnArgs::cwd_ptr/cwd_len, the kernel's ProcessData::cwd, sys_getcwd, the spawn's cwd copy and kernel::cwd. The raw spawns in the guest tests lose their cwd fields, and abuse_spawn_argv its working-directory refusals, which are now the SDK's and held by its host tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1182 removes SYS_GETCWD, so the small-kernel track's first item is the windows that half owes, beside its measured lines, and the isolation track's stage 1 no longer lists the kernel's working directory as left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #1182 at 34c11de (base dd05bf5)ArchitectureThe design fits. The kernel loses a field, a pure module, a syscall and a
Deletion is complete. Outside Size. The diff is +136/−170. The env bytes the kernel keeps for Evidence. I checked the following:
That run never starts a child anywhere but FindingsBLOCKER
SUGGESTION
VerdictSEND BACK, for one blocker: a one-line stale comment. With that fixed and the pending metal readings for |
A check that a child std spawns with current_dir starts there, through the SDK's PWD and the child's SDK reading it: the binary runs itself in a fresh /tmp directory under an inherited PWD naming another, and the child prints its working directory. std_fs is a shared member, so this runs on metal (testcases), not on a filtered QEMU run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1182 removes SYS_GETCWD, so the small-kernel track's first item is the windows that half owes, beside its measured lines, and the isolation track's stage 1 no longer lists the kernel's working directory as left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s kernel-held query_modules_size's header pointed its contract at sys_getcwd and sys_readdir, neither of which exists now; the next line states the contract itself. The small-kernel record names the environment (ProcessData::env, SYS_GET_ENV) as userland data the kernel still holds, with a startup memory object as its likely exit, so "the kernel keeps no working directory" is not read as "the kernel holds no path text". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
34c11de to
0e98591
Compare
|
Orchestrator verification of the r1 fix (34c11de..0e98591), which changes no code:
|
Problem
Step 9's file half (#1152) left
SYS_GETCWD(21). The kernel copied each spawn's starting directory out ofSpawnArgs::cwd_ptr/cwd_len, checked that it was absolute and at mostMAX_PATH(kernel/pure/cwd.rs), and kept it inProcessData::cwdfor the life of the process. Its only job was to answer the SDK once, and the SDK has owned the working directory since #1152.Result
The kernel keeps no working directory. The starting directory now travels in data the parent already hands the child: its environment, under POSIX's own name for it,
PWD.toyos::spawn::Helper::spawnis the one helper spawn that std'sCommand, libc'sposix_spawnand the supervisor's launcher all reach. It writesPWD=<dir>in place of anyPWDthe given environment held (toyos::files::starting_in). It refuses a directory that is not absolute, is longer thanMAX_PATHor holds a NUL, which are the checks the kernel used to make, now made at the SDK boundary.SYS_GET_ENV, which the kernel keeps unchanged) the first time it needs its working directory. It starts there, cleaned of.and..(starting_directory).PWDstarts its child at the root of its view. That covers the kernel's start of the supervisor and every raw-syscall spawn in the tree, all of which passed/before.PWDthat is not absolute UTF-8 panics the child loudly, as the oldasserton the kernel's answer did. Only a raw-syscall parent can write one.PWD, even one spawned afterCommand::env_clear(), which on Linux, macOS and Windows would see noPWD. That is the carrier: the spawn states the child's directory there.SYS_GETCWD,syscall::getcwd,SpawnArgs::cwd_ptr/cwd_len,ProcessData::cwd,sys_getcwd, the spawn's cwd copy, andkernel::cwdwith its tests.abuse_spawn_argvdrops its working-directory refusals; those refusals are now the SDK's, held by host tests.sdk/stdin this tree (sys/process.rsgets one comment). No fork or~/.cargo/git/checkoutsconsumer names the removed items.ProcessData::env,SYS_GET_ENV) as userland data the kernel still holds, with a startup memory object as the likely exit. The isolation stage 1 record no longer lists the kernel's working directory. Thecwdparagraph ofthe-capability-end-state-is-twelve-answers.md, already stale (spawn_cwd.rs,kernel/src/syscall/fs.rs), now says what is true.Decision: why the environment
The brief left the carrier open: environment, endowment labels or the startup block.
PWDsees the truth.SpawnArgsthat the kernel still copies, and would change every entry point's stack layout.One tradeoff: the text sits inside the opaque environment bytes the kernel keeps for
SYS_GET_ENV. The kernel never interprets those bytes, but they are not literally free of path text. Moving the environment out of the kernel is a separate question.Size
kernel/src:kernel/puregoes from 25,513 lines to 25,477. That completes the lines half of the file half's measurement.Checks and evidence
Evidence: https://github.com/ToyOSOrg/evidence/tree/e10645d67f35e7d754073b0f717f913cb5f9cc50/getcwd
The branch was rebuilt after review to reword one commit message.
926544f82and13e944b3bcarry exactly the trees of the measuredbaedeb48dand34c11dea7, so every result below still applies. Head0e98591f7changes only one guest-test comment and an issue record on top of them; that guest binary compiles with the harness's toolchain.cargo run -- --ci hostatbaedeb48dexited 0, 108 steps green. The earlier run on the first cut was red on one clippy lint (slow_vector_initializationinowner.rs), which is fixed in0b66e1691.sdk/toyos/src/files.rs:a_child_starts_where_its_spawn_says_and_nowhere_its_environment_saida_spawn_stating_no_directory_starts_its_child_at_the_roota_directory_no_child_can_read_back_is_never_statedmutate-keep-pwd.patchmakesstarting_inkeep an inheritedPWD. With it applied, the first test is red (exit 101; the child would read the inherited/elsewhere). After the restore it is green again.cargo run -- --build-onlyatbaedeb48dexited 0.34c11dea7, 9 of 9 green. They cover spawn and the launcher's directory on x86-64, plus aarch64, because the ABI and spawn are shared code:console_image_boots(every supervisor row is spawned with a directory),libc_children(posix_spawn),session_lifecycle,a_launch_gives_each_unsent_stdio_slot_a_null,a_row_reaches_its_own_state_and_no_other,a_spawn_from_an_image_frees_it_when_the_child_endsvirt_user_mode,virt_smp,virt_readonly_copyout34c11dea7: these are the only checks that a child starts in a directory other than/end to end, since no filtered QEMU row asserts it (the shared-boot binaries now run only on metal). The orchestrator ran proctreecase and testcases (rc=0 each). Judged offline with--metal-readback ... app_view std_fsat34c11dea7: exit 0,3 passed, 0 failed, 2 boot(s).app_viewpassed: the launched package reportedcwd=/home/toy/Games.std_fsandstd_fs_writeexited 0, including the new check, in which a child spawned withcurrent_dirunder an inheritedPWD=/systemprints its own directory.echobroken-pipe panic in that boot's log comes fromstd_fs's existingpipe_is_not_a_directory, which runs before the new check.mask_windowsreading is no comparison.Unresolved
mask_windowsboot is not that comparison. This change touches no masked or preemption-off path (it deletes a syscall arm and a field), so I expect no movement, but that is an inference.🤖 Generated with Claude Code