code wiki / (root) / nx_ownership.nx

nx_ownership.nx

buildroot/runtime/nx_ownership.nx

3083 B56 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tooltopic ownership
docsdependenciesstructsconstsfunctions

about

nx_ownership.nx -- LN4 + LN5 OWNERSHIP fixture organ (lang.plan rungs LN4 own_check_move and LN5 own_check_uaf; /compare/lang rows "Memory safety (bounds, ownership, use-after-free)" and "Use-after-free prevented (CWE-416 class)"). THE HAZARD, twice, in the two functions that ARE the watch symbols. Under the default build both compile clean AND RUN EXIT 0 -- and the second one is the whole argument for this rung, because it is right for a reason nobody wrote down: sys_munmap's body is `if len <= NXA_SMALL_MAX { return 0 }` (nx_syscalls.nx:294, NXA_SMALL_MAX = 256), so releasing 64 bytes is a NO-OP in the bump arena and the read afterwards happens to find its own data still there. Change the constant, or the size, or the allocator, and the same source is a SIGSEGV. THAT is what "the arena no-free doctrine mitigates in practice" actually means, and it is why a doctrine is not a guarantee. Under `--ownership` the compiler REFUSES both, naming the local, the line that ended its life, and which of the two rules fired (capability=own-check-move / capability=own-check-uaf). Siblings: nx_ownership_ok.nx is the POSITIVE CONTROL (every accept idiom, must still compile AND run under the mode -- a deny-everything checker fails there, not here); nx_ownership_alias.nx is the alias-sweep witness; nx_ownership_dfree.nx is the double-free witness. license_tier: ORIGINAL No hw writes (Rule 26).

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_ownership.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

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

main own_check_move 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 ↻ own_check_uaf sys_mmap ↻ sys_munmap

structs

none

consts

25const OWN_FIX_BYTES: i64 = 64
26const OWN_FIX_MARK: i64 = 41

functions

33func own_check_move(seed: i64) -> i64
called by 1: main calls 1: sys_mmap
43func own_check_uaf(seed: i64) -> i64
called by 1: main calls 2: sys_mmapsys_munmap
50func main(argc: i64, argv: *i64) -> i64