Re: Enterable namespaces: /proc/pid/$ns/srv
"Frank D. Engel, Jr." <[email protected]> Sat, 13 Dec 2025 21:58:15 -0500
| Newsgroups | gmane.os.9front.general,gmane.os.plan9.general |
|---|---|
| Message-ID | <[email protected]> |
Doesn't that create a security hole by making it possible to access to=20 private ramdisks and factotum instances and the like which were=20 previously not accessible to the process? On 12/13/25 19:54, ori-C8/[email protected] wrote: > 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 runni= ng. > .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 @@ > =20 > static int lenwatchpt(Proc *); > =20 > +static Chan* > +mntchan(Proc *p, Chan *c) > +{ > + char *s, *t, buf[32]; > + Chan *nc, *mc; > + Pgrp *pg; > + Mount *f; > + > + s =3D c->path->s; > + if((t =3D strrchr(s, '/')) !=3D nil) > + s =3D t+1; > + > + pg =3D p->pgrp; > + if(pg =3D=3D nil) > + error(Eprocdied); > + > + nc =3D nil; > + rlock(&pg->ns); > + for(f =3D pg->mntorder; f !=3D nil; f =3D f->order){ > + if(strcmp(f->to->path->s, "#M") !=3D 0) > + continue; > + mc =3D f->to->mchan; > + snprint(buf, sizeof(buf), "%ld.%x.%llx", mc->dev, mc->type, mc->qid.pa= th); > + if(strcmp(s, buf) =3D=3D 0){ > + nc =3D 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; > =20 > if(s =3D=3D 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) =3D=3D Qsrv){ > + i =3D 0; > + p =3D proctab(SLOT(c->qid)); > + pg =3D p->pgrp; > + if(pg =3D=3D nil || p->dot =3D=3D nil || p->pid !=3D PID(c->qid)) > + error(Eprocdied); > + rlock(&pg->ns); > + for(f =3D pg->mntorder; f !=3D nil; f =3D f->order){ > + if(strcmp(f->to->path->s, "#M") !=3D 0) > + continue; > + if(i++ >=3D s) > + break; > + } > + if(f =3D=3D nil){ > + runlock(&pg->ns); > + return -1; > + } > + mc =3D f->to->mchan; > + path =3D ((uvlong)i<<CSHIFT) | c->qid.path&~((1<<QSHIFT)-1); > + snprint(up->genbuf, sizeof(up->genbuf), "%ld.%x.%llx", mc->dev, mc->ty= pe, 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) =3D=3D Qchan){ > + p =3D proctab(SLOT(c->qid)); > + if(p->dot =3D=3D nil || p->pid !=3D PID(c->qid)) > + error(Eprocdied); > + e =3D c->path->s; > + if((t =3D strrchr(e, '/')) !=3D nil) > + e =3D 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 =3D=3D 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; > } > =20 > - 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 =3D 0; > return c; > } > + > =09 > p =3D proctab(SLOT(c->qid)); > eqlock(&p->debug); > @@ -436,7 +516,13 @@ > if(omode !=3D OREAD) > error(Eperm); > break; > - > + case Qchan: > + tc =3D mntchan(p, c); > + if(tc =3D=3D 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; > } > -=09 > poperror(); > +Found: > qunlock(&p->debug); > poperror(); > =20 > @@ -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; > =20 > pg =3D p->pgrp; > if(pg =3D=3D nil || p->dot =3D=3D nil || p->pid !=3D PID(c->qid)) > @@ -656,32 +743,33 @@ > rlock(&pg->ns); > =20 > i =3D 0; > - for(f =3D pg->mntorder; f !=3D nil; f =3D f->order) { > + for(f =3D pg->mntorder; f !=3D nil; f =3D f->order) > if(i++ >=3D c->nrock) > break; > - } > =20 > if(f =3D=3D nil) { > c->nrock =3D -1; > - i =3D snprint(buf, nbuf, "cd %q\n", p->dot->path->s); > + n =3D snprint(buf, nbuf, "cd %q\n", p->dot->path->s); > } else { > c->nrock =3D i; > int2flag(f->mflag, flag); > if(strcmp(f->to->path->s, "#M") =3D=3D 0){ > - srv =3D f->to->mchan->srvname; > - if(srv =3D=3D nil) > - srv =3D f->to->mchan->path->s; > - i =3D 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 =3D f->to->mchan; > + snprint(srv, sizeof(srv), "%ld.%x.%llx", mc->dev, mc->type, mc->qid.p= ath); > + if(f->spec[0] !=3D 0) > + n =3D 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 =3D snprint(buf, nbuf, "mount %s /proc/%lud/srv/%q %q\n", > + flag, p->pid, srv, f->umh->from->path->s); > }else{ > - i =3D snprint(buf, nbuf, "bind %s %q %q\n", flag, > + n =3D snprint(buf, nbuf, "bind %s %q %q\n", flag, > f->to->path->s, f->umh->from->path->s); > } > } > runlock(&pg->ns); > =20 > - return i; > + return n; > } > =20 > int >