Perform basic mode checks for VFS I/O
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 9 Sep 2015 15:06:36 +0000 (11:06 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Sep 2015 19:14:00 +0000 (15:14 -0400)
Prior to this, you could (probably) read and write to files that lacked
the appropriate permissions.

There is a rough sort of protection, in that certain file ops don't
exist.  For instance, there is no generic_dir_write(), so directories
are never writable.  But that doesn't help when a certain type of object
(e.g. file, dir) can be writable but happens to not be for a particular
FD / struct file.

kern/src/vfs.c

index b01adf8..bcab6a4 100644 (file)
@@ -1197,6 +1197,10 @@ ssize_t generic_file_read(struct file *file, char *buf, size_t count,
        /* Consider pushing some error checking higher in the VFS */
        if (!count)
                return 0;
+       if (!(file->f_flags & O_READ)) {
+               set_errno(EBADF);
+               return 0;
+       }
        if (orig_off >= file->f_dentry->d_inode->i_size)
                return 0; /* EOF */
        /* Make sure we don't go past the end of the file */
@@ -1257,6 +1261,10 @@ ssize_t generic_file_write(struct file *file, const char *buf, size_t count,
        /* Consider pushing some error checking higher in the VFS */
        if (!count)
                return 0;
+       if (!(file->f_flags & O_WRITE)) {
+               set_errno(EBADF);
+               return 0;
+       }
        if (file->f_flags & O_APPEND) {
                spin_lock(&file->f_dentry->d_inode->i_lock);
                orig_off = file->f_dentry->d_inode->i_size;
@@ -1318,6 +1326,10 @@ ssize_t generic_dir_read(struct file *file, char *u_buf, size_t count,
        }
        if (!count)
                return 0;
+       if (!(file->f_flags & O_READ)) {
+               set_errno(EBADF);
+               return 0;
+       }
        /* start readdir from where it left off: */
        dirent->d_off = *offset;
        for (   ;