9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
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

      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).