nx_scratch_gate.nx source
↩ module page · 122 lines · 5581 B
1// nx_scratch_gate.nx -- proves the sovereign scratch arena on the resource it exists to protect.
2//
3// Every tooth is designed so that a BROKEN arena fails it. T1 and T6 are a matched pair: T6 runs
4// the OLD idiom in this same process and REQUIRES it to grow, so if T1 reports "no growth" we know
5// that is the arena working and not the instrument being blind. A gate that cannot see the defect
6// cannot certify the fix.
7//
8// nx_scratch_gate -- 6 teeth, exit 0 = GREEN
9// license_tier: ORIGINAL layer: gate module: nishi-core.gate.scratch
10import "nx_scratch.nx"
11
12const SG_ITERS: i64 = 5000
13
14static SG_T: i64
15static SG_O: i64
16
17func sg_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
18func sg_n(v: i64) -> i64 {
19 if SG_T == 0 { SG_T = sys_mmap(64) as i64; SG_O = sys_mmap(64) as i64 }
20 let t: *u8 = SG_T as *u8
21 let o: *u8 = SG_O as *u8
22 var m: i64=v; var k: i64=0
23 if m==0 { t[0]=48 as u8; k=1 }
24 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
25 var i: i64=0; while i<k { o[i]=t[k-1-i]; i=i+1 }
26 sys_write(1,o,k); return 0
27}
28func sg_statm(buf: *u8) -> i64 {
29 let fd: i64 = sys_openat_rd("/proc/self/statm" as *u8)
30 if fd < 0 { return 0 - 1 }
31 let n: i64 = sys_read(fd, buf, 256)
32 sys_close(fd)
33 if n < 1 { return 0 - 1 }
34 var v: i64 = 0; var i: i64 = 0; var go: i64 = 1
35 while go == 1 {
36 if i >= n { go = 0 } else {
37 let c: i64 = buf[i] as i64
38 if c >= 48 { if c <= 57 { v = v*10 + (c-48); i = i + 1 } else { go = 0 } } else { go = 0 }
39 }
40 }
41 return v
42}
43
44func main(argc: i64, argv: *i64) -> i64 {
45 let sb: *u8 = sys_mmap(256)
46 var red: i64 = 0
47 nxs_init(NXS_CAP_DEFAULT)
48
49 // ---- T1: a full work iteration, repeated, must not grow the process ----
50 let base: i64 = sg_statm(sb)
51 if base < 0 { sg_p("[RED] /proc/self/statm unreadable -- instrument blind, refusing to certify\n" as *u8); sys_exit(1); return 1 }
52 var i: i64 = 0
53 while i < SG_ITERS {
54 nxs_reset()
55 let a: *u8 = nxs_alloc(128)
56 let b: *u8 = nxs_alloc(4096)
57 let c: *u8 = nxs_alloc(28)
58 a[0] = 65 as u8; b[0] = 66 as u8; c[0] = 67 as u8
59 i = i + 1
60 }
61 let after: i64 = sg_statm(sb)
62 let grow: i64 = after - base
63 sg_p("T1 "); sg_n(SG_ITERS); sg_p(" reset+3-alloc iterations must grow 0 pages: grew=" as *u8); sg_n(grow)
64 if grow == 0 { sg_p(" GREEN\n" as *u8) } else { sg_p(" [RED]\n" as *u8); red = red + 1 }
65
66 // ---- T2: 16-byte alignment on every hand-out ----
67 nxs_reset()
68 var bad_align: i64 = 0
69 var j: i64 = 0
70 while j < 200 {
71 let p: *u8 = nxs_alloc(j + 1)
72 if (p as i64) % NXS_ALIGN != 0 { bad_align = bad_align + 1 }
73 j = j + 1
74 }
75 sg_p("T2 every alloc 16-byte aligned: misaligned=" as *u8); sg_n(bad_align)
76 if bad_align == 0 { sg_p(" GREEN\n" as *u8) } else { sg_p(" [RED]\n" as *u8); red = red + 1 }
77
78 // ---- T3: distinct live allocations must not overlap ----
79 nxs_reset()
80 let p1: *u8 = nxs_alloc(64)
81 let p2: *u8 = nxs_alloc(64)
82 p1[0] = 11 as u8
83 p2[0] = 22 as u8
84 sg_p("T3 two live allocs distinct: p1[0]=" as *u8); sg_n(p1[0] as i64)
85 sg_p(" p2[0]=" as *u8); sg_n(p2[0] as i64)
86 if p1[0] == (11 as u8) { if p2[0] == (22 as u8) { if (p2 as i64) >= (p1 as i64) + 64 { sg_p(" GREEN\n" as *u8) } else { sg_p(" [RED] overlap\n" as *u8); red = red + 1 } } else { sg_p(" [RED] clobber\n" as *u8); red = red + 1 } } else { sg_p(" [RED] clobber\n" as *u8); red = red + 1 }
87
88 // ---- T4: reset must actually REUSE, not advance ----
89 nxs_reset()
90 let r1: *u8 = nxs_alloc(256)
91 nxs_reset()
92 let r2: *u8 = nxs_alloc(256)
93 sg_p("T4 reset reuses the same address: same=" as *u8)
94 if (r1 as i64) == (r2 as i64) { sg_p("1 GREEN\n" as *u8) } else { sg_p("0 [RED] reset did not rewind\n" as *u8); red = red + 1 }
95
96 // ---- T5: NEG-CONTROL. Overflow must FAIL SAFE -- usable memory, counted, never null ----
97 let ovf_before: i64 = nxs_overflows()
98 let big: *u8 = nxs_alloc(NXS_CAP_DEFAULT * 2)
99 var usable: i64 = 0
100 if (big as i64) != 0 { big[0] = 99 as u8; if big[0] == (99 as u8) { usable = 1 } }
101 let ovf_after: i64 = nxs_overflows()
102 sg_p("T5 NEG-CONTROL oversized request falls back usably: usable=" as *u8); sg_n(usable)
103 sg_p(" overflow_counted=" as *u8); sg_n(ovf_after - ovf_before)
104 if usable == 1 { if ovf_after == ovf_before + 1 { sg_p(" GREEN\n" as *u8) } else { sg_p(" [RED] not counted\n" as *u8); red = red + 1 } } else { sg_p(" [RED] returned unusable memory\n" as *u8); red = red + 1 }
105
106 // ---- T6: NEG-CONTROL. The OLD idiom must still visibly leak on this same instrument ----
107 let lb: i64 = sg_statm(sb)
108 var k2: i64 = 0
109 while k2 < 2000 { let junk: *u8 = sys_mmap(28); junk[0] = 1 as u8; k2 = k2 + 1 }
110 let la: i64 = sg_statm(sb)
111 let lgrow: i64 = la - lb
112 sg_p("T6 NEG-CONTROL old idiom must still grow >= 2000 pages: grew=" as *u8); sg_n(lgrow)
113 if lgrow >= 2000 { sg_p(" GREEN\n" as *u8) } else { sg_p(" [RED] instrument cannot see the defect it certifies against\n" as *u8); red = red + 1 }
114
115 sg_p("arena hwm_bytes=" as *u8); sg_n(nxs_hwm())
116 sg_p(" cap_bytes=" as *u8); sg_n(nxs_cap_bytes())
117 sg_p(" overflows=" as *u8); sg_n(nxs_overflows()); sg_p("\n" as *u8)
118
119 if red == 0 { sg_p("NX-SCRATCH-GATE 6/6 GREEN -- arena is correct, bounded, and fail-safe\n" as *u8); sys_exit(0); return 0 }
120 sg_p("NX-SCRATCH-GATE RED teeth=" as *u8); sg_n(red); sg_p("\n" as *u8)
121 sys_exit(1); return 1
122}