M port/chan.c => port/chan.c +15 -0
@@ 710,6 710,21 @@ namec(char *name, int amode, int omode, ulong perm)
c = cclone(up->slash, 0);
break;
case '#':
+ /*
+ * 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)
+ */
+ if(up->pgrp->noattach)
+ if(strchr("|decp", name[1]) == 0)
+ error(Enoattach);
cname = newcname(name); /* save this before advancing */
mntok = 0;
elem[0] = 0;
M port/error.h => port/error.h +1 -0
@@ 56,3 56,4 @@ extern char Eshort[]; /* i/o count too small */
extern char Egreg[]; /* xterm: Error 50, errno 1: Too big */
extern char Ebadspec[]; /* bad attach specifier */
extern char Enoreg[]; /* process has no saved registers */
+extern char Enoattach[]; /* mount/attach disallowed */
M port/portdat.h => port/portdat.h +2 -0
@@ 396,6 396,7 @@ enum
struct Pgrp
{
Ref; /* also used as a lock when mounting */
+ int noattach;
ulong pgrpid;
QLock debug; /* single access via devproc.c */
RWlock ns; /* Namespace n read/one write lock */
@@ 476,6 477,7 @@ enum
RFCENVG = (1<<11),
RFCFDG = (1<<12),
RFREND = (1<<13),
+ RFNOMNT = (1<<14),
};
/*
M port/sysfile.c => port/sysfile.c +3 -0
@@ 629,6 629,9 @@ bindmount(ulong *arg, int ismount)
bogus.flags = flag & MCACHE;
if(ismount){
+ if(up->pgrp->noattach)
+ error(Enoattach);
+
bc = fdtochan(fd, ORDWR, 0, 1);
if(waserror()) {
cclose(bc);
M port/sysproc.c => port/sysproc.c +8 -0
@@ 53,8 53,12 @@ sysrfork(ulong *arg)
up->pgrp = newpgrp();
if(flag & RFNAMEG)
pgrpcpy(up->pgrp, opg);
+ /* inherit noattach */
+ up->pgrp->noattach = opg->noattach;
closepgrp(opg);
}
+ if(flag & RFNOMNT)
+ up->pgrp->noattach = 1;
if(flag & RFREND) {
org = up->rgrp;
up->rgrp = newrgrp();
@@ 121,11 125,15 @@ sysrfork(ulong *arg)
p->pgrp = newpgrp();
if(flag & RFNAMEG)
pgrpcpy(p->pgrp, up->pgrp);
+ /* inherit noattach */
+ p->pgrp->noattach = up->pgrp->noattach;
}
else {
p->pgrp = up->pgrp;
incref(p->pgrp);
}
+ if(flag & RFNOMNT)
+ up->pgrp->noattach = 1;
if(flag & RFREND)
p->rgrp = newrgrp();