git: 9front

Download patch

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;
--