This patch makes it possible to enter a namespace through
/proc/$pid/ns, like so:
auth/newns -n /proc/$pid/ns $cmd
or through procesing the namespace file any other way
that they want.
with the hope it'll be useful for things like fixing up
tab completion in rio, making the plumber responsive to
the local namespace that we are plumbing from, and other
things that we haven't figured out yet.
It works by making the chans for a proc's mounts available
via /proc/$pid/srv/$id, and changing /proc/$pid/ns to use
the channel name rather than files other procs can't access,
such as '#|'.
Hopefully folks will be able to experiment a bit with this,
and figure out some good uses for it.
diff 4341e26ac5d5cb86af2e1d88dd85365e7feb3a59 uncommitted
--- a/sys/man/3/proc
+++ b/sys/man/3/proc
@@ -22,6 +22,7 @@
.BI /proc/ n /profile
.BI /proc/ n /regs
.BI /proc/ n /segment
+.BI /proc/ n /srv/ chan
.BI /proc/ n /status
.BI /proc/ n /text
.BI /proc/ n /wait
@@ -127,6 +128,15 @@
for read-only, if any;
starting virtual address, in hexadecimal;
ending virtual address, and reference count.
+.PP
+The
+.B srv
+directory provides a directory holding already-open channels
+to services in the style of
+.IR srv (3).
+This allows a process with appropriate permissions to execute the
+.I ns
+file and accurately reproduce the namespace of the process that is running.
.PP
The read-only
.B status
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -28,6 +28,8 @@
Qnoteid,
Qnotepg,
Qns,
+ Qsrv,
+ Qchan,
Qppid,
Qproc,
Qregs,
@@ -100,6 +102,7 @@
"noteid", {Qnoteid}, 0, 0664,
"notepg", {Qnotepg}, 0, 0000,
"ns", {Qns}, 0, 0444,
+ "srv", {Qsrv,0,QTDIR}, 0, 0555,
"ppid", {Qppid}, 0, 0444,
"proc", {Qproc}, 0, 0400,
"regs", {Qregs}, sizeof(Ureg), 0000,
@@ -154,8 +157,8 @@
* in vers,
* 32 bits of pid, for consistency checking
*/
-#define QSHIFT 5 /* location in qid of proc slot # */
-
+#define QSHIFT 5 /* location in qid of proc slot # */
+#define CSHIFT (26+5) /* location in qid of chan # */
#define QID(q) ((((ulong)(q).path)&0x0000001F)>>0)
#define SLOTMAX 0x4000000
#define SLOT(q) (((((ulong)(q).path)>>QSHIFT)&(SLOTMAX-1))-1)
@@ -175,6 +178,39 @@
static int lenwatchpt(Proc *);
+static Chan*
+mntchan(Proc *p, Chan *c)
+{
+ char *s, *t, buf[32];
+ Chan *nc, *mc;
+ Pgrp *pg;
+ Mount *f;
+
+ s = c->path->s;
+ if((t = strrchr(s, '/')) != nil)
+ s = t+1;
+
+ pg = p->pgrp;
+ if(pg == nil)
+ error(Eprocdied);
+
+ nc = nil;
+ rlock(&pg->ns);
+ for(f = pg->mntorder; f != nil; f = f->order){
+ if(strcmp(f->to->path->s, "#M") != 0)
+ continue;
+ mc = f->to->mchan;
+ snprint(buf, sizeof(buf), "%ld.%x.%llx", mc->dev, mc->type,
mc->qid.path);
+ if(strcmp(s, buf) == 0){
+ nc = f->to->mchan;
+ incref(nc);
+ break;
+ }
+ }
+ runlock(&pg->ns);
+ return nc;
+}
+
static int
procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
{
@@ -182,7 +218,13 @@
Proc *p;
char *ename;
Segment *q;
- ulong pid, path, perm, len;
+ Mount *f;
+ Chan *mc;
+ Pgrp *pg;
+ ulong pid, perm, len;
+ uvlong path;
+ char *e, *t;
+ int i;
if(s == DEVDOTDOT){
mkqid(&qid, Qdir, 0, QTDIR);
@@ -226,9 +268,46 @@
devdir(c, qid, up->genbuf, 0, p->user, 0555, dp);
return 1;
}
+ if(QID(c->qid) == Qsrv){
+ i = 0;
+ p = proctab(SLOT(c->qid));
+ pg = p->pgrp;
+ if(pg == nil || p->dot == nil || p->pid != PID(c->qid))
+ error(Eprocdied);
+ rlock(&pg->ns);
+ for(f = pg->mntorder; f != nil; f = f->order){
+ if(strcmp(f->to->path->s, "#M") != 0)
+ continue;
+ if(i++ >= s)
+ break;
+ }
+ if(f == nil){
+ runlock(&pg->ns);
+ return -1;
+ }
+ mc = f->to->mchan;
+ path = ((uvlong)i<<CSHIFT) | c->qid.path&~((1<<QSHIFT)-1);
+ snprint(up->genbuf, sizeof(up->genbuf), "%ld.%x.%llx", mc->dev,
mc->type, mc->qid.path);
+ mkqid(&qid, path | Qchan, p->pid, QTFILE);
+ devdir(c, qid, up->genbuf, 0, p->user, 0400, dp);
+ runlock(&pg->ns);
+ return 1;
+ }
+ if(QID(c->qid) == Qchan){
+ p = proctab(SLOT(c->qid));
+ if(p->dot == nil || p->pid != PID(c->qid))
+ error(Eprocdied);
+ e = c->path->s;
+ if((t = strrchr(e, '/')) != nil)
+ e = t+1;
+ snprint(up->genbuf, sizeof(up->genbuf), "%s", e);
+ mkqid(&qid, c->qid.path, p->pid, QTFILE);
+ devdir(c, qid, up->genbuf, 0, eve, 0400, dp);
+ return 1;
+ }
if(c->qid.path == Qtrace){
strcpy(up->genbuf, "trace");
- mkqid(&qid, Qtrace, -1, QTFILE);
+ mkqid(&qid, c->qid.path, -1, QTFILE);
devdir(c, qid, up->genbuf, 0, eve, 0400, dp);
return 1;
}
@@ -265,7 +344,7 @@
break;
}
- mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
+ mkqid(&qid, path|tab->qid.path, c->qid.vers, tab->qid.type);
devdir(c, qid, tab->name, len, p->user, perm, dp);
return 1;
}
@@ -398,6 +477,7 @@
c->offset = 0;
return c;
}
+
p = proctab(SLOT(c->qid));
eqlock(&p->debug);
@@ -436,7 +516,13 @@
if(omode != OREAD)
error(Eperm);
break;
-
+ case Qchan:
+ tc = mntchan(p, c);
+ if(tc == nil)
+ error(Eshutdown);
+ devpermcheck(p->user, c->mode, omode);
+ nonone(p);
+ goto Found;
case Qctl:
case Qargs:
case Qwait:
@@ -488,8 +574,8 @@
clearwatchpt(p);
break;
}
-
poperror();
+Found:
qunlock(&p->debug);
poperror();
@@ -641,10 +727,11 @@
static int
readns1(Chan *c, Proc *p, char *buf, int nbuf)
{
+ char flag[10], srv[32];
Pgrp *pg;
Mount *f;
- char flag[10], *srv;
- int i;
+ Chan *mc;
+ int i, n;
pg = p->pgrp;
if(pg == nil || p->dot == nil || p->pid != PID(c->qid))
@@ -656,32 +743,33 @@
rlock(&pg->ns);
i = 0;
- for(f = pg->mntorder; f != nil; f = f->order) {
+ for(f = pg->mntorder; f != nil; f = f->order)
if(i++ >= c->nrock)
break;
- }
if(f == nil) {
c->nrock = -1;
- i = snprint(buf, nbuf, "cd %q\n", p->dot->path->s);
+ n = snprint(buf, nbuf, "cd %q\n", p->dot->path->s);
} else {
c->nrock = i;
int2flag(f->mflag, flag);
if(strcmp(f->to->path->s, "#M") == 0){
- srv = f->to->mchan->srvname;
- if(srv == nil)
- srv = f->to->mchan->path->s;
- i = snprint(buf, nbuf, *f->spec?
- "mount %s %q %q %q\n": "mount %s %q %q\n", flag,
- srv, f->umh->from->path->s, f->spec);
+ mc = f->to->mchan;
+ snprint(srv, sizeof(srv), "%ld.%x.%llx", mc->dev,
mc->type, mc->qid.path);
+ if(f->spec[0] != 0)
+ n = snprint(buf, nbuf, "mount %s
/proc/%lud/srv/%q %q %q\n",
+ flag, p->pid, srv,
f->umh->from->path->s, f->spec);
+ else
+ n = snprint(buf, nbuf, "mount %s
/proc/%lud/srv/%q %q\n",
+ flag, p->pid, srv,
f->umh->from->path->s);
}else{
- i = snprint(buf, nbuf, "bind %s %q %q\n", flag,
+ n = snprint(buf, nbuf, "bind %s %q %q\n", flag,
f->to->path->s, f->umh->from->path->s);
}
}
runlock(&pg->ns);
- return i;
+ return n;
}
int
------------------------------------------
9fans: 9fans
Permalink:
https://9fans.topicbox.com/groups/9fans/Tdf1407e79f217ea2-M4ee7de06944875b04c453002
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription