code wiki / _hdl_build / nx_buildroot_guard.nx

nx_buildroot_guard.nx source

↩ module page · 172 lines · 9100 B

1// nx_buildroot_guard.nx -- SELF-HEALING buildroot integrity (eats seq140: the recurring lib-drift that 2// breaks EVERY store-lib organ build when a sibling ships/reverts an OLD nx_seg_store.nx without ss_begin_cap). 3// Data-driven (rule 11): a manifest of <buildroot-lib-path> <required-symbol> <pinned-good-path> rows. The 4// drift signal is SEMANTIC (missing a required symbol = broken), NOT byte-equality -- so a legitimately-newer 5// lib that still has the symbol survives; only a BROKEN revert is healed. Fail-safe BY CONSTRUCTION: `pin` 6// refuses to snapshot a lib that lacks the symbol, and `heal` refuses to restore from a pin that lacks it 7// -- the guard can never make a build WORSE, only restore a known-good. 8// nx_buildroot_guard pin [manifest] (snapshot each currently-GOOD buildroot lib to its pinned-good path) 9// nx_buildroot_guard check [manifest] (JSON: per lib -- has_symbol, pinned_ok, drifted) 10// nx_buildroot_guard heal [manifest] (restore drifted libs from their pinned-good; JSON report) 11// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 12import "nx_syscalls.nx" 13 14const BG_CAP: i64 = 1048576 15const BG_TAB: i64 = 9 16const BG_NL: i64 = 10 17const BG_HASH: i64 = 35 18const BG_STDERR: i64 = 2 19const BG_MODE: i64 = 420 20const BG_SPAN: i64 = 16 21const BG_EXIT_USAGE: i64 = 2 22 23func bg_werr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(BG_STDERR, s, n); return 0 } 24func bg_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 25func bg_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o] = s[i]; o = o + 1; i = i + 1 } return o } 26func bg_catn(d: *u8, o: i64, v: i64) -> i64 { let t: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 } 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 { d[o] = t[k-1-i]; o = o + 1; i = i + 1 } return o } 27func bg_cat_esc(d: *u8, o: i64, q: *u8, s: i64, e: i64) -> i64 { var i: i64 = s; while i < e { var c: i64 = q[i] as i64; if c == 34 { c = 39 } if c == 92 { c = 47 } if c < 32 { c = 32 } d[o] = c as u8; o = o + 1; i = i + 1 } return o } 28// read a whole file into buf (capped). returns byte count, or -1 if open fails. 29func bg_read(path: *u8, buf: *u8, cap: i64) -> i64 { 30 let fd: i64 = sys_openat_rd(path) 31 if fd < 0 { return 0 - 1 } 32 var n: i64 = 0 33 var go: i64 = 1 34 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } } 35 sys_close(fd) 36 return n 37} 38// write buf[0..n) to path (O_TRUNC create). returns 0 ok, -1 fail. 39func bg_write(path: *u8, buf: *u8, n: i64) -> i64 { 40 let fd: i64 = sys_openat_wr(path, BG_MODE) 41 if fd < 0 { return 0 - 1 } 42 sys_write(fd, buf, n) 43 sys_close(fd) 44 return 0 45} 46// does buf[0..n) contain the NUL-terminated literal lit as a substring? 47func bg_contains(buf: *u8, n: i64, lit: *u8) -> i64 { 48 var ll: i64 = 0 49 while lit[ll] != (0 as u8) { ll = ll + 1 } 50 if ll == 0 { return 1 } 51 var i: i64 = 0 52 while i + ll <= n { 53 var j: i64 = 0 54 var ok: i64 = 1 55 while j < ll { if buf[i+j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } } 56 if ok == 1 { return 1 } 57 i = i + 1 58 } 59 return 0 60} 61func bg_le(q: *u8, i: i64, n: i64) -> i64 { var e: i64 = i; var s: i64 = 1; while s == 1 { if e >= n { s = 0 } else { if q[e] == (BG_NL as u8) { s = 0 } else { e = e + 1 } } } return e } 62func bg_col(q: *u8, ls: i64, le: i64, c: i64, out: *i64) -> i64 { 63 var col: i64 = 0 64 var p: i64 = ls 65 while col < c { 66 var s: i64 = 1 67 while s == 1 { if p >= le { return 0 } if q[p] == (BG_TAB as u8) { s = 0 } else { p = p + 1 } } 68 p = p + 1 69 col = col + 1 70 } 71 var e: i64 = p 72 var s2: i64 = 1 73 while s2 == 1 { if e >= le { s2 = 0 } else { if q[e] == (BG_TAB as u8) { s2 = 0 } else { e = e + 1 } } } 74 out[0] = p 75 out[1] = e 76 return 1 77} 78// copy span q[s..e) into dst as a NUL-terminated C string 79func bg_cstr(q: *u8, s: i64, e: i64, dst: *u8) -> i64 { var i: i64 = 0; while s + i < e { dst[i] = q[s+i]; i = i + 1 } dst[i] = 0 as u8; return i } 80func main(argc: i64, argv: *i64) -> i64 { 81 if argc < 2 { bg_werr("usage: nx_buildroot_guard {pin|check|heal} [manifest]\n" as *u8); sys_exit(BG_EXIT_USAGE); return BG_EXIT_USAGE } 82 let verb: *u8 = argv[1] as *u8 83 let vl: i64 = bg_vlen(verb) 84 var mpath: *u8 = "knowledge/registry/buildroot_libs.tsv" as *u8 85 if argc > 2 { mpath = argv[2] as *u8 } 86 var is_pin: i64 = 0 87 var is_check: i64 = 0 88 var is_heal: i64 = 0 89 if bg_vlen("pin" as *u8) == vl { if bg_contains(verb, vl, "pin" as *u8) == 1 { is_pin = 1 } } 90 if bg_vlen("check" as *u8) == vl { if bg_contains(verb, vl, "check" as *u8) == 1 { is_check = 1 } } 91 if bg_vlen("heal" as *u8) == vl { if bg_contains(verb, vl, "heal" as *u8) == 1 { is_heal = 1 } } 92 if is_pin == 0 { if is_check == 0 { if is_heal == 0 { bg_werr("PUT-FAIL unknown verb (pin|check|heal)\n" as *u8); sys_exit(BG_EXIT_USAGE); return BG_EXIT_USAGE } } } 93 let man: *u8 = sys_mmap(BG_CAP) 94 let mn: i64 = bg_read(mpath, man, BG_CAP) 95 if mn <= 0 { bg_werr("BG-FAIL manifest empty or unreadable\n" as *u8); sys_exit(1); return 1 } 96 let libbuf: *u8 = sys_mmap(BG_CAP) 97 let pinbuf: *u8 = sys_mmap(BG_CAP) 98 let libp: *u8 = sys_mmap(512) 99 let symp: *u8 = sys_mmap(512) 100 let pinp: *u8 = sys_mmap(512) 101 let c0: *i64 = sys_mmap(BG_SPAN) as *i64 102 let c1: *i64 = sys_mmap(BG_SPAN) as *i64 103 let c2: *i64 = sys_mmap(BG_SPAN) as *i64 104 let out: *u8 = sys_mmap(BG_CAP) 105 var o: i64 = 0 106 o = bg_cat(out, o, "{\"verb\":\"" as *u8) 107 o = bg_cat(out, o, verb) 108 o = bg_cat(out, o, "\",\"libs\":[" as *u8) 109 var total: i64 = 0 110 var acted: i64 = 0 111 var drifted: i64 = 0 112 var emitted: i64 = 0 113 var i: i64 = 0 114 while i < mn { 115 let le: i64 = bg_le(man, i, mn) 116 if le > i { if (man[i] as i64) != BG_HASH { 117 if bg_col(man, i, le, 0, c0) == 1 { if bg_col(man, i, le, 1, c1) == 1 { if bg_col(man, i, le, 2, c2) == 1 { 118 bg_cstr(man, c0[0], c0[1], libp) 119 bg_cstr(man, c1[0], c1[1], symp) 120 bg_cstr(man, c2[0], c2[1], pinp) 121 total = total + 1 122 let ln: i64 = bg_read(libp, libbuf, BG_CAP) 123 var has: i64 = 0 124 if ln > 0 { if bg_contains(libbuf, ln, symp) == 1 { has = 1 } } 125 var action: *u8 = "none" as *u8 126 if is_pin == 1 { 127 // fail-safe: only pin a lib that currently HAS the symbol (never snapshot a broken one) 128 if has == 1 { if bg_write(pinp, libbuf, ln) == 0 { action = "pinned" as *u8; acted = acted + 1 } } else { action = "skip-broken-not-pinned" as *u8 } 129 } 130 if is_heal == 1 { 131 if has == 0 { 132 drifted = drifted + 1 133 let pn: i64 = bg_read(pinp, pinbuf, BG_CAP) 134 var pin_ok: i64 = 0 135 if pn > 0 { if bg_contains(pinbuf, pn, symp) == 1 { pin_ok = 1 } } 136 // fail-safe: restore ONLY from a pin that itself has the symbol 137 if pin_ok == 1 { if bg_write(libp, pinbuf, pn) == 0 { action = "healed-restored" as *u8; acted = acted + 1 } } else { action = "DRIFTED-no-good-pin" as *u8 } 138 } else { action = "ok" as *u8 } 139 } 140 if is_check == 1 { 141 if has == 0 { drifted = drifted + 1; action = "DRIFTED" as *u8 } else { action = "ok" as *u8 } 142 } 143 if emitted > 0 { o = bg_cat(out, o, "," as *u8) } 144 o = bg_cat(out, o, "{\"lib\":\"" as *u8) 145 o = bg_cat_esc(out, o, man, c0[0], c0[1]) 146 o = bg_cat(out, o, "\",\"symbol\":\"" as *u8) 147 o = bg_cat_esc(out, o, man, c1[0], c1[1]) 148 o = bg_cat(out, o, "\",\"has_symbol\":" as *u8) 149 o = bg_catn(out, o, has) 150 o = bg_cat(out, o, ",\"bytes\":" as *u8) 151 if ln < 0 { o = bg_cat(out, o, "-1" as *u8) } else { o = bg_catn(out, o, ln) } 152 o = bg_cat(out, o, ",\"action\":\"" as *u8) 153 o = bg_cat(out, o, action) 154 o = bg_cat(out, o, "\"}" as *u8) 155 emitted = emitted + 1 156 } } } 157 } } 158 i = le + 1 159 } 160 o = bg_cat(out, o, "],\"total\":" as *u8) 161 o = bg_catn(out, o, total) 162 o = bg_cat(out, o, ",\"acted\":" as *u8) 163 o = bg_catn(out, o, acted) 164 o = bg_cat(out, o, ",\"drifted\":" as *u8) 165 o = bg_catn(out, o, drifted) 166 o = bg_cat(out, o, ",\"verdict\":\"" as *u8) 167 if drifted == 0 { o = bg_cat(out, o, "GREEN" as *u8) } else { if is_heal == 1 { o = bg_cat(out, o, "HEALED" as *u8) } else { o = bg_cat(out, o, "DRIFT-DETECTED" as *u8) } } 168 o = bg_cat(out, o, "\"}\n" as *u8) 169 sys_write(1, out, o) 170 sys_exit(0) 171 return 0 172}