code wiki / _hdl_build / _bs_poison.nx
_bs_poison.nx source
↩ module page · 112 lines · 5055 B
1// _bs_poison.nx -- R1-T1-004 / X-CLEAN-002 the "next reproducer": try to make the LATENT nxasm
2// rc=6 uninit-read DETERMINISTIC by POISONING the child's inherited context. R1-T1-004 pinned the
3// class as parent-ctx x output-path (uninit-read in nxasm, value=parent-residue, relevance=path-slot)
4// but the trigger went latent (fresh /tmp, residue gone). This probe floods the nxasm child's
5// inherited ENVIRONMENT (the parent-controlled bytes that survive execve) with several poison
6// patterns x sizes, plus a 1MB poison scratch fill, and assembles ONE real .s to a genuinely
7// WRITABLE output path under each config. CONTROL = clean env (must rc=0). If ANY poison config
8// makes a WRITABLE path fail (rc!=0), the uninit-read picked up poison -> DETERMINISTIC TRIGGER
9// FOUND (then bisect nxasm). If all stay rc=0, the defect is not reachable via this vector
10// (strengthens latent/non-reproducible -> no-overclaim close). Pure diagnostic; NO nxasm edits.
11// license_tier: ORIGINAL
12import "nx_syscalls.nx"
13
14func bp_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
15func bp_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64=v; if m<0 {m=0-m}; let t: *u8 = sys_mmap(28); var k: i64=0; if m==0 {t[0]=48;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1}; var i: i64=0; while i<k {bb[i]=t[k-1-i]; i=i+1}; sys_write(1, bb, k); return 0 }
16
17// fork + execve + wait4 -> WEXITSTATUS (or 128+sig). Faithful copy of rg_run / sbr_run.
18func bp_run(path: *u8, argv: *i64, envp: *i64) -> i64 {
19 let pid: i64 = sys_fork()
20 if pid == 0 {
21 sys_execve(path, argv, envp)
22 sys_exit(127)
23 }
24 let st: *i64 = sys_mmap(16) as *i64
25 sys_wait4(pid, st, 0)
26 let sig: i64 = st[0] & 0x7f
27 if sig != 0 { return 128 + sig }
28 return (st[0] >> 8) & 0xff
29}
30
31func bp_try(asm_tool: *u8, spath: *u8, outpath: *u8, envp: *i64) -> i64 {
32 let aa: *i64 = sys_mmap(8 * 4) as *i64
33 aa[0] = asm_tool as i64; aa[1] = spath as i64; aa[2] = outpath as i64; aa[3] = 0
34 return bp_run(asm_tool, aa, envp)
35}
36
37// build an envp = [PATH, <count> poison vars of slen bytes filled with pattern, 0].
38func bp_poison_env(pattern: i64, count: i64, slen: i64) -> *i64 {
39 let envp: *i64 = sys_mmap(8 * (count + 2)) as *i64
40 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64
41 var e: i64 = 1
42 while e <= count {
43 let s: *u8 = sys_mmap(slen + 4)
44 s[0] = 90 as u8 // 'Z'
45 s[1] = 61 as u8 // '='
46 var i: i64 = 2
47 while i < slen { s[i] = pattern as u8; i = i + 1 }
48 s[slen] = 0 as u8
49 envp[e] = s as i64
50 e = e + 1
51 }
52 envp[count + 1] = 0
53 return envp
54}
55
56func main() -> i64 {
57 let asm_tool: *u8 = "_offc/nxasm_x86_main.elf" as *u8
58 let spath: *u8 = "/tmp/repro_in.s" as *u8 // a REAL .s (runner pre-builds it)
59 let validout: *u8 = "/tmp/_bs_out.elf" as *u8 // WRITABLE: rc must be 0 unless the uninit-read corrupts it
60
61 // 1MB poison scratch fill (the literal R1-T1-004 "fill parent w/ pattern pre-execve").
62 let scratch: *u8 = sys_mmap(1048576)
63 var z: i64 = 0
64 while z < 1048576 { scratch[z] = 0xAA as u8; z = z + 1 }
65
66 // CONTROL: clean env must assemble a writable path cleanly.
67 let clean: *i64 = sys_mmap(8 * 2) as *i64
68 clean[0] = "PATH=/usr/bin:/bin" as *u8 as i64; clean[1] = 0
69 let baseline: i64 = bp_try(asm_tool, spath, validout, clean)
70
71 // poison patterns x (count,slen) combos
72 let pats: *i64 = sys_mmap(8 * 4) as *i64
73 pats[0] = 0xAA; pats[1] = 0xFF; pats[2] = 0x2F; pats[3] = 0x41
74 let cnts: *i64 = sys_mmap(8 * 3) as *i64
75 cnts[0] = 64; cnts[1] = 200; cnts[2] = 8
76 let lens: *i64 = sys_mmap(8 * 3) as *i64
77 lens[0] = 512; lens[1] = 256; lens[2] = 4000
78
79 var configs: i64 = 0
80 var reproduced: i64 = 0
81 var hit_pat: i64 = 0
82 var hit_rc: i64 = 0
83
84 var pi: i64 = 0
85 while pi < 4 {
86 var ci: i64 = 0
87 while ci < 3 {
88 // re-poison the scratch right before the spawn
89 var zz: i64 = 0
90 while zz < 1048576 { scratch[zz] = pats[pi] as u8; zz = zz + 1 }
91 let envp: *i64 = bp_poison_env(pats[pi], cnts[ci], lens[ci])
92 let rc: i64 = bp_try(asm_tool, spath, validout, envp)
93 configs = configs + 1
94 if rc != 0 { reproduced = 1; hit_pat = pats[pi]; hit_rc = rc }
95 ci = ci + 1
96 }
97 pi = pi + 1
98 }
99
100 bp_puts("BSPOISON baseline_rc=" as *u8); bp_putn(baseline)
101 bp_puts(" configs=" as *u8); bp_putn(configs)
102 bp_puts(" reproduced=" as *u8); bp_putn(reproduced)
103 bp_puts(" hit_pat=" as *u8); bp_putn(hit_pat)
104 bp_puts(" hit_rc=" as *u8); bp_putn(hit_rc)
105
106 // probe is VALID (sound experiment) iff the clean control assembled (rc=0) and configs were swept.
107 var valid: i64 = 0
108 if baseline == 0 { if configs > 0 { valid = 1 } }
109 if valid == 1 { bp_puts(" verdict=GREEN\n" as *u8); return 0 }
110 bp_puts(" verdict=RED\n" as *u8)
111 return 1
112}