9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Jacob Moody <moody@mail.posixcafe.org>
To: 9front@9front.org
Subject: Re: [9front] [PATCH] Unmount to remove sharp devices.
Date: Wed, 25 May 2022 23:55:49 -0600	[thread overview]
Message-ID: <c57bac9f-ca9b-fb7c-7069-d76ea1aeb249@posixcafe.org> (raw)
In-Reply-To: <f1dfd9ef-faf2-6661-f58e-91e4b4b6f8ed@posixcafe.org>

Another iteration.
To state all of what this does:

A process can remove access to a driver through writing

chdev [ 0! ] devmask

to /dev/drivers. This is tied to the processes namegroup,
and is inherited on both RFCNAMEG and RFNAMEG. In order to provide
all the knobs RFNOMNT does, blocking 'M' is interpreted to block all mounting.

Support for this new operation has been added to namespace files,
along with a matching chdev(1). /lib/namespace.ftp has been updated
to use chdev.

aux/listen now allows individual namespace files to be used
per service. This namespace is sourced one per listener. Each
connection receives a copy of the namespace. A example
/rc/bin/service/!tcp80.namespace is provided which builds
an isolated webroot. In order to accomplish this without
bringing in most of /root, a /rc folder was added to #/.


thanks,
moody

----
diff 6fbb1acc8fa0b6655b14e8c46240a4a8d2d8c672 uncommitted
--- a/lib/namespace
+++ b/lib/namespace
@@ -22,6 +22,7 @@

 # standard bin
 bind /$cputype/bin /bin
+bind $rootdir'/rc' /rc
 bind -a /rc/bin /bin

 # internal networks
--- a/lib/namespace.ftp
+++ b/lib/namespace.ftp
@@ -8,5 +8,6 @@
 # bind a personal incoming directory below incoming
 bind -c /usr/none/incoming /usr/web/incoming/none

+chdev |MedIa/
 # this cuts off everything not mounted below /usr/web
 bind /usr/web /
--- /tmp/diff100000711164
+++ b/rc/bin/chdev
@@ -1,0 +1,3 @@
+#!/bin/rc
+
+echo chdev $* >> '#c/drivers'
--- /tmp/diff100000711167
+++ b/rc/bin/service/!tcp80.namespace
@@ -1,0 +1,24 @@
+mount -aC #s/boot /root $rootspec
+
+# kernel devices
+bind #c /dev
+bind #d /fd
+bind -c #e /env
+bind #p /proc
+bind -a #l /net
+bind -a #I /net
+
+bind /root/$cputype/bin /bin
+bind /root/rc /rc
+bind -a /rc/bin /bin
+
+chdev Mcde|pslI/
+
+# grab just our webroot
+bind /root/usr/web /srv
+
+# or bind in the actual root
+# bind -a /root /
+
+unmount /root
+chdev !Ms
--- /tmp/diff100000711170
+++ b/sys/man/1/chdev
@@ -1,0 +1,93 @@
+.TH CHDEV 1
+.SH NAME
+chdev \- change kernel driver access
+.SH SYNOPSIS
+.B chdev
+[ 0! ] \f2devmask\fP...
+.SH DESCRIPTION
+.I Chdev
+modifies access to kernel drivers for the current
+process and processes within the same name group
+(see
+.IR fork (2)).
+Access is defined as the ability for a process
+to walk files and directories served by the driver
+through its location within '#'. Existing binds
+of drivers are left unaffected.
+.PP
+Access may only be removed; after a specific
+driver is ejected no further operations can
+permit access again. Access is inherited by
+all children of the name group, regardless if the
+child has elected to receive a clean namespace.
+.PP
+.IR Devmask
+is a string of driver characters. The default
+behavior is to block access to all but the listed
+drivers. A prefix of '!' inverts this operation,
+retaining access to all but the specified drivers.
+A
+.I devmask
+of '0' removes access to all drivers.
+.PP
+Access to some drivers is tied to other
+related process capabilities:
+.TP
+\f2mnt\fP(3)
+.IP
+Ability to perform the
+.IR mount (2)
+system call, and
+to post new services to
+.IR shr (3).
+.TP
+\f2pipe\fP(3)
+.IP
+Ability to perform the
+.IR pipe (2)
+system call.
+.SH EXAMPLES
+Permit access to only
+.IR draw (3),
+.IR rtc (3),
+.IR fs (3),
+and
+.IR srv (3):
+.IP
+.EX
+chdev irks
+.EE
+.PP
+Remove access to
+.IR cons (3),
+.IR rtc (3),
+.IR audio (3),
+and
+.IR proc (3):
+.IP
+.EX
+chdev !crAp
+.EE
+.PP
+Create a
+.IR pipe (3)
+then remove the ability to create more:
+.IP
+.EX
+bind '#|' /n/pipe
+chdev '!|'
+.EE
+.SH DIAGNOSTICS
+.I Chdev
+is implemented through writes to
+.BR /dev/drivers ,
+served by
+.IR cons (3).
+.SH SOURCE
+.B /rc/bin/chdev
+.SH "SEE ALSO"
+.B /dev/drivers
+for a list of current drivers.
+.PP
+.IR intro (3),
+.IR cons (3)
--- a/sys/man/3/cons
+++ b/sys/man/3/cons
@@ -90,10 +90,36 @@
 .PP
 The
 .B drivers
-file contains, one per line, a listing of the drivers configured in the kernel, in the format
+file contains, one per line, a listing of available kernel drivers, in the format
 .IP
 .EX
 #c cons
+.EE
+.PP
+A process can restrict access to kernel drivers through writing messages to the
+.B drivers
+file. A message in the format of
+.IP
+.EX
+chdev [ !0 ] \f2devmask\fP
+.EE
+.PP
+will restrict access to just the provided driver characters listed in
+.IR devmask .
+If \f2devmask\fP is prefixed with a '!', a namespace instead retains access to all
+but the specified drivers. A
+.I devmask
+of '0' removes access to all devices. Removing access to
+.IR mnt (3)
+additionally prevents new mounts into the current namespace.
+The following removes access to all drivers except
+.IR draw (3),
+.IR cons (3),
+and
+.IR fs (3):
+.IP
+.EX
+chdev ick
 .EE
 .PP
 The
--- a/sys/man/3/root
+++ b/sys/man/3/root
@@ -10,6 +10,7 @@
 .B /net
 .B /net.alt
 .B /proc
+.B /rc
 .B /root
 .B /srv
 .fi
--- a/sys/man/6/namespace
+++ b/sys/man/6/namespace
@@ -59,6 +59,17 @@
 .I new
 is missing.
 .TP
+.BR chdev \ [ !0 "] \fIdevmask
+.I Devmask
+defines a string a driver characters to restrict
+the current namespace to. Existing binds
+of drivers are left unaffected. If
+.I devmask
+is prefixed with a '!', the namespace instead retains
+access to all but the specified drivers. A
+.I devmask
+of '0' removes all drivers.
+.TP
 .BR clear
 Clear the name space with
 .BR rfork(RFCNAMEG) .
@@ -80,4 +91,5 @@
 .SH "SEE ALSO"
 .IR bind (1),
 .IR namespace (4),
-.IR init (8)
+.IR init (8),
+.IR chdev (1)
--- a/sys/man/8/listen
+++ b/sys/man/8/listen
@@ -96,6 +96,14 @@
 an inbound call on the TCP network for port 565 executes service
 .BR tcp565 .
 .PP
+Services may have individual
+.IR namespace (6)
+files specified within
+.IR srvdir .
+If provided, the namespace is used as the parent for each connection
+to the corresponding service. Namespace files are found by appending a .namespace
+suffix to the service name.
+.PP
 At least the following services are available in
 .BR /bin/service .
 .TF \ tcp0000
--- a/sys/src/9/boot/boot.c
+++ b/sys/src/9/boot/boot.c
@@ -25,6 +25,7 @@
 	buf[1+read(open("/env/cputype", OREAD|OCEXEC), buf+1, sizeof buf - 6)] = '\0';
 	strcat(buf, bin);
 	bind(buf, bin, MAFTER);
+	bind("/root/rc", "/rc", MREPL);
 	bind("/rc/bin", bin, MAFTER);

 	exec("/bin/bootrc", argv);
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -1272,7 +1272,7 @@
 Chan*
 namec(char *aname, int amode, int omode, ulong perm)
 {
-	int len, n, t, nomount;
+	int len, n, t, nomount, devunmount;
 	Chan *c;
 	Chan *volatile cnew;
 	Path *volatile path;
@@ -1292,6 +1292,24 @@
 	name = aname;

 	/*
+	 * When unmounting, the name parameter must be accessed
+	 * using Aopen in order to get the real chan from
+	 * something like /srv/cs or /fd/0. However when sandboxing,
+	 * unmounting a sharp from a union is a valid operation even
+	 * if the device is blocked.
+	 */
+	devunmount = 0;
+	if(amode == Aunmount){
+		/*
+		 * Doing any walks down the device could leak information
+		 * about the existence of files.
+		 */
+		if(name[0] == '#' && utflen(name) == 2)
+			devunmount = 1;
+		amode = Aopen;
+	}
+
+	/*
 	 * Find the starting off point (the current slash, the root of
 	 * a device tree, or the current dot) as well as the name to
 	 * evaluate starting there.
@@ -1313,24 +1331,13 @@
 			up->genbuf[n++] = *name++;
 		}
 		up->genbuf[n] = '\0';
-		/*
-		 *  noattach is sandboxing.
-		 *
-		 *  the OK exceptions are:
-		 *	|  it only gives access to pipes you create
-		 *	d  this process's file descriptors
-		 *	e  this process's environment
-		 *  the iffy exceptions are:
-		 *	c  time and pid, but also cons and consctl
-		 *	p  control of your own processes (and unfortunately
-		 *	   any others left unprotected)
-		 */
 		n = chartorune(&r, up->genbuf+1)+1;
-		if(up->pgrp->noattach && utfrune("|decp", r)==nil)
-			error(Enoattach);
 		t = devno(r, 1);
 		if(t == -1)
 			error(Ebadsharp);
+		if(!devunmount && !devallowed(up->pgrp, r))
+			error(Enoattach);
+
 		c = devtab[t]->attach(up->genbuf+n);
 		break;

--- a/sys/src/9/port/dev.c
+++ b/sys/src/9/port/dev.c
@@ -31,6 +31,74 @@
 }

 void
+devmask(Pgrp *pgrp, char *devs)
+{
+	int i, t, w;
+	int invert;
+	char *p;
+	Rune r;
+	u64int mask[nelem(pgrp->notallowed)];
+
+	
+	invert = 1;
+	switch(*devs){
+	case '!':
+		memset(mask, 0, sizeof mask);
+		devs++;
+		invert--;
+		break;
+	case '0':
+		devs = "";
+	default:
+		memset(mask, 0xFF, sizeof mask);
+		break;
+	}		
+
+	w = sizeof mask[0] * 8;
+	for(p = devs; *p != '\0';){
+		p += chartorune(&r, p);
+		t = devno(r, 1);
+		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, 1);
+	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
@@ -39,6 +39,16 @@
 	CMrdb,		"rdb",		0,
 };

+enum
+{
+	CMchdev,
+};
+
+Cmdtab drivermsg[] =
+{
+	CMchdev,	"chdev",	2,
+};
+
 void
 printinit(void)
 {
@@ -332,7 +342,7 @@
 	"cons",		{Qcons},	0,		0660,
 	"consctl",	{Qconsctl},	0,		0220,
 	"cputime",	{Qcputime},	6*NUMSIZE,	0444,
-	"drivers",	{Qdrivers},	0,		0444,
+	"drivers",	{Qdrivers},	0,		0666,
 	"hostdomain",	{Qhostdomain},	DOMLEN,		0664,
 	"hostowner",	{Qhostowner},	0,		0664,
 	"kmesg",	{Qkmesg},	0,		0440,
@@ -583,9 +593,15 @@
 	case Qdrivers:
 		b = smalloc(READSTR);
 		k = 0;
-		for(i = 0; devtab[i] != nil; i++)
+		
+		rlock(&up->pgrp->ns);
+		for(i = 0; devtab[i] != nil; i++){
+			if(up->pgrp->notallowed[i/(sizeof(u64int)*8)] & 1<<i%(sizeof(u64int)*8))
+				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();
@@ -674,6 +690,24 @@

 	case Qconfig:
 		error(Eperm);
+		break;
+
+	case Qdrivers:
+		cb = parsecmd(a, n);
+		if(waserror()) {
+			free(cb);
+			nexterror();
+		}
+
+		ct = lookupcmd(cb, drivermsg, nelem(drivermsg));
+		if(ct == nil)
+			error(Ebadarg);
+		if(ct->index != CMchdev)
+			error(Ebadarg);
+
+		devmask(up->pgrp, cb->f[1]);
+		poperror();
+		free(cb);
 		break;

 	case Qreboot:
--- a/sys/src/9/port/devroot.c
+++ b/sys/src/9/port/devroot.c
@@ -105,6 +105,7 @@
 	addrootdir("net");
 	addrootdir("net.alt");
 	addrootdir("proc");
+	addrootdir("rc");
 	addrootdir("root");
 	addrootdir("srv");
 	addrootdir("shr");
--- a/sys/src/9/port/devshr.c
+++ b/sys/src/9/port/devshr.c
@@ -464,7 +464,7 @@
 		cclose(c);
 		return nc;	
 	case Qcroot:
-		if(up->pgrp->noattach)
+		if(!canmount(up->pgrp))
 			error(Enoattach);
 		if((perm & DMDIR) == 0 || mode != OREAD)
 			error(Eperm);
@@ -498,7 +498,7 @@
 		sch->shr = shr;
 		break;
 	case Qcshr:
-		if(up->pgrp->noattach)
+		if(!canmount(up->pgrp))
 			error(Enoattach);
 		if((perm & DMDIR) != 0 || mode != OWRITE)
 			error(Eperm);
@@ -731,7 +731,7 @@
 	Mhead *h;
 	Mount *m;

-	if(up->pgrp->noattach)
+	if(!canmount(up->pgrp))
 		error(Enoattach);
 	sch = tosch(c);
 	if(sch->level != Qcmpt)
--- a/sys/src/9/port/mkdevc
+++ b/sys/src/9/port/mkdevc
@@ -78,6 +78,9 @@
 	if(ARGC < 2)
 		exit "usage"

+	if(ndev >= 256)
+		exit "device count will overflow Pgrp.notallowed"
+
 	printf "#include \"u.h\"\n";
 	printf "#include \"../port/lib.h\"\n";
 	printf "#include \"mem.h\"\n";
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -121,6 +121,7 @@
 	Amount,				/* to be mounted or mounted upon */
 	Acreate,			/* is to be created */
 	Aremove,			/* will be removed by caller */
+	Aunmount,			/* unmount arg[0] */

 	COPEN	= 0x0001,		/* for i/o */
 	CMSG	= 0x0002,		/* the message channel for a mount */
@@ -484,7 +485,7 @@
 {
 	Ref;
 	RWlock	ns;			/* Namespace n read/one write lock */
-	int	noattach;
+	u64int	notallowed[4];		/* Room for 256 devices */
 	Mhead	*mnthash[MNTHASH];
 };

--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -413,6 +413,9 @@
 ushort		nhgets(void*);
 ulong		µs(void);
 long		lcycles(void);
+void		devmask(Pgrp*,char*);
+int		devallowed(Pgrp*, int);
+int		canmount(Pgrp*);

 #pragma varargck argpos iprint	1
 #pragma	varargck argpos	panic	1
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -1048,7 +1048,7 @@
 			nexterror();
 		}

-		if(up->pgrp->noattach)
+		if(!canmount(up->pgrp))
 			error(Enoattach);

 		ac = nil;
@@ -1160,14 +1160,8 @@
 		nexterror();
 	}
 	if(name != nil) {
-		/*
-		 * This has to be namec(..., Aopen, ...) because
-		 * if arg[0] is something like /srv/cs or /fd/0,
-		 * opening it is the only way to get at the real
-		 * Chan underneath.
-		 */
 		validaddr((uintptr)name, 1, 0);
-		cmounted = namec(name, Aopen, OREAD, 0);
+		cmounted = namec(name, Aunmount, OREAD, 0);
 	}
 	cunmount(cmount, cmounted);
 	poperror();
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -34,6 +34,7 @@
 	Egrp *oeg;
 	ulong pid, flag;
 	Mach *wm;
+	char *devs;

 	flag = va_arg(list, ulong);
 	/* Check flags before we commit */
@@ -44,6 +45,11 @@
 	if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
 		error(Ebadarg);

+	/*
+	 * Code using RFNOMNT expects to block all but
+	 * the following devices.
+	 */
+	devs = "|decp";
 	if((flag&RFPROC) == 0) {
 		if(flag & (RFMEM|RFNOWAIT))
 			error(Ebadarg);
@@ -60,12 +66,12 @@
 			up->pgrp = newpgrp();
 			if(flag & RFNAMEG)
 				pgrpcpy(up->pgrp, opg);
-			/* inherit noattach */
-			up->pgrp->noattach = opg->noattach;
+			/* inherit notallowed */
+			memmove(up->pgrp->notallowed, opg->notallowed, sizeof up->pgrp->notallowed);
 			closepgrp(opg);
 		}
 		if(flag & RFNOMNT)
-			up->pgrp->noattach = 1;
+			devmask(up->pgrp, devs);
 		if(flag & RFREND) {
 			org = up->rgrp;
 			up->rgrp = newrgrp();
@@ -177,8 +183,8 @@
 		p->pgrp = newpgrp();
 		if(flag & RFNAMEG)
 			pgrpcpy(p->pgrp, up->pgrp);
-		/* inherit noattach */
-		p->pgrp->noattach = up->pgrp->noattach;
+		/* inherit notallowed */
+		memmove(p->pgrp->notallowed, up->pgrp->notallowed, sizeof p->pgrp->notallowed);
 	}
 	else {
 		p->pgrp = up->pgrp;
@@ -185,7 +191,7 @@
 		incref(p->pgrp);
 	}
 	if(flag & RFNOMNT)
-		p->pgrp->noattach = 1;
+		devmask(p->pgrp, devs);

 	if(flag & RFREND)
 		p->rgrp = newrgrp();
--- a/sys/src/cmd/aux/listen.c
+++ b/sys/src/cmd/aux/listen.c
@@ -136,6 +136,7 @@
 {
 	int ctl, pid, start;
 	char dir[40], err[128], ds[128];
+	char prog[Maxpath], serv[Maxserv], ns[Maxpath];
 	long childs;
 	Announce *a;
 	Waitmsg *wm;
@@ -178,6 +179,10 @@
 			sleep((pid*10)%200);

 			snprint(ds, sizeof ds, "%s!%s!%s", protodir, addr, a->a);
+			snprint(serv, sizeof serv, "%s%s", proto, a->a);
+			snprint(prog, sizeof prog, "%s/%s", srvdir, serv);
+			snprint(ns, sizeof ns, "%s.namespace", prog);
+
 			whined = a->whined;

 			/* a process per service */
@@ -201,7 +206,11 @@
 						else
 							exits("ctl");
 					}
-					dolisten(dir, ctl, srvdir, a->a, &childs);
+					procsetname("%s %s", dir, ds);
+					if(!trusted)
+						if(newns("none", ns) < 0)
+							syslog(0, listenlog, "can't build namespace %s: %r\n", ns);
+					dolisten(dir, ctl, serv, prog, &childs);
 					close(ctl);
 				}
 			default:
@@ -299,6 +308,8 @@
 				continue;
 			if(strncmp(nm, proto, nlen) != 0)
 				continue;
+			if(strstr(nm + nlen, ".namespace") != nil)
+				continue;
 			addannounce(nm + nlen);
 		}
 		free(db);
@@ -329,15 +340,10 @@
 }

 void
-dolisten(char *dir, int ctl, char *srvdir, char *port, long *pchilds)
+dolisten(char *dir, int ctl, char *serv, char *prog, long *pchilds)
 {
 	char ndir[40], wbuf[64];
-	char prog[Maxpath], serv[Maxserv];
 	int nctl, data, wfd, nowait;
-
-	procsetname("%s %s!%s!%s", dir, proto, addr, port);
-	snprint(serv, sizeof serv, "%s%s", proto, port);
-	snprint(prog, sizeof prog, "%s/%s", srvdir, serv);
 	
 	wfd = -1;
 	nowait = RFNOWAIT;
--- a/sys/src/libauth/newns.c
+++ b/sys/src/libauth/newns.c
@@ -14,8 +14,8 @@
 static int	setenv(char*, char*);
 static char	*expandarg(char*, char*);
 static int	splitargs(char*, char*[], char*, int);
-static int	nsfile(char*, Biobuf *, AuthRpc *);
-static int	nsop(char*, int, char*[], AuthRpc*);
+static int	nsfile(char*, Biobuf *, AuthRpc *, int);
+static int	nsop(char*, int, char*[], AuthRpc*, int);
 static int	catch(void*, char*);

 int newnsdebug;
@@ -35,7 +35,7 @@
 {
 	Biobuf *b;
 	char home[4*ANAMELEN];
-	int afd, cdroot;
+	int afd, cdroot, dfd;
 	char *path;
 	AuthRpc *rpc;

@@ -51,6 +51,10 @@
 	}
 	/* rpc != nil iff afd >= 0 */

+	dfd = open("#c/drivers", OWRITE|OCEXEC);
+	if(dfd < 0 && newnsdebug)
+		fprint(2, "open #c/drivers: %r\n");
+
 	if(file == nil){
 		if(!newns){
 			werrstr("no namespace file specified");
@@ -70,7 +74,8 @@
 		setenv("home", home);
 	}

-	cdroot = nsfile(newns ? "newns" : "addns", b, rpc);
+	cdroot = nsfile(newns ? "newns" : "addns", b, rpc, dfd);
+	close(dfd);
 	Bterm(b);
 	freecloserpc(rpc);

@@ -87,7 +92,7 @@
 }

 static int
-nsfile(char *fn, Biobuf *b, AuthRpc *rpc)
+nsfile(char *fn, Biobuf *b, AuthRpc *rpc, int dfd)
 {
 	int argc;
 	char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
@@ -103,7 +108,7 @@
 			continue;
 		argc = splitargs(cmd, argv, argbuf, NARG);
 		if(argc)
-			cdroot |= nsop(fn, argc, argv, rpc);
+			cdroot |= nsop(fn, argc, argv, rpc, dfd);
 	}
 	atnotify(catch, 0);
 	return cdroot;
@@ -143,7 +148,7 @@
 }

 static int
-nsop(char *fn, int argc, char *argv[], AuthRpc *rpc)
+nsop(char *fn, int argc, char *argv[], AuthRpc *rpc, int dfd)
 {
 	char *argv0;
 	ulong flags;
@@ -181,7 +186,7 @@
 		b = Bopen(argv[0], OREAD|OCEXEC);
 		if(b == nil)
 			return 0;
-		cdroot |= nsfile(fn, b, rpc);
+		cdroot |= nsfile(fn, b, rpc, dfd);
 		Bterm(b);
 	}else if(strcmp(argv0, "clear") == 0 && argc == 0){
 		rfork(RFCNAMEG);
@@ -212,6 +217,13 @@
 	}else if(strcmp(argv0, "cd") == 0 && argc == 1){
 		if(chdir(argv[0]) == 0 && *argv[0] == '/')
 			cdroot = 1;
+	}else if(strcmp(argv0, "chdev") == 0 && argc == 1){
+		//We should not silently fail if we can not honor a chdev
+		//due to the parent namespace missing #c/drivers.
+		if(dfd <= 0)
+			sysfatal("chdev requested, but could not open #c/drivers");
+		if(fprint(dfd, "chdev %s", argv[0]) < 0 && newnsdebug)
+			fprint(2, "%s: chdev %s %r\n", fn, argv[0]);
 	}
 	return cdroot;
 }

  reply	other threads:[~2022-05-26  5:57 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-04 14:09 Jacob Moody
2022-05-04 15:05 ` ori
2022-05-04 15:31 ` ori
2022-05-04 16:15   ` Stanley Lieber
2022-05-04 17:41   ` Lyndon Nerenberg (VE7TFX/VE6BBM)
2022-05-04 17:55     ` Jacob Moody
2022-05-05  1:59       ` Alex Musolino
2022-05-05 16:07         ` Jacob Moody
2022-05-08  2:55           ` Jacob Moody
2022-05-11 14:47             ` Jacob Moody
2022-05-11 16:11               ` Stanley Lieber
2022-05-12  4:29                 ` Jacob Moody
2022-05-12  3:18             ` ori
2022-05-12  5:10               ` Jacob Moody
2022-05-12 14:21                 ` ori
2022-05-23  5:42                   ` Jacob Moody
2022-05-23 17:06                     ` cinap_lenrek
2022-05-23 17:37                       ` Jacob Moody
2022-05-25 19:03                         ` Jacob Moody
2022-05-25 20:53                           ` hiro
2022-05-25 21:20                             ` Jacob Moody
2022-05-26  5:55                               ` Jacob Moody [this message]
2022-05-26 23:36                                 ` unobe
2022-05-27  0:33                                   ` Jacob Moody
2022-05-27  3:25                                     ` unobe
2022-05-26  3:13                             ` ori
2022-05-27  1:11                           ` Lyndon Nerenberg (VE7TFX/VE6BBM)
2022-05-27  2:25                             ` Frank D. Engel, Jr.

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c57bac9f-ca9b-fb7c-7069-d76ea1aeb249@posixcafe.org \
    --to=moody@mail.posixcafe.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).