code wiki / _hdl_build / nx_acl.nx

nx_acl.nx source

↩ module page · 68 lines · 5177 B

1// nx_acl.nx -- GROUPS + ACLs (deepens AUTH-USERS beyond nx_users' owner/other model). POSIX-style: users have a 2// primary gid + supplementary group membership; resources carry owner-uid + owner-gid + 9 permission bits 3// (user rwx / group rwx / other rwx); an access check picks the right class. Sovereign, deterministic. 4// T1 owner gets the USER bits. T2 a group member gets the GROUP bits (r-x: read yes / write no). 5// T3 a non-member gets the OTHER bits. T4 teeth: a non-member is denied; group-write denied when group lacks w. 6// expect_exit: 0 Sovereign: nx_syscalls. NEVER-BRICK: userspace permission logic, 0 firmware. 7import "nx_syscalls.nx" 8import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 9import "nx_g_puts_lib.nx" 10 11// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 12// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 13// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 14// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 15func g_pn(v: i64) -> i64 { nxi_out(v); return 0 } 16func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c } 17 18const MAXG: i64 = 8 // max groups per user 19// is gid in user `u`'s group list? gmemb[u*MAXG..] terminated by -1. 20func in_group(gmemb: *i64, u: i64, gid: i64) -> i64 { var k: i64=0; while k<MAXG { let g: i64=gmemb[u*MAXG+k]; if g==(0-1) { return 0 } if g==gid { return 1 } k=k+1 } return 0 } 21// perm bits: user r=1<<8 w=1<<7 x=1<<6 | group r=1<<5 w=1<<4 x=1<<3 | other r=1<<2 w=1<<1 x=1<<0 22// pick the permission class for (uid,gid-list) on a resource(owner,ogid,perms); want: 2=read,1=write,0=exec(bit index within class) 23func acl_allow(gmemb: *i64, uid: i64, owner: i64, ogid: i64, perms: i64, wantbit: i64) -> i64 { 24 var shift: i64=0 // class base shift: other=0 25 if uid==owner { shift=6 } // user class 26 else { if in_group(gmemb, uid, ogid)==1 { shift=3 } } // group class 27 return (perms>>(shift+wantbit))&1 28} 29 30func main() -> i64 { 31 g_puts("nx_acl (GROUPS + ACLs: POSIX-style user/group/other permission classes)\n" as *u8) 32 var pass: i64=0; var total: i64=0 33 // users: alice uid1 groups{10}, bob uid2 groups{10,20}, carol uid3 groups{30} 34 let NU: i64=3 35 let gmemb: *i64 = sys_mmap(NU*MAXG*8) as *i64 36 var i: i64=0; while i<NU*MAXG { gmemb[i]=0-1; i=i+1 } 37 gmemb[1*MAXG+0]=10 // alice in g10 38 gmemb[2*MAXG+0]=10; gmemb[2*MAXG+1]=20 // bob in g10,g20 39 gmemb[3*MAXG+0]=30 // carol in g30 40 41 // resource owned by alice(uid1), group g10, perms rwx r-x --- = user(111) group(101) other(000) 42 // = (1<<8)|(1<<7)|(1<<6) | (1<<5)|(1<<3) = 0x1C0 | 0x28 = 0x1E8 43 let owner: i64=1; let ogid: i64=10; let perms: i64=0x1E8 44 // wantbit: read=2, write=1, exec=0 45 46 var t1: i64=0; if acl_allow(gmemb,1,owner,ogid,perms,2)==1 { if acl_allow(gmemb,1,owner,ogid,perms,1)==1 { if acl_allow(gmemb,1,owner,ogid,perms,0)==1 { t1=1 } } } 47 pass=pass+ck("T1: owner (alice) gets USER bits -- rwx all allowed" as *u8, t1); total=total+1 48 49 var t2: i64=0; if acl_allow(gmemb,2,owner,ogid,perms,2)==1 { if acl_allow(gmemb,2,owner,ogid,perms,1)==0 { if acl_allow(gmemb,2,owner,ogid,perms,0)==1 { t2=1 } } } 50 g_puts(" T2 bob (group g10): read="); g_pn(acl_allow(gmemb,2,owner,ogid,perms,2)); g_puts(" write="); g_pn(acl_allow(gmemb,2,owner,ogid,perms,1)); g_puts(" exec="); g_pn(acl_allow(gmemb,2,owner,ogid,perms,0)); g_puts("\n" as *u8) 51 pass=pass+ck("T2: a group member (bob in g10) gets GROUP bits (r-x: read yes, write NO, exec yes)" as *u8, t2); total=total+1 52 53 var t3: i64=0; if acl_allow(gmemb,3,owner,ogid,perms,2)==0 { if acl_allow(gmemb,3,owner,ogid,perms,1)==0 { t3=1 } } 54 g_puts(" T3 carol (not owner, not in g10): read="); g_pn(acl_allow(gmemb,3,owner,ogid,perms,2)); g_puts(" write="); g_pn(acl_allow(gmemb,3,owner,ogid,perms,1)); g_puts(" (other=000)\n" as *u8) 55 pass=pass+ck("T3: a non-member (carol) gets OTHER bits -- here --- (all denied)" as *u8, t3); total=total+1 56 57 var t4: i64=0; if acl_allow(gmemb,3,owner,ogid,perms,2)==0 { if acl_allow(gmemb,2,owner,ogid,perms,1)==0 { t4=1 } } 58 pass=pass+ck("T4 (teeth): non-member denied; group-write denied when the group class lacks w" as *u8, t4); total=total+1 59 60 var okall: i64=0; if pass==total { okall=1 } 61 g_puts("---- nx_acl: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8) 62 if okall==1 { 63 let logf: i64=sys_openat_append("knowledge/status/acl.log" as *u8, 420) 64 if logf>=0 { let z: i64=sys_write(logf,"NXACL GREEN: POSIX-style user/group/other ACLs -- owner=user bits, member=group bits, else other; teeth enforced\n" as *u8,109); sys_close(logf) } 65 g_puts("verdict=GREEN (groups + ACLs: POSIX-style user/group/other permission classes; deepens AUTH-USERS)\n" as *u8); sys_exit(0); return 0 66 } 67 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 68}