Add more restrictive oflag checks to sys_open
authorKevin Klues <klueska@cs.berkeley.edu>
Thu, 14 Aug 2014 00:56:22 +0000 (17:56 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 14 Aug 2014 00:56:22 +0000 (17:56 -0700)
Also make sure and error out with EISDIR if the named file is a
directory and oflag includes O_WRONLY or O_RDWR. This has only been
added to the vfs.

kern/src/syscall.c
kern/src/vfs.c

index 7ebeca9..cfc23f5 100644 (file)
@@ -1136,6 +1136,13 @@ static intreg_t sys_open(struct proc *p, const char *path, size_t path_l,
        struct file *file;
 
        printd("File %s Open attempt oflag %x mode %x\n", path, oflag, mode);
+       /* Make sure only one of O_RDONLY, O_WRONLY, O_RDWR is specified in flags */
+       if (((flags & (O_RDONLY | O_WRONLY | O_RDWR)) != O_RDONLY) &&
+           ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) != O_WRONLY) &&
+           ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) != O_RDWR)) {
+               set_errno(EINVAL);
+               return -1;
+       }
        char *t_path = user_strdup_errno(p, path, path_l);
        if (!t_path)
                return -1;
index 9a2de2a..38560c8 100644 (file)
@@ -1330,7 +1330,16 @@ struct file *do_file_open(char *path, int flags, int mode)
        nd->intent = LOOKUP_OPEN;
        error = path_lookup(path, LOOKUP_FOLLOW, nd);
        if (!error) {
-               /* Still need to make sure we didn't want to O_EXCL create */
+               /* If this is a directory, make sure we are opening with O_RDONLY.
+                * Unfortunately we can't just check for O_RDONLY directly because its
+                * value is 0x0.  We instead have to make sure it's not O_WRONLY and
+                * not O_RDWR explicitly. */
+               if (S_ISDIR(nd->dentry->d_inode->i_mode) &&
+                   ((flags & O_WRONLY) || (flags & O_RDWR))) {
+                       set_errno(EISDIR);
+                       goto out_path_only;
+               }
+               /* Also need to make sure we didn't want to O_EXCL create */
                if ((flags & O_CREAT) && (flags & O_EXCL)) {
                        set_errno(EEXIST);
                        goto out_path_only;