Fix 9ns FD access
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 9 Sep 2015 17:11:51 +0000 (13:11 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Sep 2015 19:14:00 +0000 (15:14 -0400)
fdtochan takes the access mode, or -1 to mean "not being used for user
access, just give me the chan".  We were doing a few weird things here
that may have been wrong.

The biggest thing was the O_TRUNC business.  We had a check that was
essentially making sure the device cleared O_TRUNC in its open call.  It
makes more sense to do that right after the open, if at all.  Also, I
don't see how fdtochan would ever get called with O_TRUNC, legitimately.
(Note that -1 sets all flags, so don't check too early!).  As it is now,
the current check will work if for some reason we have an O_TRUNC in
fdtochan's mode parameter, or anything other than what the chan really
supports.

I also dropped the == O_RDWR shortcut, as that has assumptions baked in
to it that O_RDWR means "everything".  This might break some
applications, though in that case maybe the apps or other parts of the
kernel were doing something wrong.

kern/src/ns/chan.c
kern/src/ns/sysfile.c

index 8c00e6f..ffc1930 100644 (file)
@@ -1171,6 +1171,12 @@ Open:
                                         * to change that. */
                                        c->flag |= omode & CEXTERNAL_FLAGS;
                                        c = devtab[c->type].open(c, omode & ~OCEXEC);
+                                       /* if you get this from a dev, in the dev's open, you are
+                                        * probably saving mode directly, without passing it through
+                                        * openmode. */
+                                       if (c->mode & OTRUNC)
+                                               error("Device '%c' %s open failed to clear OTRUNC",
+                                                     devtab[c->type].dc, devtab[c->type].name);
                                        break;
                        }
                        break;
index 9f934a0..0daf255 100644 (file)
@@ -43,34 +43,21 @@ struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
                set_errno(EBADF);
                error("Bad FD %d\n", fd);
        }
-
        if (chkmnt && (c->flag & CMSG)) {
                if (iref)
                        cclose(c);
+               set_errno(EBADF);
                error(Ebadusefd);
        }
-
-       if (mode < 0 || c->mode == ORDWR) {
+       if (mode < 0)
                return c;
-       }
-
-       if ((mode & OTRUNC) && !(c->mode & O_WRITE)) {
+       if ((mode & c->mode) != mode) {
                if (iref)
                        cclose(c);
-               error(Ebadusefd);
-       }
-
-       /* TODO: this is probably wrong.  if you get this from a dev, in the dev's
-        * open, you are probably saving mode directly, without passing it through
-        * openmode. */
-       if ((mode & ~OTRUNC) != c->mode) {
-               warn("Trunc mode issue: mode %o, mode minus trunc %o, chan mode %o\n",
-                        mode, mode & ~OTRUNC, c->mode);
-               if (iref)
-                       cclose(c);
-               error(Ebadusefd);
+               set_errno(EBADF);
+               error("FD access mode failure: chan mode 0x%x, wanted 0x%x",
+                     c->mode, mode);
        }
-
        return c;
 }