ref: c0fb4ee8004910b7b839acd104c8cc522ed6516b
parent: 7979093c548ad1521cfd742af7b1fd19654f7109
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Dec 1 18:20:54 EST 2025
kernel: refactor chdev(1) machinery As the "notallowed" bitmap is part of Pgrp, the code dealing with it should reside in pgrp.c as well. Rename Pgrp.notallowed[] to Pgrp.devmask[] and make it an array of uchar[]. This avoids the 8 * sizeof(pgrp->devmask[0]) for generating the shift counts. Change devallowed() to devmasked() to be symmetric with devmask(). Put functions in lexical order in portfns.h. Make devmasked() take a devtab index instead of device character, avoiding calling devno() twice and makes it applicable to be used in a loop (such as when reading #c/drivers). Simplify devmask(): Convert to bitmap and afterwards invert it while we copy into Pgrp->devmask[] under lock using xor. Move the inheritance logic into pgrpcpy() and do it under the ns lock. This way, a background forker will not inherit a partially changed devmask. This only impatcs rforking with CNAMEG flag.
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -1337,7 +1337,7 @@
up->genbuf[n] = '\0';
n = chartorune(&r, up->genbuf+1)+1;
t = devno(r);
- if(t == -1)
+ if(t < 0)
error(Ebadsharp);
/*
* When sandboxing, unmounting a sharp from a union is a valid
@@ -1346,7 +1346,7 @@
* about the existence of files.
*/
if((amode != Aunmount || up->genbuf[n] || *name)
- && !devallowed(up->pgrp, r))
+ && devmasked(up->pgrp, t))
error(Enoattach);
c = devtab[t]->attach(up->genbuf+n);
--- a/sys/src/9/port/dev.c
+++ b/sys/src/9/port/dev.c
@@ -28,63 +28,6 @@
}
void
-devmask(Pgrp *pgrp, int invert, char *devs)
-{- int i, t, w;
- char *p;
- Rune r;
- u64int mask[nelem(pgrp->notallowed)];
-
- if(invert)
- memset(mask, 0xFF, sizeof mask);
- else
- memset(mask, 0, sizeof mask);
-
- w = sizeof mask[0] * 8;
- for(p = devs; *p != '\0';){- p += chartorune(&r, p);
- t = devno(r);
- if(t == -1)
- continue;
- if(invert)
- mask[t/w] &= ~(1<<t%w);
- else
- mask[t/w] |= 1<<t%w;
- }
-
- wlock(&pgrp->ns);
- for(i=0; i < nelem(pgrp->notallowed); i++)
- pgrp->notallowed[i] |= mask[i];
- wunlock(&pgrp->ns);
-}
-
-int
-devallowed(Pgrp *pgrp, int r)
-{- int t, w, b;
-
- t = devno(r);
- if(t == -1)
- return 0;
-
- w = sizeof(u64int) * 8;
- rlock(&pgrp->ns);
- b = !(pgrp->notallowed[t/w] & 1<<t%w);
- runlock(&pgrp->ns);
- return b;
-}
-
-int
-canmount(Pgrp *pgrp)
-{- /*
- * Devmnt is not usable directly from user procs, so
- * having it removed is interpreted to block any mounts.
- */
- return devallowed(pgrp, 'M');
-}
-
-void
devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
{db->name = n;
--- a/sys/src/9/port/devcons.c
+++ b/sys/src/9/port/devcons.c
@@ -593,15 +593,12 @@
case Qdrivers:
b = smalloc(READSTR);
k = 0;
-
- rlock(&up->pgrp->ns);
for(i = 0; devtab[i] != nil; i++){- if(up->pgrp->notallowed[i/(sizeof(u64int)*8)] & 1<<i%(sizeof(u64int)*8))
+ if(devmasked(up->pgrp, i))
continue;
k += snprint(b+k, READSTR-k, "#%C %s\n",
devtab[i]->dc, devtab[i]->name);
}
- runlock(&up->pgrp->ns);
if(waserror()){free(b);
nexterror();
@@ -634,7 +631,6 @@
{char buf[256];
long l, bp;
- int invert;
char *a;
Mach *mp;
int id;
@@ -705,27 +701,21 @@
error(Ebadarg);
if(cb->nf == 1)
error(Ebadarg);
-
- invert = 1;
- a = "";
switch(cb->f[1][0]){case '&':
if(cb->nf != 3)
error(Ebadarg);
- a = cb->f[2];
- if(cb->f[1][1] == '~')
- invert--;
+ devmask(up->pgrp, cb->f[1][1] != '~', cb->f[2]);
break;
case '~':
if(cb->nf != 2)
error(Ebadarg);
+ devmask(up->pgrp, 1, "");
break;
default:
error(Ebadarg);
break;
}
-
- devmask(up->pgrp, invert, a);
poperror();
free(cb);
break;
--- a/sys/src/9/port/pgrp.c
+++ b/sys/src/9/port/pgrp.c
@@ -90,7 +90,7 @@
}
void
-pgrpcpy(Pgrp *to, Pgrp *from)
+pgrpcpy(Pgrp *to, Pgrp *from, int flag)
{Mount *n, *m, **link;
Mhead *f, **l, *mh;
@@ -103,6 +103,13 @@
wunlock(&to->ns);
nexterror();
}
+
+ /* always inherit devmask unconditionally */
+ memmove(to->devmask, from->devmask, sizeof from->devmask);
+
+ if((flag & RFNAMEG) == 0)
+ goto Done;
+
for(i = 0; i < MNTHASH; i++) {l = &to->mnthash[i];
for(f = from->mnthash[i]; f != nil; f = f->hash) {@@ -132,9 +139,51 @@
m->norder = nil;
pgrpinsert(to, n);
}
+Done:
wunlock(&from->ns);
wunlock(&to->ns);
poperror();
+}
+
+int
+canmount(Pgrp *pgrp)
+{+ /*
+ * Devmnt is not usable directly from user procs, so
+ * having it masked is interpreted to block any mounts.
+ */
+ return !devmasked(pgrp, devno('M'));+}
+
+int
+devmasked(Pgrp *pgrp, int i)
+{+ return (pgrp->devmask[i>>3] & 1<<(i&7)) != 0;
+}
+
+void
+devmask(Pgrp *pgrp, int invert, char *devs)
+{+ uchar mask[sizeof pgrp->devmask];
+ Rune r;
+ int i;
+
+ if(invert)
+ invert = 0xFF;
+
+ memset(mask, 0, sizeof mask);
+ while(*devs != '\0') {+ devs += chartorune(&r, devs);
+ i = devno(r);
+ if(i < 0)
+ continue;
+ mask[i>>3] |= 1<<(i&7);
+ }
+
+ wlock(&pgrp->ns);
+ for(i=0; i < sizeof mask; i++)
+ pgrp->devmask[i] |= mask[i] ^ invert;
+ wunlock(&pgrp->ns);
}
Fgrp*
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -512,7 +512,7 @@
{Ref;
RWLock ns; /* Namespace n read/one write lock */
- u64int notallowed[4]; /* Room for 256 devices */
+ uchar devmask[256/8]; /* Room for 256 devices */
Mount *mntorder; /* Ordered list of mounts */
Mount **mntordertail;
Mhead *mnthash[MNTHASH];
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -19,6 +19,7 @@
void callwithureg(void(*)(Ureg*));
char* chanpath(Chan*);
int canlock(Lock*);
+int canmount(Pgrp*);
int canpage(Proc*);
int canqlock(QLock*);
int canrlock(RWLock*);
@@ -71,6 +72,8 @@
long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen devgen;
void devinit(void);
+void devmask(Pgrp*, int, char*);
+int devmasked(Pgrp*, int);
int devno(int);
Chan* devopen(Chan*, int, Dirtab*, int, Devgen*);
void devpermcheck(char*, ulong, int);
@@ -244,7 +247,7 @@
void pathclose(Path*);
ulong perfticks(void);
_Noreturn void pexit(char*, int);
-void pgrpcpy(Pgrp*, Pgrp*);
+void pgrpcpy(Pgrp*, Pgrp*, int);
void pgrpinsert(Pgrp*, Mount *);
void pgrpremove(Pgrp*, Mount *);
ulong pidalloc(Proc*);
@@ -434,9 +437,6 @@
ushort nhgets(void*);
ulong µs(void);
long lcycles(void);
-void devmask(Pgrp*,int,char*);
-int devallowed(Pgrp*, int);
-int canmount(Pgrp*);
#pragma varargck argpos iprint 1
#pragma varargck argpos panic 1
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -91,10 +91,7 @@
/* Process group */
if(flag & (RFNAMEG|RFCNAMEG)) {up->pgrp = newpgrp();
- if(flag & RFNAMEG)
- pgrpcpy(up->pgrp, opg);
- /* inherit notallowed */
- memmove(up->pgrp->notallowed, opg->notallowed, sizeof up->pgrp->notallowed);
+ pgrpcpy(up->pgrp, opg, flag);
}
/* Rendezvous group */
@@ -218,10 +215,7 @@
/* Process groups */
if(flag & (RFNAMEG|RFCNAMEG)) {p->pgrp = newpgrp();
- if(flag & RFNAMEG)
- pgrpcpy(p->pgrp, up->pgrp);
- /* inherit notallowed */
- memmove(p->pgrp->notallowed, up->pgrp->notallowed, sizeof p->pgrp->notallowed);
+ pgrpcpy(p->pgrp, up->pgrp, flag);
}
else {p->pgrp = up->pgrp;
--
⑨