Open mode checks, don't use == for OREAD
authorBarret Rhoden <brho@cs.berkeley.edu>
Sun, 19 Jan 2014 22:10:46 +0000 (14:10 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sun, 19 Jan 2014 22:10:46 +0000 (14:10 -0800)
There's a disconnect between omode and the access bits part of the VFS
open flags.  Don't simply check for equality of OREAD.

I didn't want to change omode higher in the stack (to do so, we can pass
it through the poorly named 'openmode').  I wanted to keep the vfs_flags
info around as long as possible, in case lower layers want to make use
of that info.

Btw, OREAD's value is 0, which means we can't check for the bit.
Fucking terrible.

kern/drivers/dev/alarm.c
kern/drivers/dev/dev.c
kern/drivers/dev/vm.c
kern/src/net/devip.c
kern/src/ns/sysfile.c

index 0ef0723..3a29a37 100644 (file)
@@ -239,7 +239,7 @@ static struct chan *alarmopen(struct chan *c, int omode)
                case Qalarmdir:
                        if (omode & ORCLOSE)
                                error(Eperm);
-                       if (omode != OREAD)
+                       if ((omode & OREAD) != OREAD)
                                error(Eisdir);
                        break;
                case Qclone:
index 19a52df..e6d8273 100644 (file)
@@ -357,8 +357,8 @@ devopen(struct chan *c, int omode, struct dirtab *tab, int ntab, Devgen *gen)
        }
 Return:
        c->offset = 0;
-       if((c->qid.type&QTDIR) && omode!=OREAD)
-               error(Eperm);
+       if ((c->qid.type & QTDIR) && ((omode & OREAD) != OREAD))
+               error("Tried opening dir with non-read-only mode %o", omode);
        c->mode = openmode(omode);
        c->flag |= COPEN;
        return c;
index 20fa35e..384a9d8 100644 (file)
@@ -280,7 +280,7 @@ static struct chan *vmopen(struct chan *c, int omode)
        case Qvmdir:
                if (omode & ORCLOSE)
                        error(Eperm);
-               if (omode != OREAD)
+               if ((omode & OREAD) != OREAD)
                        error(Eisdir);
                break;
        case Qclone:
index 1e6d9f6..e143fc9 100644 (file)
@@ -409,11 +409,11 @@ ipopen(struct chan* c, int omode)
        case Qstats:
        case Qbootp:
        case Qipselftab:
-               if(omode != OREAD)
+               if((omode & OREAD) != OREAD)
                        error(Eperm);
                break;
        case Qsnoop:
-               if(omode != OREAD)
+               if((omode & OREAD) != OREAD)
                        error(Eperm);
                p = f->p[PROTO(c->qid)];
                cv = p->conv[CONV(c->qid)];
index 0f86afc..1767781 100644 (file)
@@ -99,7 +99,7 @@ fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
        if(mode<0 || c->mode==ORDWR)
                return c;
 
-       if((mode&OTRUNC) && c->mode==OREAD) {
+       if((mode&OTRUNC) && (c->mode & OREAD) == OREAD) {
                if(iref)
                        cclose(c);
                error(Ebadusefd);
@@ -127,7 +127,7 @@ kchanio(void *vc, void *buf, int n, int mode)
                return -1;
        }
 
-       if(mode == OREAD)
+       if ((mode & OREAD) == OREAD)
                r = devtab[c->type]->read(c, buf, n, c->offset);
        else
                r = devtab[c->type]->write(c, buf, n, c->offset);
@@ -139,9 +139,14 @@ kchanio(void *vc, void *buf, int n, int mode)
        return r;
 }
 
-int
-openmode(uint32_t o)
+
+int openmode(uint32_t omode)
 {
+#if 0
+    /* this is the old plan9 style.  i think they want to turn exec into read,
+     * and strip off anything higher, and just return the RD/WR style bits.  not
+     * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
+     * the only one of their non-RW-related flags that isn't masked out) */
        if(o >= (OTRUNC|OCEXEC|ORCLOSE|OEXEC))
                error(Ebadarg);
        o &= ~(OTRUNC|OCEXEC|ORCLOSE);
@@ -150,6 +155,12 @@ openmode(uint32_t o)
        if(o == OEXEC)
                return OREAD;
        return o;
+#endif
+    /* no error checking (we have a shitload of flags anyway), and we return the
+     * basic access modes (RD/WR/ETC) */
+    if (omode == O_EXEC)
+        return O_RDONLY;
+    return omode & O_ACCMODE;
 }
 
 void
@@ -624,7 +635,7 @@ sysunmount(char *old, char *new)
 }
 
 int
-sysopen(char *path, int mode)
+sysopen(char *path, int vfs_flags)
 {
        ERRSTACK(2);
        int fd;
@@ -635,8 +646,8 @@ sysopen(char *path, int mode)
                return -1;
        }
 
-       openmode(mode);                         /* error check only */
-       c = namec(path, Aopen, mode, 0);
+       openmode(vfs_flags);                         /* error check only */
+       c = namec(path, Aopen, vfs_flags, 0);
        if(waserror()){
                cclose(c);
                nexterror();