9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Jacob Moody <moody@mail.posixcafe.org>
To: 9front@9front.org
Subject: Re: [9front] Pitch for devskel
Date: Sun, 5 Jun 2022 21:16:07 -0600	[thread overview]
Message-ID: <fbdfdf2e-dd29-cf92-594d-dd18537150b1@posixcafe.org> (raw)
In-Reply-To: <59355e7b-9c12-90f8-d4b4-989f1fa30f26@posixcafe.org>

To further the case for this, I've worked on a userspace
application of the device in the form of auth/box.

The premise of auth/box is to setup a slim namespace
and execute a program as none.

-f and -d specify the files and directories to be included
in the new namespace. The absolute path is replicated
to the new namespace and the specified file/dir is bound
over the empty skeleton.

The specified files/dirs are stat'd to reveal their
device. Box then restricts devices to only those
found this way, the -e option specifies additional
devices.

An example of creating a box with /env, /bin/walk and /sys/log:

; auth/box -f /bin/walk -d /env -d /sys/log walk /
/sys/log/auth
/sys/log/boot
...
/sys/log
/sys
/env/terminal
/env/cputype
...
/env
/bin/walk
/bin
/


thanks,
moody

---
diff df92301d8fc8310fbfdf3de91b97a156ca0504d4 uncommitted
--- /dev/null
+++ b//sys/src/cmd/auth/box.c
@@ -1,0 +1,210 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+
+static int debug;
+static int mountok;
+
+#define DEBUG if(debug)
+
+typedef struct List List;
+struct List {
+	char *s;
+	Rune dev;
+	List *next;
+};
+
+void
+addto(List *l, char *s)
+{
+	List *p;
+
+	for(p = l; p->s != nil && p->next != nil; p = p->next)
+		if(strcmp(p->s, s) == 0)
+			return;
+
+	if(p->s != nil){
+		p->next = mallocz(sizeof *p, 1);
+		p = p->next;
+
+	}
+	p->s = s;
+}
+
+void
+resolve(List *l)
+{
+	List *p;
+	char buf[8192];
+	int fd;
+	Dir *d;
+
+	fd = open(".", OREAD);
+	if(fd < 0)
+		sysfatal("could not open .: %r");
+	fd2path(fd, buf, sizeof buf);
+	for(p = l; p != nil; p = p->next){
+		if(p->s == nil)
+			continue;
+		cleanname(p->s);
+		switch(p->s[0]){
+		case '#':
+		case '/':
+			break;
+		case '.':
+			if(p->s[1] == '/')
+				break;
+		default:
+			p->s = cleanname(smprint("%s/%s", buf, p->s));
+		}
+		d = dirstat(p->s);
+		if(d == nil){
+			p->s = nil;
+			continue;
+		}
+		p->dev = d->type;
+		free(d);
+	}
+
+	close(fd);
+}
+
+void
+mimic(char *newroot, List *l, int type)
+{
+	char *parts[32];
+	char src[8192], targ[8192], dir[8192], skel[8192];
+	char mode;
+	List *p;
+	int n, i;
+
+	for(p = l; p != nil; p = p ->next){
+		if(p->s == nil)
+			continue;
+		snprint(src, sizeof src, "%s", p->s);
+		n = gettokens(src, parts, nelem(parts), "/");
+		snprint(targ, sizeof targ, "%s", newroot);
+		for(i = 0; i < n; i++){
+			snprint(dir, sizeof dir, "%s", targ);
+			snprint(targ, sizeof targ, "%s/%s", targ, parts[i]);
+			if(close(open(targ, OREAD)) >= 0)
+				continue;
+			if(i == n-1 && type == QTFILE)
+				mode = 'f';
+			else
+				mode = 'd';
+			snprint(skel, sizeof skel, "#z%c/%s", mode, parts[i]);
+			DEBUG print("bind -b %s %s\n", skel, dir);
+			bind(skel, dir, MBEFORE);
+		}
+		if(i > 0){
+			DEBUG print("bind %s %s\n", p->s, targ);
+			bind(p->s, targ, MREPL);
+		}
+	}
+	
+}
+
+void
+collectdevs(List *l, char *buf, int n)
+{
+	List *p;
+	for(p = l; p != nil; p = p->next){
+		if(!mountok && p->dev == 'M')
+			continue;
+		if(utfrune(buf, p->dev) == nil)
+			snprint(buf, n, "%s%C", buf, p->dev);
+	}
+}
+
+void
+run(char **a)
+{
+	exec(a[0], a);
+
+	if(a[0][0] != '/' && a[0][0] != '#' &&
+	  (a[0][0] != '.' || (a[0][1] != '/' &&
+		             (a[0][1] != '.' ||  a[0][2] != '/'))))
+		exec(smprint("/bin/%s", a[0]), a);
+
+	sysfatal("exec: %s: %r", a[0]);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage %s: [ -f file ] [ -d dir ] cmd args...\n", argv0);
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	char newroot[8192];
+	char devs[1024];
+	int dfd;
+	char *p;
+	List files, dirs;
+	char *defargv[] = { "/bin/rc", "-i", nil };
+
+	dfd = -1;
+	mountok = 0;
+	memset(devs, 0, sizeof devs);
+	ARGBEGIN{
+	case 'M':
+		mountok = 1;
+		snprint(devs, sizeof devs, "%s%c", devs, 'M');
+		break;
+	case 'D':
+		debug = 1;
+		break;
+	case 'f':
+		addto(&files, EARGF(usage()));
+		break;
+	case 'd':
+		addto(&dirs, EARGF(usage()));
+		break;
+	case 'e':
+		p = EARGF(usage());
+		snprint(devs, sizeof devs, "%s%s", devs, p);
+		break;
+	default:
+		usage();
+		break;
+	}ARGEND
+
+	rfork(RFNAMEG|RFENVG);
+	snprint(newroot, sizeof newroot, "#zd/newroot.%d", getpid());
+
+	resolve(&files);
+	resolve(&dirs);
+	if(procsetuser("none") < 0)
+		sysfatal("cant become none: %r");
+	putenv("user", "none");
+	collectdevs(&files, devs, sizeof devs);
+	collectdevs(&dirs, devs, sizeof devs);
+	if(devs[0] != '\0'){
+		dfd = open("/dev/drivers", OWRITE);
+		if(dfd < 0)
+			sysfatal("cant open drivers: %r");
+	}
+
+	if(bind(newroot, "/", MBEFORE) < 0)
+		sysfatal("failed to bind: %r");
+
+	p = newroot + strlen("#zd");
+	mimic(p, &files, QTFILE);
+	mimic(p, &dirs, QTDIR);
+	if(bind(p, "/", MREPL) < 0)
+		sysfatal("failed to bind: %r");
+
+	if(devs[0] != '\0'){
+		DEBUG print("chdev %s\n", devs);
+		fprint(dfd, "chdev & %s", devs);
+		close(dfd);
+	}
+
+	if(argc == 0)
+		argv = defargv;
+	run(argv);
+}
--- a//sys/src/cmd/auth/mkfile
+++ b//sys/src/cmd/auth/mkfile
@@ -9,6 +9,7 @@
 	asn1dump\
 	asn12rsa\
 	authsrv\
+	box\
 	changeuser\
 	convkeys\
 	cron\


  reply	other threads:[~2022-06-06  3:18 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-05  0:57 Jacob Moody
2022-06-06  3:16 ` Jacob Moody [this message]
2022-06-06  6:41   ` Jacob Moody
2022-06-06 14:40     ` ori
2022-06-06 15:08       ` Jacob Moody
2022-06-06 15:24         ` ori
2022-06-06 15:31           ` Jacob Moody

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=fbdfdf2e-dd29-cf92-594d-dd18537150b1@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).