code wiki / (root) / nx_proc_ctl_rt.nx

nx_proc_ctl_rt.nx source

↩ module page · 61 lines · 3499 B

1// nx_proc_ctl.nx -- canonical sovereign process control: kill by FULL /proc/<pid>/cmdline. THE one true copy that 2// replaces (a) nx_proc_kill.nx's /proc/<pid>/comm match -- the 15-char-TRUNCATED field that silently matched nothing 3// for long names = the 2026-06-29 gallery-login disaster -- and (b) the buried-in-nx_hostctl hc_kill_by_cmdline. 4// IMPORTABLE (no main, no self-test). Matches "/"+name -> the binary PATH, never an arg mention (so it can't kill its 5// own command line); signal is a parameter (9=SIGKILL, 15=SIGTERM); returns the HONEST killed count (0 => nothing 6// matched => the op did nothing). Bounded reader (fixed reused buffers; no sys_read_file 4GiB-per-call leak). 7// license_tier: ORIGINAL 8import "nx_syscalls.nx" 9 10// 1 iff buf[0..n) contains "/" + name (NUL-term). "/path/name" matches; "restart name" (arg mention) does NOT. 11func nx_pctl_cmdl_has(buf: *u8, n: i64, name: *u8) -> i64 { 12 var nl: i64 = 0; while name[nl] != (0 as u8) { nl = nl + 1 } 13 if nl == 0 { return 0 } 14 var i: i64 = 0 15 while i + 1 + nl <= n { 16 if (buf[i] as i64) == 47 { 17 var j: i64 = 0; var ok: i64 = 1 18 while j < nl { if buf[i+1+j] != name[j] { ok = 0; j = nl } else { j = j + 1 } } 19 if ok == 1 { return 1 } 20 } 21 i = i + 1 22 } 23 return 0 24} 25 26// scan /proc and send signal `sig` to every process whose /proc/<pid>/cmdline contains "/"+name. Honest killed count. 27func nx_pctl_kill_by_cmdline(name: *u8, sig: i64) -> i64 { 28 let fd: i64 = sys_openat_rd("/proc" as *u8) 29 if fd < 0 { return 0 } 30 let self_pid: i64 = __syscall(172, 0, 0, 0, 0, 0, 0) // getpid (x86_64) -- a kill-by-cmdline must NEVER kill its caller // rv64 getpid=172 (was raw x86 39, which the backend translates to ioctl -- debt idx 2277) 31 let gbuf: *u8 = sys_mmap(65536); let path: *u8 = sys_mmap(256); let cmdl: *u8 = sys_mmap(8192) 32 var killed: i64 = 0; var go: i64 = 1 33 while go == 1 { 34 let n: i64 = sys_getdents64(fd, gbuf, 65536) 35 if n <= 0 { go = 0 } else { 36 var off: i64 = 0 37 while off < n { 38 let rec: *u8 = ((gbuf as i64) + off) as *u8 39 let reclen: i64 = dirent_reclen(rec) 40 let pname: *u8 = dirent_name(rec) 41 var pid: i64 = 0; var valid: i64 = 1; var di: i64 = 0 42 if pname[0] == (0 as u8) { valid = 0 } 43 while pname[di] != (0 as u8) { let c: i64 = pname[di] as i64; if c < 48 { valid = 0 } else { if c > 57 { valid = 0 } else { pid = pid*10 + (c-48) } } di = di + 1 } 44 if valid == 1 { if pid > 0 { if pid != self_pid { 45 var po: i64 = 0; let pf: *u8 = "/proc/" as *u8; while pf[po] != (0 as u8) { path[po]=pf[po]; po=po+1 } 46 var ni: i64 = 0; while pname[ni] != (0 as u8) { path[po]=pname[ni]; po=po+1; ni=ni+1 } 47 let sf: *u8 = "/cmdline" as *u8; var si: i64 = 0; while sf[si] != (0 as u8) { path[po]=sf[si]; po=po+1; si=si+1 } 48 path[po] = 0 as u8 49 let cfd: i64 = sys_openat_rd(path) 50 if cfd >= 0 { 51 let r: i64 = sys_read(cfd, cmdl, 8191); sys_close(cfd) 52 if r > 0 { if nx_pctl_cmdl_has(cmdl, r, name) == 1 { nx_kill(pid, sig); killed = killed + 1 } } 53 } 54 } } } 55 if reclen <= 0 { off = n } else { off = off + reclen } 56 } 57 } 58 } 59 sys_close(fd) 60 return killed 61}