code: plan9front

Download patch

ref: eaa1949ba0cbc21b1951c4907fe52ead915a411a
parent: 6926080a2d7c8a5b61888c18fa88d70f3384409b
author: Jacob Moody <moody@posixcafe.org>
date: Fri May 27 22:27:59 EDT 2022

auth/newns: add chdev command

--- a/sys/man/6/namespace
+++ b/sys/man/6/namespace
@@ -59,6 +59,12 @@
 .I new
 is missing.
 .TP
+.BR chdev \ [ -nr "] \fIdevmask
+.I Devmask
+defines a string of driver characters to restrict
+the current namespace to. Existing binds
+of drivers are left unaffected.
+.TP
 .BR clear
 Clear the name space with
 .BR rfork(RFCNAMEG) .
@@ -80,4 +86,5 @@
 .SH "SEE ALSO"
 .IR bind (1),
 .IR namespace (4),
-.IR init (8)
+.IR init (8),
+.IR chdev (1)
--- 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,8 +51,13 @@
 	}
 	/* 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){
+			close(dfd);
 			werrstr("no namespace file specified");
 			return freecloserpc(rpc);
 		}
@@ -60,6 +65,7 @@
 	}
 	b = Bopen(file, OREAD|OCEXEC);
 	if(b == nil){
+		close(dfd);
 		werrstr("can't open %s: %r", file);
 		return freecloserpc(rpc);
 	}
@@ -70,7 +76,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 +94,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 +110,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,10 +150,11 @@
 }
 
 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;
+	char *devop;
 	int fd, i;
 	Biobuf *b;
 	int cdroot;
@@ -153,6 +161,7 @@
 
 	cdroot = 0;
 	flags = 0;
+	devop = "&";
 	argv0 = nil;
 	if(newnsdebug){
 		for (i = 0; i < argc; i++)
@@ -172,6 +181,12 @@
 	case 'C':
 		flags |= MCACHE;
 		break;
+	case 'r':
+		devop = "&~";
+		break;
+	case 'n':
+		devop = "~";
+		break;
 	}ARGEND
 
 	if(!(flags & (MAFTER|MBEFORE)))
@@ -181,7 +196,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 +227,18 @@
 	}else if(strcmp(argv0, "cd") == 0 && argc == 1){
 		if(chdir(argv[0]) == 0 && *argv[0] == '/')
 			cdroot = 1;
+	}else if(strcmp(argv0, "chdev") == 0){
+		//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(argc == 0 && devop[0] == '~'){
+			if(fprint(dfd, "chdev ~") < 0 && newnsdebug)
+				fprint(2, "%s: chdev ~: %r\n", fn);
+		}else if(argc == 1){
+			if(fprint(dfd, "chdev %s %s", devop, argv[0]) < 0 && newnsdebug)
+				fprint(2, "%s: chdev %s %s: %r\n", fn, devop, argv[0]);
+		}
 	}
 	return cdroot;
 }