9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Jacob Moody <moody@mail.posixcafe.org>
To: 9front@9front.org
Subject: [9front] [PATCH] Unmount to remove sharp devices.
Date: Wed, 4 May 2022 08:09:56 -0600	[thread overview]
Message-ID: <164813d2-28cb-44dd-2aee-b789ea75ba9a@posixcafe.org> (raw)

Hello,

This patch allows processes to unmount sharp devices to prevent itself and its children from accessing
them. This is implemented through an internal rework of how RFNOMNT works, making RFNOMNT a special
case of setting disallowed devices. To replicate the mount blocking functionality of RFNOMNT a special
case is given for blocking devmnt, which also blocks the process and its children from making any mount
calls.

If everything passes the sniff test I can commit these changes. Diff is here: http://okturing.com/src/13574/body and included
below.

Thanks,
moody

diff 9126ee3eea90d639f4e877c01400248581d10f65 uncommitted
--- a//sys/man/3/0intro
+++ b//sys/man/3/0intro
@@ -87,6 +87,20 @@
 commands will need quotes to protect the
 .B #
 characters.
+.PP
+Access to a kernel device can be forfeited by
+unmounting it. For example, after
+.IP
+.EX
+unmount(nil, "#c")
+.EE
+.LP
+the calling process and its children can no longer access the device through its
+sharp name. Existing binds of these devices are untouched.
+Unmounting the mount device (see
+.IR mnt (3))
+has the side effect of preventing the calling process and its children
+from performing mounts.
 .SH SEE ALSO
 .IR intro (5),
 .IR intro (2)
--- a//sys/src/9/port/chan.c
+++ b//sys/src/9/port/chan.c
@@ -1313,24 +1313,19 @@
 			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);
+		/*
+		 * Notallowed is sandboxing.
+		 * A process group can willingly give up access to a
+		 * sharp device by unmounting it. Notallowed itself is
+		 * a bitmask of indicies in to devtab, a high bit indicating
+		 * that the process has given up its right to use that device.
+		 */
+		if((up->pgrp->notallowed[t/(sizeof(u64int)*8)] & 1<<(t%(sizeof(u64int)*8))) != 0)
+			error(Enoattach);
 		c = devtab[t]->attach(up->genbuf+n);
 		break;

--- 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, 1))
 			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, 1))
 			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, 1))
 		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
@@ -484,7 +484,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,7 @@
 ushort		nhgets(void*);
 ulong		µs(void);
 long		lcycles(void);
+int		canmount(Pgrp*,int);

 #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, 1))
 			error(Enoattach);

 		ac = nil;
@@ -1146,6 +1146,8 @@
 {
 	Chan *cmount, *cmounted;
 	char *name, *old;
+	int t;
+	Rune r;

 	name = va_arg(list, char*);
 	old = va_arg(list, char*);
@@ -1152,6 +1154,14 @@

 	cmounted = nil;
 	validaddr((uintptr)old, 1, 0);
+	if(old[0] == '#' && utflen(old) == 2){
+		chartorune(&r, old+1);
+		t = devno(r, 1);
+		if(t == -1)
+			error(Ebadsharp);
+		up->pgrp->notallowed[t/(sizeof(u64int)*8)] |= 1<<(t%(sizeof(u64int)*8));
+		return 0;
+	}
 	cmount = namec(old, Amount, 0, 0);
 	if(waserror()) {
 		cclose(cmount);
--- a//sys/src/9/port/sysproc.c
+++ b//sys/src/9/port/sysproc.c
@@ -23,6 +23,43 @@
 	pexit("fork aborted", 1);
 }

+int
+canmount(Pgrp *p, int user)
+{
+	int t;
+
+	/*
+	 * Devmnt is not usable directly from user procs, so
+	 * having it removed is interpreted to block any mounts.
+	 */
+	t = devno('M', user);
+	if(t != -1 && (p->notallowed[t/(sizeof(u64int)*8)] & 1<<(t%(sizeof(u64int)*8))) != 0)
+		return 0;
+	return 1;
+}
+
+static void
+setrfnomnt(Pgrp *p)
+{
+	int t, i;
+	u64int mask[nelem(p->notallowed)];
+	char allowed[] = "|decp";
+
+	/*
+	 * Code using RFNOMNT expects to block all sharp devices
+	 * and mounting except for the devices defined in allowed[]
+	 */
+	for(i=0; i < sizeof allowed; i++){
+		t = devno(allowed[i], 1);
+		if(t == -1)
+			continue;
+		mask[t/(sizeof(u64int)*8)] |= 1<<(t%(sizeof(u64int)*8));
+	}
+	/* Sets bit for devmnt, so all mounts are disabled implicitly */
+	for(i=0; i < nelem(p->notallowed); i++)
+		p->notallowed[i] |= ~mask[i];
+}
+
 uintptr
 sysrfork(va_list list)
 {
@@ -60,12 +97,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;
+			setrfnomnt(up->pgrp);
 		if(flag & RFREND) {
 			org = up->rgrp;
 			up->rgrp = newrgrp();
@@ -177,8 +214,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 +222,7 @@
 		incref(p->pgrp);
 	}
 	if(flag & RFNOMNT)
-		p->pgrp->noattach = 1;
+		setrfnomnt(p->pgrp);

 	if(flag & RFREND)
 		p->rgrp = newrgrp();


             reply	other threads:[~2022-05-04 14:13 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-04 14:09 Jacob Moody [this message]
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
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=164813d2-28cb-44dd-2aee-b789ea75ba9a@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).