9ns: Clean up the dir->mode bits
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Mar 2018 15:32:16 +0000 (11:32 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:33:44 +0000 (14:33 -0400)
The lower 9 bits are the classic rwxrwxrwx bits.  The upper bits contain
things like "is a directory."

'mode' is a bit confusing, especially if you are familiar with the
POSIX/glibc world.  dir->mode is the permissions, which we get from the
'perm' argument to create (i.e. SYS_openat with O_CREATE).  That is
different from the 'mode' argument to open(), which is the e.g. O_RDWR
flags for the *chan* (file in Unix) - not the filesystem file (inode in
Unix).

Good times.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/ns.h
kern/src/ns/fs_file.c
kern/src/syscall.c

index aa82108..9bb03b9 100644 (file)
@@ -126,9 +126,9 @@ extern int parseether(uint8_t * unused_uint8_p_t, char *unused_char_p_t);
 #define DMWRITABLE     0x08000000      /* non-standard, for select() */
 #define DMREADABLE     0x04000000      /* non-standard, for select() */
 #define DMSYMLINK      0x02000000      /* symlink -- from 9p2000.u */
-#define DMREAD         0x4     /* mode bit for read permission */
-#define DMWRITE                0x2     /* mode bit for write permission */
-#define DMEXEC         0x1     /* mode bit for execute permission */
+/* The lower parts of dir.mode are the three rwx perms (S_PMASK) */
+#define DMMODE_BITS (DMDIR | DMAPPEND | DMEXCL | DMMOUNT | DMWRITABLE \
+                     | DMREADABLE | DMSYMLINK)
 
 struct qid {
        uint64_t path;
index 680bbf0..dc556df 100644 (file)
@@ -86,6 +86,8 @@ void fs_file_init_dir(struct fs_file *f, int dir_type, int dir_dev,
                dir->qid.type |= QTSYMLINK;
        if (!(dir->qid.type & (QTSYMLINK | QTDIR)))
                dir->qid.type |= QTFILE;
+       /* dir->mode stores all the DM bits, but note that userspace can only affect
+        * the permissions (S_PMASK) bits. */
        dir->mode = perm;
        __set_acmtime(f, FSF_ATIME | FSF_BTIME | FSF_MTIME | FSF_CTIME);
        dir->length = 0;
@@ -416,6 +418,7 @@ static void wstat_mode(struct fs_file *f, int new_mode)
                error(EPERM, "wrong user for wstat, need %s", f->dir.uid);
        /* Only allowing changes in permissions, not random stuff like whether it is
         * a directory or symlink. */
+       static_assert(!(DMMODE_BITS & S_PMASK));
        mode = (f->dir.mode & ~S_PMASK) | (new_mode & S_PMASK);
        WRITE_ONCE(f->dir.mode, mode);
        __set_acmtime(f, FSF_CTIME);
index a117797..27ce840 100644 (file)
@@ -1783,7 +1783,6 @@ static intreg_t sys_openat(struct proc *p, int fromfd, const char *path,
        if (!t_path)
                return -1;
        sysc_save_str("open %s at fd %d", t_path, fromfd);
-       mode &= ~p->umask;
        fd = sysopenat(fromfd, t_path, oflag);
        /* successful lookup with CREATE and EXCL is an error */
        if (fd != -1) {
@@ -1795,7 +1794,9 @@ static intreg_t sys_openat(struct proc *p, int fromfd, const char *path,
                }
        } else {
                if (oflag & O_CREATE) {
+                       mode &= ~p->umask;
                        mode &= S_PMASK;
+                       static_assert(!(DMMODE_BITS & S_PMASK));
                        fd = syscreate(t_path, oflag, mode);
                }
        }
@@ -2094,11 +2095,9 @@ intreg_t sys_mkdir(struct proc *p, const char *path, size_t path_l, int mode)
 
        if (!t_path)
                return -1;
-       mode &= S_PMASK;
        mode &= ~p->umask;
-       /* mixing plan9 and glibc here, make sure DMDIR doesn't overlap with any
-        * permissions */
-       static_assert(!(S_PMASK & DMDIR));
+       mode &= S_PMASK;
+       static_assert(!(DMMODE_BITS & S_PMASK));
        retval = syscreate(t_path, O_READ, DMDIR | mode);
        if (retval >= 0) {
                sysclose(retval);