code wiki / (root) / nx_read_file_gate.nx

nx_read_file_gate.nx

buildroot/runtime/nx_read_file_gate.nx

8121 B154 linesdepth 4pulls 6 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

about

nx_read_file_gate.nx -- referee for sys_read_file / sys_free_file, the estate's whole-file reader. WHY (debt 1787076780, measured 2026-08-17/19): for a file whose size is UNKNOWABLE (lseek END <= 0 -- /proc files, pipes, and every EMPTY regular file, which reports 0 just the same) the reader reserved 4 GiB of address space per call and the paired free could release only what was read. A daemon that read an empty registry every sweep ballooned its VmSize by 4 GiB per read; the leak screens flagged it. 2026-08-19 the size-unknowable path GROWS (64 KiB window, doubling, exact hand-back). These teeth pin: T1 a known-size file reads whole and byte-exact (the path the compiler itself uses -- unchanged) T2 an EMPTY regular file returns a non-NULL buffer with len 0 (present-and-empty is not absent) T3 THE BITE: reading + freeing an empty file 32 times moves VmSize by < 1 MiB (the old reader grew by 4 GiB per read -- 128 GiB here -- and could not shrink back) T4 a size-unknowable /proc file reads whole (procs_blocked, the LAST line of /proc/stat, is present) T5 a size-unknowable file LARGER than the first window (/proc/kallsyms, MBs) reads whole through the doubling path -- precondition: readable on this kernel; SKIP otherwise, never RED T6 sys_free_file on the exact mapping returns 0 (munmap success) and an absent path returns NULL/0 T7 neg-control: the free of NULL is a no-op (returns 0, never a crash) license_tier: ORIGINAL expect_exit: 0

dependencies 2 imports · 0 importers

nx_gate_verdict.nx nx_resmon_lib.nx nx_read_file_gate.nx

imports: nx_gate_verdict.nxnx_resmon_lib.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main gv_ctr sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_head gv_puts sys_write ↻ rf_write_known gv_need gv_puts ↻ gv_check gv_puts ↻ rf_vmsize_kb rm_read sys_openat_rd sys_read sys_close rm_field rm_slen gv_puts ↻ gv_num sys_mmap ↻ sys_write ↻ sys_munmap rf_contains rf_slen gv_verdict

structs

none

consts

21const RF_FIX_DIR: *u8 = "/tmp/nx_read_file_gate"
22const RF_FIX_EMPTY: *u8 = "/tmp/nx_read_file_gate/empty.bin"
23const RF_FIX_KNOWN: *u8 = "/tmp/nx_read_file_gate/known.bin"
24const RF_FIX_ABSENT: *u8 = "/tmp/nx_read_file_gate/does-not-exist.bin"
25const RF_KNOWN_BYTES: i64 = 100003 // odd, past a page and past any arena cell: the known-size path
26const RF_EMPTY_ROUNDS: i64 = 32 // 32 x 4 GiB would be 128 GiB under the old reader
27const RF_VMSIZE_TOL_KB: i64 = 1024 // 1 MiB of VmSize drift tolerated across the 32 rounds (arena cells, page rounding)
28const RF_STATUS_CAP: i64 = 8192
29const RF_PROC_STAT: *u8 = "/proc/stat"
30const RF_PROC_BIG: *u8 = "/proc/kallsyms"
31const RF_MODE_0644: i64 = 420

functions

33func rf_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
called by 1: rf_contains
34func rf_vmsize_kb() -> i64
called by 1: main calls 2: rm_readrm_field
40func rf_contains(buf: *u8, n: i64, pat: *u8) -> i64
called by 1: main calls 1: rf_slen
52func rf_write_known() -> i64
called by 1: main
64func main(argc: i64, argv: *i64) -> i64