srv: Support remove on close
authorBarret Rhoden <brho@cs.berkeley.edu>
Sun, 8 Jan 2017 20:42:50 +0000 (15:42 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 10 Jan 2017 00:01:40 +0000 (19:01 -0500)
Note that the O_REMCLO only applies to the chan/file *created* in srv,
not the ones made from *opening* a file in srv.  When someone opens a
chan/file in srv, that FD points to a new chan from another device,
(e.g. a pipe), and when *that* FD is closed, we call *that* device's
close.

I don't know what the deal was with O_REMCLO and the commented-out code.
All in all, srv needs a good security review, and optionally a port from
Plan 9.  This one was written since the Inferno one didn't seem to do
what we needed.

Also, srv should have some security checks on setting REMCLO, equivalent
to what we do for remove.  Right now, we have no checks on that, so
whatever.  Also, due to srv's implementation, you can only set REMCLO on
create(), which means a process was the creator.  It seems reasonable to
allow the creator to also remove.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/srv.c

index ba4e144..c3d2f65 100644 (file)
@@ -204,15 +204,6 @@ static struct chan *srvopen(struct chan *c, int omode)
                nexterror();
        }
        devpermcheck(srv->user, srv->perm, omode);
-       /* No remove on close support yet */
-#if 0
-       if (omode & ORCLOSE) {
-               if (strcmp(srv->user, up->env->user) != 0)
-                       error(EPERM, ERROR_FIXME);
-               else
-                       srv->flags |= SORCLOSE;
-       }
-#endif
        if ((srv->perm & DMEXCL) && atomic_read(&srv->opens))
                error(EBUSY, ERROR_FIXME);
        /* srv->chan is write-once, so we don't need to sync. */
@@ -255,15 +246,6 @@ static int srvwstat(struct chan *c, uint8_t * dp, int n)
        return -1;
 }
 
-static void srvclose(struct chan *c)
-{
-       struct srvfile *srv = c->aux;
-       if (!grab_ref(srv))
-               return;
-       atomic_dec(&srv->opens);
-       kref_put(&srv->ref);
-}
-
 static void srvremove(struct chan *c)
 {
        struct srvfile *srv_i, *temp;
@@ -280,6 +262,18 @@ static void srvremove(struct chan *c)
                kref_put(&srv_i->ref);  /* dropping ref from the list */
 }
 
+static void srvclose(struct chan *c)
+{
+       struct srvfile *srv = c->aux;
+
+       if (!grab_ref(srv))
+               return;
+       atomic_dec(&srv->opens);
+       kref_put(&srv->ref);
+       if (c->flag & O_REMCLO)
+               srvremove(c);
+}
+
 /* N.B. srvopen gives the chan back. The only 'reading' we do
  * in srv is of the top level directory.
  */