From: "Frank D. Engel, Jr." <fde101@fjrhome.net>
To: 9front@9front.org, 9fans@9fans.net
Subject: [9fans] Re: [9front] Enterable namespaces: /proc/pid/$ns/srv
Date: Sat, 13 Dec 2025 21:58:15 -0500 [thread overview]
Message-ID: <167ace73-f1df-49f5-bed0-1682e38a19e3@fjrhome.net> (raw)
In-Reply-To: <33BB7902D0B6A6B88BE31817F26530D6@eigenstate.org>
Doesn't that create a security hole by making it possible to access to
private ramdisks and factotum instances and the like which were
previously not accessible to the process?
On 12/13/25 19:54, ori@eigenstate.org 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 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-Ma80db8de7eb2ec3200ae6890
Delivery options: https://9fans.topicbox.com/groups/9fans/subscription
prev parent reply other threads:[~2025-12-14 4:26 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-14 0:54 [9fans] Enterable namespaces: /proc/pid/$ns/srv ori
2025-12-14 2:58 ` Frank D. Engel, Jr. [this message]
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=167ace73-f1df-49f5-bed0-1682e38a19e3@fjrhome.net \
--to=fde101@fjrhome.net \
--cc=9fans@9fans.net \
--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).