code wiki / (root) / nx_tools_api_exec_gate.nx

nx_tools_api_exec_gate.nx source

↩ module page · 283 lines · 18365 B

1// nx_tools_api_exec_gate.nx -- GATE for R2: the /mcp tools/call STUB is now REAL execution. Drives the live 2// pure router ta_handle_pfx IN-PROCESS (no socket) and proves, end-to-end, that a capability-authorized 3// tools/call for a GREEN-allowlisted tool actually FORKS the organ and returns its real stdout -- with the 4// two never-brick negative controls that make this safe: (T2) no capability -> JSON-RPC -32001 (nothing 5// runs), (T3) a valid capability for a tool that is NOT on the GREEN execution allowlist -> tool-level error, 6// NOT executed. Composes R0 (nx_tool_run) + R1 (nx_tool_exec_allow) + the cap-token ocap layer. 7// 8// PREREQ: build nx_tool_ping FIRST (produces _offc/nx_tool_ping.elf, the allowlisted target). This gate 9// writes the real allowlist file (tool_allowlist.conf) in the server CWD, since ta_mcp_call resolves through 10// the production TEA_CONF path -- proving the ACTUAL wired path, not a test shim. 11// license_tier: ORIGINAL expect_exit: 0 12import "nx_tools_api.nx" // ta_handle_pfx + tea_* + capt_* (transitive) + sys_* 13import "nx_gate.nx" // gw / gn 14 15const EG_CONF: *u8 = "tool_allowlist.conf" as *u8 16const EG_PINGELF: *u8 = "_offc/nx_tool_ping.elf" as *u8 17 18func eg_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ d[o+i]=s[i]; i=i+1 } return o+i } 19func eg_catb(d: *u8, o: i64, s: *u8, n: i64) -> i64 { var i: i64=0; while i<n { d[o+i]=s[i]; i=i+1 } return o+n } 20func eg_has(out: *u8, n: i64, needle: *u8) -> i64 { if ta_indexof(out, n, needle) >= 0 { return 1 } return 0 } 21func eg_write_file(path: *u8, content: *u8) -> i64 { 22 let fd: i64 = __syscall(257, 0 - 100, path, 0x241, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_TRUNC, 0644 23 if fd < 0 { return 0 - 1 } 24 var n: i64 = 0; while content[n] != (0 as u8) { n = n + 1 } 25 sys_write(fd, content, n); sys_close(fd) 26 return 0 27} 28 29// write exactly n bytes (eg_write_file is NUL-terminated; the allowlist snapshot is arbitrary bytes). 30func eg_write_file_n(path: *u8, content: *u8, n: i64) -> i64 { 31 let fd: i64 = __syscall(257, 0 - 100, path, 0x241, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_TRUNC, 0644 32 if fd < 0 { return 0 - 1 } 33 sys_write(fd, content, n); sys_close(fd) 34 return 0 35} 36 37// write "ping\t_offc/nx_tool_ping.elf\tGREEN\n" (+ a blocked row + a comment) to the real allowlist file. 38func eg_write_conf() -> i64 { 39 let fd: i64 = __syscall(257, 0 - 100, EG_CONF, 0x241, 0x1a4, 0, 0) // O_WRONLY|O_CREAT|O_TRUNC, 0644 40 if fd < 0 { return 0 - 1 } 41 let body: *u8 = "# nx execution allowlist (written by nx_tools_api_exec_gate)\nping\t_offc/nx_tool_ping.elf\tGREEN\nargecho\t_offc/nx_tool_argecho.elf\tGREEN\nnx_http_probe\t_offc/nx_http_probe.elf\tRED\n" as *u8 42 var n: i64 = 0; while body[n]!=(0 as u8){n=n+1} 43 sys_write(fd, body, n); sys_close(fd) 44 return 0 45} 46 47// build a POST /mcp tools/call request with params.name = `tool` and params._cap = `tok` (tlen bytes). Returns len. 48func eg_build_call(req: *u8, tool: *u8, tok: *u8, tlen: i64) -> i64 { 49 var o: i64 = eg_cat(req, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\n\r\n" as *u8) 50 o = eg_cat(req, o, "{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"tools/call\",\"params\":{\"name\":\"" as *u8) 51 o = eg_cat(req, o, tool) 52 o = eg_cat(req, o, "\",\"_cap\":\"" as *u8) 53 o = eg_catb(req, o, tok, tlen) 54 o = eg_cat(req, o, "\"}}" as *u8) 55 return o 56} 57 58// like eg_build_call but adds params.arguments.argv = `argvj` (a JSON string-array literal), to drive the 59// multi-arg tools/call path (params.arguments.argv -> native argv -> child). 60func eg_build_call_argv(req: *u8, tool: *u8, tok: *u8, tlen: i64, argvj: *u8) -> i64 { 61 var o: i64 = eg_cat(req, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\n\r\n" as *u8) 62 o = eg_cat(req, o, "{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"tools/call\",\"params\":{\"name\":\"" as *u8) 63 o = eg_cat(req, o, tool) 64 o = eg_cat(req, o, "\",\"_cap\":\"" as *u8) 65 o = eg_catb(req, o, tok, tlen) 66 o = eg_cat(req, o, "\",\"arguments\":{\"argv\":" as *u8) 67 o = eg_cat(req, o, argvj) 68 o = eg_cat(req, o, "}}}" as *u8) 69 return o 70} 71 72// like eg_build_call but presents the cap via the OAuth `Authorization: Bearer <cap>` HEADER (no _cap/X-Nishi-Cap) -- 73// exercises the stock-MCP-client interop path. 74func eg_build_call_bearer(req: *u8, tool: *u8, tok: *u8, tlen: i64) -> i64 { 75 var o: i64 = eg_cat(req, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\nAuthorization: Bearer " as *u8) 76 o = eg_catb(req, o, tok, tlen) 77 o = eg_cat(req, o, "\r\n\r\n" as *u8) 78 o = eg_cat(req, o, "{\"jsonrpc\":\"2.0\",\"id\":7,\"method\":\"tools/call\",\"params\":{\"name\":\"" as *u8) 79 o = eg_cat(req, o, tool) 80 o = eg_cat(req, o, "\"}}" as *u8) 81 return o 82} 83 84func main() -> i64 { 85 gw("=== nx_tools_api_exec_gate (R2: /mcp tools/call is REAL execution, cap+allowlist gated) ===\n" as *u8) 86 // NEVER-BRICK GUARD (2026-08-19): this gate O_TRUNCs tool_allowlist.conf in its CWD. Run with 87 // CWD=nishihost, its 4-row fixture REPLACED the production execution allowlist at 13:38 and every 88 // MCP tool refused for 2h20m (the 2026-08-06 nx_cap_grant_e2e_gate incident repeated, by a runner 89 // that does not consume knowledge/gate_effectful.conf). This gate REQUIRES an unprovisioned 90 // scratch CWD BY ITS OWN DESIGN -- T5 asserts insecure_placeholder -- so a real 91 // tools_cap_secret.key in the CWD is mechanical proof of a production misrun: REFUSE. 92 let kchk: i64 = sys_openat_rd("tools_cap_secret.key" as *u8) 93 if kchk >= 0 { 94 sys_close(kchk) 95 gw("TOOLS-API-EXEC REFUSED effectful-in-production: CWD holds a real tools_cap_secret.key and this gate overwrites tool_allowlist.conf. Run it from a scratch CWD (/tmp/<gate>/ with _offc/nx_tool_ping.elf + _offc/nx_tool_argecho.elf copied in). exit 3 = SKIP, not a verdict\n" as *u8) 96 sys_exit(3); return 3 97 } 98 // SNAPSHOT the allowlist about to be overwritten; RESTORED at the verdict exits below 99 // (idempotent-gate law: the fixture must not outlive the gate). 100 let egsz: *i64 = sys_mmap(16) as *i64 101 let egsnap: *u8 = sys_read_file(EG_CONF, egsz) 102 let TP: *u8 = "knowledge/toolreg-test-exec-" as *u8 103 tool_register_pfx(TP, "ping" as *u8, "no-op smoke-test organ" as *u8, "ping" as *u8, "gate-proven" as *u8) 104 tool_register_pfx(TP, "nx_http_probe" as *u8, "sovereign HTTP GET probe" as *u8, "nx_http_probe <path>" as *u8, "gate-proven" as *u8) 105 tool_register_pfx(TP, "argecho" as *u8, "multi-arg witness organ (echoes argv[1..])" as *u8, "argecho <args...>" as *u8, "gate-proven" as *u8) 106 if eg_write_conf() != 0 { gw("FAIL: could not write tool_allowlist.conf\n" as *u8); sys_exit(1); return 1 } 107 108 let secret: *u8 = TA_CAP_SECRET 109 let slen: i64 = ta_slen(TA_CAP_SECRET) 110 let now: i64 = sys_now_realtime_sec() 111 let exp: i64 = now + 3600 112 let out: *u8 = sys_mmap(1048576) 113 let req: *u8 = sys_mmap(4096) 114 let tok: *u8 = sys_mmap(1024) 115 116 var pass: i64 = 0 117 var tot: i64 = 0 118 119 // T1: valid cap for "ping" + ping is GREEN-allowlisted -> EXECUTES, real stdout returned, isError:false 120 tot = tot + 1 121 let tl1: i64 = capt_issue(secret, slen, "ping" as *u8, 4, exp, 1001, tok, 1024) 122 let rn1: i64 = eg_build_call(req, "ping" as *u8, tok, tl1) 123 let on1: i64 = ta_handle_pfx(TP, req, rn1, out) 124 var t1: i64 = 0 125 if eg_has(out, on1, "NX_TOOL_PING_OK" as *u8) == 1 { if eg_has(out, on1, "\"isError\":false" as *u8) == 1 { if eg_has(out, on1, "\"exit_code\":0" as *u8) == 1 { t1 = 1 } } } 126 if t1 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 127 gw("T1 cap-authorized + GREEN-allowlisted 'ping' -> real fork+capture: 'NX_TOOL_PING_OK', exit_code 0\n" as *u8) 128 129 // T2 NEG (no ambient authority): tools/call WITHOUT any capability -> -32001, nothing executed 130 tot = tot + 1 131 var o2: i64 = eg_cat(req, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 132 o2 = eg_cat(req, o2, "{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"tools/call\",\"params\":{\"name\":\"ping\"}}" as *u8) 133 let on2: i64 = ta_handle_pfx(TP, req, o2, out) 134 var t2: i64 = 0 135 if eg_has(out, on2, "-32001" as *u8) == 1 { if eg_has(out, on2, "NX_TOOL_PING_OK" as *u8) == 0 { t2 = 1 } } 136 if t2 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 137 gw("T2 no capability -> -32001, organ NOT executed (no ambient authority)\n" as *u8) 138 139 // T3 NEG (fail-closed allowlist): valid cap for 'nx_http_probe' but its row is RED -> tool error, not run 140 tot = tot + 1 141 let tl3: i64 = capt_issue(secret, slen, "nx_http_probe" as *u8, 13, exp, 1003, tok, 1024) 142 let rn3: i64 = eg_build_call(req, "nx_http_probe" as *u8, tok, tl3) 143 let on3: i64 = ta_handle_pfx(TP, req, rn3, out) 144 var t3: i64 = 0 145 if eg_has(out, on3, "not on the GREEN execution allowlist" as *u8) == 1 { if eg_has(out, on3, "\"isError\":true" as *u8) == 1 { t3 = 1 } } 146 if t3 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 147 gw("T3 cap-valid but non-GREEN allowlist row -> tool error, NOT executed (defense in depth)\n" as *u8) 148 149 // T4: MULTI-ARG tools/call -- params.arguments.argv is parsed into a native argv and delivered to the child 150 // as real argv[1..]. Proves the FULL arg-passing path end-to-end: parse -> cap-verify -> tea_run_argv -> 151 // resolve -> fork+execve(argecho, [path,alpha,bravo,charlie]) -> child echoes them -> captured. This is the 152 // exceed that makes multi-arg organs (e.g. nx_mgmt_client <url> call GET <path> <tok>) callable over MCP. 153 tot = tot + 1 154 let tl4: i64 = capt_issue(secret, slen, "argecho" as *u8, 7, exp, 1004, tok, 1024) 155 let rn4: i64 = eg_build_call_argv(req, "argecho" as *u8, tok, tl4, "[\"alpha\",\"bravo\",\"charlie\"]" as *u8) 156 let on4: i64 = ta_handle_pfx(TP, req, rn4, out) 157 var t4: i64 = 0 158 if eg_has(out, on4, "NX_TOOL_ARGECHO_OK" as *u8) == 1 { if eg_has(out, on4, "alpha" as *u8) == 1 { if eg_has(out, on4, "bravo" as *u8) == 1 { if eg_has(out, on4, "charlie" as *u8) == 1 { if eg_has(out, on4, "\"isError\":false" as *u8) == 1 { t4 = 1 } } } } } 159 if t4 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 160 gw("T4 multi-arg tools/call: params.arguments.argv -> child argv (alpha/bravo/charlie echoed) -- arg-passing exceed\n" as *u8) 161 162 // T5: GET /api/cap/status is PUBLIC (no cap) and honestly reports the INSECURE placeholder when no keyfile is 163 // provisioned (the gate CWD has none) -- the bootstrap self-check that prevents a blind mint against a stale key. 164 tot = tot + 1 165 let o5: i64 = eg_cat(req, 0, "GET /api/cap/status HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 166 let on5: i64 = ta_handle_pfx(TP, req, o5, out) 167 var t5: i64 = 0 168 if eg_has(out, on5, "200 OK" as *u8) == 1 { if eg_has(out, on5, "insecure_placeholder" as *u8) == 1 { if eg_has(out, on5, "\"secure\":false" as *u8) == 1 { t5 = 1 } } } 169 if t5 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 170 gw("T5 GET /api/cap/status (public) honestly reports insecure_placeholder when no keyfile is provisioned\n" as *u8) 171 172 // T6: ta_cap_provisioned detection -- real keyfile -> secure; absent OR a file literally holding the placeholder 173 // -> insecure. Proves the status readout flips correctly once nx_cap_keygen writes a real key on the server. 174 let KP: *u8 = "/tmp/eg_capkey.key" as *u8 175 __syscall(87, KP, 0, 0, 0, 0, 0) // ensure absent 176 tot = tot + 1 177 var t6: i64 = 0 178 if ta_cap_provisioned_from(KP) == 0 { 179 eg_write_file(KP, "a-real-256-bit-secret-not-the-placeholder-000000" as *u8) 180 if ta_cap_provisioned_from(KP) == 1 { 181 eg_write_file(KP, TA_CAP_SECRET) 182 if ta_cap_provisioned_from(KP) == 0 { t6 = 1 } 183 } 184 } 185 __syscall(87, KP, 0, 0, 0, 0, 0) // cleanup 186 if t6 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 187 gw("T6 ta_cap_provisioned: real keyfile -> secure; absent/placeholder-in-file -> insecure (status flips on provisioning)\n" as *u8) 188 189 // T7: OAuth 2.1 interop -- present the SAME ocap via `Authorization: Bearer <cap>` (not X-Nishi-Cap/_cap) -> EXECUTES. 190 tot = tot + 1 191 let tl7: i64 = capt_issue(secret, slen, "ping" as *u8, 4, exp, 1007, tok, 1024) 192 let rn7: i64 = eg_build_call_bearer(req, "ping" as *u8, tok, tl7) 193 let on7: i64 = ta_handle_pfx(TP, req, rn7, out) 194 var t7: i64 = 0 195 if eg_has(out, on7, "NX_TOOL_PING_OK" as *u8) == 1 { if eg_has(out, on7, "\"isError\":false" as *u8) == 1 { t7 = 1 } } 196 if t7 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 197 gw("T7 OAuth Bearer: 'Authorization: Bearer <cap>' authorizes tools/call (stock-MCP-client interop)\n" as *u8) 198 199 // T8: RFC 9728 discovery -- GET /.well-known/oauth-protected-resource advertises bearer-in-header auth + the AS. 200 tot = tot + 1 201 let o8: i64 = eg_cat(req, 0, "GET /.well-known/oauth-protected-resource HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 202 let on8: i64 = ta_handle_pfx(TP, req, o8, out) 203 var t8: i64 = 0 204 if eg_has(out, on8, "200 OK" as *u8) == 1 { if eg_has(out, on8, "bearer_methods_supported" as *u8) == 1 { if eg_has(out, on8, "authorization_servers" as *u8) == 1 { t8 = 1 } } } 205 if t8 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 206 gw("T8 RFC9728 GET /.well-known/oauth-protected-resource advertises bearer-in-header auth\n" as *u8) 207 208 // T9 (R4 per-client consent): delegate a NARROWER cap WITH a client id -> attenuated cap + consent_recorded. 209 tot = tot + 1 210 let ptl: i64 = capt_issue(secret, slen, "ping,argecho" as *u8, 12, exp, 1009, tok, 1024) 211 var o9: i64 = eg_cat(req, 0, "POST /api/cap/issue HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\n\r\n" as *u8) 212 o9 = eg_cat(req, o9, "{\"_cap\":\"" as *u8) 213 o9 = eg_catb(req, o9, tok, ptl) 214 o9 = eg_cat(req, o9, "\",\"allow\":\"ping\",\"nonce\":42,\"client\":\"gate-test-client\"}" as *u8) 215 let on9: i64 = ta_handle_pfx(TP, req, o9, out) 216 var t9r: i64 = 0 217 if eg_has(out, on9, "\"consent_recorded\":true" as *u8) == 1 { if eg_has(out, on9, "\"cap\":\"" as *u8) == 1 { t9r = 1 } } 218 if t9r == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 219 gw("T9 R4 per-client consent: delegate w/ client id -> attenuated cap + consent_recorded\n" as *u8) 220 221 // T10 (R4): the append-only consent ledger records the client id (auditable). 222 tot = tot + 1 223 let o10: i64 = eg_cat(req, 0, "GET /api/cap/consent-log HTTP/1.1\r\nHost: x\r\n\r\n" as *u8) 224 let on10: i64 = ta_handle_pfx(TP, req, o10, out) 225 var t10: i64 = 0 226 if eg_has(out, on10, "gate-test-client" as *u8) == 1 { t10 = 1 } 227 if t10 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 228 gw("T10 R4 consent ledger: GET /api/cap/consent-log records the client id (auditable)\n" as *u8) 229 230 // T11 (rung 24): ASYNC JOB LANE -- "_async":"1" returns JOB-STARTED 231 // immediately; the detached worker lands .out then the ATOMIC .done 232 // marker (tmp+rename, written LAST); the echoed argv proves the worker 233 // ran the same cap+allowlist-gated pinned dispatch the sync lane runs. 234 tot = tot + 1 235 let tl11: i64 = capt_issue(secret, slen, "argecho" as *u8, 7, exp, 1011, tok, 1024) 236 var o11: i64 = eg_cat(req, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\nContent-Type: application/json\r\n\r\n" as *u8) 237 o11 = eg_cat(req, o11, "{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"tools/call\",\"params\":{\"name\":\"argecho\",\"_cap\":\"" as *u8) 238 o11 = eg_catb(req, o11, tok, tl11) 239 o11 = eg_cat(req, o11, "\",\"arguments\":{\"argv\":[\"async_alpha\",\"async_bravo\"],\"_async\":\"1\"}}}" as *u8) 240 let on11: i64 = ta_handle_pfx(TP, req, o11, out) 241 var t11: i64 = 0 242 if eg_has(out, on11, "JOB-STARTED id=" as *u8) == 1 { if eg_has(out, on11, "\"state\":\"RUNNING\"" as *u8) == 1 { 243 let idp: i64 = ta_indexof(out, on11, "JOB-STARTED id=" as *u8) + 15 244 let dpath: *u8 = sys_mmap(256) 245 let opath: *u8 = sys_mmap(256) 246 var dq: i64 = eg_cat(dpath, 0, "_jobs/job_" as *u8) 247 var oq: i64 = eg_cat(opath, 0, "_jobs/job_" as *u8) 248 var di: i64 = idp 249 var digo: i64 = 1 250 while digo == 1 { 251 let dc: i64 = out[di] as i64 252 if dc >= 48 { if dc <= 57 { dpath[dq] = out[di]; opath[oq] = out[di]; dq = dq + 1; oq = oq + 1; di = di + 1 } else { digo = 0 } } else { digo = 0 } 253 } 254 dq = eg_cat(dpath, dq, ".done" as *u8) 255 oq = eg_cat(opath, oq, ".out" as *u8) 256 dpath[dq] = 0 as u8 257 opath[oq] = 0 as u8 258 var polls: i64 = 0 259 var seen: i64 = 0 260 while polls < 100 { 261 let dfd: i64 = sys_openat_rd(dpath) 262 if dfd >= 0 { sys_close(dfd); seen = 1; polls = 100 } else { sys_sleep_ms(50); polls = polls + 1 } 263 } 264 if seen == 1 { 265 let dl: *i64 = sys_mmap(16) as *i64 266 let db2: *u8 = sys_read_file(dpath, dl) 267 let ol: *i64 = sys_mmap(16) as *i64 268 let ob2: *u8 = sys_read_file(opath, ol) 269 if eg_has(db2, dl[0], "exit=0" as *u8) == 1 { if eg_has(ob2, ol[0], "async_alpha" as *u8) == 1 { if eg_has(ob2, ol[0], "async_bravo" as *u8) == 1 { t11 = 1 } } } 270 } 271 __syscall(87, dpath, 0, 0, 0, 0, 0) 272 __syscall(87, opath, 0, 0, 0, 0, 0) 273 } } 274 if t11 == 1 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 275 gw("T11 async job: JOB-STARTED immediate, detached worker lands .out + atomic .done, argv echoed\n" as *u8) 276 277 gw("\n=== nx_tools_api_exec_gate " as *u8); gn(pass); gw("/" as *u8); gn(tot); gw(" ===\n" as *u8) 278 // RESTORE the pre-run allowlist (or remove the fixture if none existed) BEFORE the verdict: 279 // this exact fixture WAS the production allowlist for 2h20m on 2026-08-19. 280 if egsz[0] > 0 { eg_write_file_n(EG_CONF, egsnap, egsz[0]) } else { __syscall(87, EG_CONF, 0, 0, 0, 0, 0) } 281 if pass == tot { gw("TOOLS-API-EXEC GREEN -- /mcp tools/call now RUNS vetted organs and returns real output; the stub is gone, ocap + allowlist both enforced\n" as *u8); sys_exit(0); return 0 } 282 gw("TOOLS-API-EXEC RED\n" as *u8); sys_exit(1); return 1 283}