9ns: Add helpers for permissions checks
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 22 Feb 2018 21:19:33 +0000 (16:19 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 6 Apr 2018 19:22:56 +0000 (15:22 -0400)
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/ns.h
kern/src/ns/dev.c
kern/src/ns/util.c

index 883ba31..1e31279 100644 (file)
@@ -1003,6 +1003,12 @@ void printqid(void (*putch) (int, void **), void **putdat, struct qid *q);
 void printcname(void (*putch) (int, void **), void **putdat, struct cname *c);
 void printchan(void (*putch) (int, void **), void **putdat, struct chan *c);
 
+/* kern/src/ns/util.c */
+bool caller_is_username(char *uid);
+bool caller_has_perms(char *fileuid, uint32_t perm, int omode);
+bool caller_has_dir_perms(struct dir *dir, int omode);
+void dir_perm_check(struct dir *dir, int omode);
+
 static inline int abs(int a)
 {
        if (a < 0)
index 7012b5a..bc8db6e 100644 (file)
@@ -391,27 +391,13 @@ devdirread(struct chan *c, char *d, long n,
 }
 
 /*
- * error(EPERM, ERROR_FIXME) if open permission not granted for
- * current->user.name
+ * Throws an error if open permission not granted for current->user.name
  */
 void devpermcheck(char *fileuid, uint32_t perm, int omode)
 {
-       int rwx;
-
-       /* select user, group, or other from the traditional rwxrwxrwx, shifting
-        * into the upper-most position */
-       if (strcmp(current->user.name, fileuid) == 0)
-               perm <<= 0;
-       else if (iseve())
-               perm <<= 3;
-       else
-               perm <<= 6;
-       /* translate omode into things like S_IRUSR (just one set of rwx------).
-        * Plan 9 originally only returned 0400 0200 0600 and 0100 here; it didn't
-        * seem to handle O_EXEC being mixed readable or writable. */
-       rwx = omode_to_rwx(omode);
-       if ((rwx & perm) != rwx)
-               error(EPERM, "devpermcheck(%s, 0%o, 0%o) failed", fileuid, perm, omode);
+       if (!caller_has_perms(fileuid, perm, omode))
+               error(EPERM, "permcheck(user: %s, rwx: 0%o, omode 0%o) failed",
+                     fileuid, perm, omode);
 }
 
 struct chan *devopen(struct chan *c, int omode, struct dirtab *tab, int ntab,
index b0e28bc..b3254c6 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <err.h>
 #include <syscall.h>
+#include <smp.h>
 
 /* Copies n bytes from mem + offset into buf, similar to a read() call. */
 int readmem(unsigned long offset, char *buf, unsigned long n,
@@ -97,3 +98,43 @@ int omode_to_9p_accmode(int open_flags)
                                  };
        return acc_opts[open_flags & O_ACCMODE];
 }
+
+/* TODO: This assumes UID isn't concurrently changed */
+bool caller_is_username(char *uid)
+{
+       struct username *current_user = current ? &current->user : &eve;
+
+       return strcmp(current_user->name, uid) == 0;
+}
+
+/* Checks if current->user has permissions for omode access on something with
+ * {owner_fileuid, perm} */
+bool caller_has_perms(char *fileuid, uint32_t perm, int omode)
+{
+       int rwx;
+
+       perm &= S_PMASK;        /* technically unnecessary; good for clarity */
+       /* select user, group, or other from the traditional rwxrwxrwx, shifting
+        * into the upper-most position */
+       if (caller_is_username(fileuid))
+               perm <<= 0;
+       else if (iseve())
+               perm <<= 3;
+       else
+               perm <<= 6;
+       /* translate omode into things like S_IRUSR (just one set of rwx------).
+        * Plan 9 originally only returned 0400 0200 0600 and 0100 here; it didn't
+        * seem to handle O_EXEC being mixed readable or writable. */
+       rwx = omode_to_rwx(omode);
+       return (rwx & perm) == rwx;
+}
+
+bool caller_has_dir_perms(struct dir *dir, int omode)
+{
+       return caller_has_perms(dir->uid, READ_ONCE(dir->mode), omode);
+}
+
+void dir_perm_check(struct dir *dir, int omode)
+{
+       devpermcheck(dir->uid, READ_ONCE(dir->mode) & S_PMASK, omode);
+}