code wiki / _hdl_build / nx_consol_apply_gate.nx

nx_consol_apply_gate.nx source

↩ module page · 120 lines · 6437 B

1// nx_consol_apply_gate.nx -- GATE for the gated consolidation applier (5 teeth, 2 neg-controls + 2// restore-verify). PREREQ: stage _offc/nx_consol_apply.elf + _offc/nx_fix_build.elf. Run from nxc2. 3// The mock build (nx_fix_build) reads /tmp/cab_input -> artifact, so the artifact DEPENDS on that file. 4// T1 SAFE: shadow is an UNRELATED file -> retire it -> build byte-identical -> CONSOLIDATED, shadow now 5// at retire-path, gone from origin. 6// T2 NEG (the never-brick tooth): shadow IS /tmp/cab_input (the file the build reads) -> retire -> build 7// output changes (content -> "MISSING") -> REFUSED, and the shadow is RESTORED at its origin. 8// T3 restore-verify: after T2, /tmp/cab_input exists again AND byte-equals the original (rollback sound). 9// T4 shadow-absent -> clean exit 2. 10// T5 idempotent origin: after T1, re-running with the (now-absent) origin shadow -> exit 2, no partial state. 11// Verdict exit 0 iff 5/5. license_tier: ORIGINAL No hw writes (Rule 26). 12import "nx_seat_drive_lib.nx" 13import "nx_seg_store.nx" 14import "nx_deploy_lib.nx" 15import "nx_syscalls.nx" 16 17func ag_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } return v } 18func ag_itoa(dst: *u8, v: i64) -> i64 { var m: i64 = v; let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; 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 { dst[i] = t[k - 1 - i]; i = i + 1 } dst[k] = 0 as u8; return k } 19func ag_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 20func ag_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd >= 0 { sys_close(fd); return 1 } return 0 } 21func ag_read(path: *u8, buf: *u8, cap: i64) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 } let n: i64 = sys_read(fd, buf, cap - 1); sys_close(fd); return n } 22 23// run applier: <shadow> <retire> _offc/nx_fix_build.elf <artifact> <artifact> (buildarg==artifact path) 24func ag_run(shadow: *u8, retire: *u8, artifact: *u8, outp: *u8) -> i64 { 25 let av: *i64 = sys_mmap(64) as *i64 26 av[0] = shadow as i64 27 av[1] = retire as i64 28 av[2] = "_offc/nx_fix_build.elf" as *u8 as i64 29 av[3] = artifact as i64 30 av[4] = artifact as i64 31 return dep_run_capture("_offc/nx_consol_apply.elf" as *u8, av, 5, outp) 32} 33 34func main(argc: i64, argv: *i64) -> i64 { 35 var stage: i64 = 1 36 var pass: i64 = 0 37 if argc >= 2 { let ss1: *u8 = argv[1] as *u8; stage = ag_atoi(ss1) } 38 if argc >= 3 { let ps: *u8 = argv[2] as *u8; pass = ag_atoi(ps) } 39 if stage < 1 { stage = 1 } 40 41 // the build's real input (present, stable) 42 let inp: *u8 = "the-canonical-input-bytes\n" as *u8 43 ss_writefile("/tmp/cab_input" as *u8, inp, ag_len(inp)) 44 45 if stage == 1 { 46 // SAFE: shadow is unrelated to the build 47 let sh: *u8 = "unrelated shadow content\n" as *u8 48 ss_writefile("/tmp/cab_shadow1" as *u8, sh, ag_len(sh)) 49 sys_unlinkat("/tmp/cab_retire1" as *u8) 50 let rc: i64 = ag_run("/tmp/cab_shadow1" as *u8, "/tmp/cab_retire1" as *u8, "/tmp/cab_art1" as *u8, "/tmp/ag_t1.out" as *u8) 51 var ok: i64 = 0 52 if rc == 0 { if ag_exists("/tmp/cab_shadow1" as *u8) == 0 { if ag_exists("/tmp/cab_retire1" as *u8) == 1 { ok = 1 } } } 53 if ok == 1 { sd_w("T1 safe-consolidated PASS\n" as *u8); pass = pass + 1 } else { sd_w("T1 safe-consolidated FAIL\n" as *u8) } 54 } 55 if stage == 2 { 56 // NEG never-brick: the shadow IS the build's input -> retiring changes output -> REFUSE+RESTORE 57 ss_writefile("/tmp/cab_input" as *u8, inp, ag_len(inp)) 58 sys_unlinkat("/tmp/cab_retire2" as *u8) 59 let rc: i64 = ag_run("/tmp/cab_input" as *u8, "/tmp/cab_retire2" as *u8, "/tmp/cab_art2" as *u8, "/tmp/ag_t2.out" as *u8) 60 let out: *u8 = sys_mmap(4096) 61 let n: i64 = dp_read("/tmp/ag_t2.out" as *u8, out, 4096) 62 var ok: i64 = 0 63 if rc == 1 { if sd_count(out, n, "verdict=REFUSED " as *u8) == 1 { ok = 1 } } 64 if ok == 1 { sd_w("T2 neg-live-shadow-refused PASS\n" as *u8); pass = pass + 1 } else { sd_w("T2 neg-live-shadow-refused FAIL\n" as *u8) } 65 } 66 if stage == 3 { 67 // restore-verify: /tmp/cab_input back + byte-equal original 68 var ok: i64 = 0 69 if ag_exists("/tmp/cab_input" as *u8) == 1 { 70 let b: *u8 = sys_mmap(4096) 71 let m: i64 = ag_read("/tmp/cab_input" as *u8, b, 4096) 72 if m == ag_len(inp) { 73 var same: i64 = 1 74 var i: i64 = 0 75 while i < m { if b[i] != inp[i] { same = 0; i = m } else { i = i + 1 } } 76 if same == 1 { ok = 1 } 77 } 78 } 79 if ok == 1 { sd_w("T3 restore-byte-exact PASS\n" as *u8); pass = pass + 1 } else { sd_w("T3 restore-byte-exact FAIL\n" as *u8) } 80 } 81 if stage == 4 { 82 sys_unlinkat("/tmp/cab_absent_sh" as *u8) 83 let rc: i64 = ag_run("/tmp/cab_absent_sh" as *u8, "/tmp/cab_retire4" as *u8, "/tmp/cab_art4" as *u8, "/tmp/ag_t4.out" as *u8) 84 if rc == 2 { sd_w("T4 shadow-absent-clean PASS\n" as *u8); pass = pass + 1 } else { sd_w("T4 shadow-absent-clean FAIL\n" as *u8) } 85 } 86 if stage == 5 { 87 // origin from T1 is gone -> re-run must exit 2, not partial 88 let rc: i64 = ag_run("/tmp/cab_shadow1" as *u8, "/tmp/cab_retire1b" as *u8, "/tmp/cab_art5" as *u8, "/tmp/ag_t5.out" as *u8) 89 if rc == 2 { sd_w("T5 idempotent-absent-origin PASS\n" as *u8); pass = pass + 1 } else { sd_w("T5 idempotent-absent-origin FAIL\n" as *u8) } 90 } 91 92 if stage >= 5 { 93 sd_w("NX-CONSOL-APPLY-GATE pass=" as *u8) 94 let pb: *u8 = sys_mmap(8) 95 pb[0] = (48 + pass) as u8 96 pb[1] = 0 as u8 97 sd_w(pb) 98 if pass == 5 { sd_w("/5 verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 99 sd_w("/5 verdict=RED\n" as *u8) 100 sys_exit(1) 101 return 1 102 } 103 104 let self: *u8 = argv[0] as *u8 105 let sb: *u8 = sys_mmap(24) 106 ag_itoa(sb, stage + 1) 107 let pb2b: *u8 = sys_mmap(24) 108 ag_itoa(pb2b, pass) 109 let nav: *i64 = sys_mmap(40) as *i64 110 nav[0] = self as i64 111 nav[1] = sb as i64 112 nav[2] = pb2b as i64 113 nav[3] = 0 114 let envp: *i64 = sys_mmap(16) as *i64 115 envp[0] = 0 116 sys_execve(self, nav, envp) 117 sd_w("AG-EXEC-FAIL\n" as *u8) 118 sys_exit(1) 119 return 1 120}