code wiki / (root) / nx_proc_ctl_cmdl.nx

nx_proc_ctl_cmdl.nx source

↩ module page · 67 lines · 3800 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" 9const K_MAGIC_65536: i64 = 65536 10const K_MAGIC_8192: i64 = 8192 11const K_MAGIC_8191: i64 = 8191 12 13// 1 iff buf[0..n) contains "/" + name (NUL-term). "/path/name" matches; "restart name" (arg mention) does NOT. 14func nx_pctl_cmdl_has(buf: *u8, n: i64, name: *u8) -> i64 { 15 var nl: i64 = 0; while name[nl] != (0 as u8) { nl = nl + 1 } 16 if nl == 0 { return 0 } 17 var i: i64 = 0 18 while i + 1 + nl <= n { 19 if (buf[i] as i64) == 47 { 20 var j: i64 = 0; var ok: i64 = 1 21 while j < nl { if buf[i+1+j] != name[j] { ok = 0; j = nl } else { j = j + 1 } } 22 if ok == 1 { return 1 } 23 } 24 i = i + 1 25 } 26 return 0 27} 28 29// scan /proc and send signal `sig` to every process whose /proc/<pid>/cmdline contains "/"+name. Honest killed count. 30func nx_pctl_kill_by_cmdline(name: *u8, sig: i64) -> i64 { 31 let fd: i64 = sys_openat_rd("/proc" as *u8) 32 if fd < 0 { return 0 } 33 let self_pid: i64 = __syscall(172, 0, 0, 0, 0, 0, 0) // getpid -- a kill-by-cmdline must NEVER kill its caller. 34 // rv64 getpid=172. This was raw x86 39, which IS an RV64 KEY (umount2) that the backend 35 // translated to ioctl(16), returning -ENOTTY. So self_pid was -25 and the self-exclusion 36 // comparison NEVER MATCHED -- this guard could kill its own caller (debt idx 2277). 37 let gbuf: *u8 = sys_mmap(K_MAGIC_65536); let path: *u8 = sys_mmap(256); let cmdl: *u8 = sys_mmap(K_MAGIC_8192) 38 var killed: i64 = 0; var go: i64 = 1 39 while go == 1 { 40 let n: i64 = sys_getdents64(fd, gbuf, K_MAGIC_65536) 41 if n <= 0 { go = 0 } else { 42 var off: i64 = 0 43 while off < n { 44 let rec: *u8 = ((gbuf as i64) + off) as *u8 45 let reclen: i64 = dirent_reclen(rec) 46 let pname: *u8 = dirent_name(rec) 47 var pid: i64 = 0; var valid: i64 = 1; var di: i64 = 0 48 if pname[0] == (0 as u8) { valid = 0 } 49 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 } 50 if valid == 1 { if pid > 0 { if pid != self_pid { 51 var po: i64 = 0; let pf: *u8 = "/proc/" as *u8; while pf[po] != (0 as u8) { path[po]=pf[po]; po=po+1 } 52 var ni: i64 = 0; while pname[ni] != (0 as u8) { path[po]=pname[ni]; po=po+1; ni=ni+1 } 53 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 } 54 path[po] = 0 as u8 55 let cfd: i64 = sys_openat_rd(path) 56 if cfd >= 0 { 57 let r: i64 = sys_read(cfd, cmdl, K_MAGIC_8191); sys_close(cfd) 58 if r > 0 { if nx_pctl_cmdl_has(cmdl, r, name) == 1 { nx_kill(pid, sig); killed = killed + 1 } } 59 } 60 } } } 61 if reclen <= 0 { off = n } else { off = off + reclen } 62 } 63 } 64 } 65 sys_close(fd) 66 return killed 67}