aboutsummaryrefslogtreecommitdiffstats
path: root/fs/orangefs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/orangefs/file.c')
-rw-r--r--fs/orangefs/file.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index a5612abc0936..c740159d9ad1 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -46,8 +46,9 @@ static int flush_racache(struct inode *inode)
* Post and wait for the I/O upcall to finish
*/
ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inode,
- loff_t *offset, struct iov_iter *iter, size_t total_size,
- loff_t readahead_size, struct orangefs_write_range *wr, int *index_return)
+ loff_t *offset, struct iov_iter *iter, size_t total_size,
+ loff_t readahead_size, struct orangefs_write_range *wr,
+ int *index_return, struct file *file)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_khandle *handle = &orangefs_inode->refn.khandle;
@@ -55,6 +56,8 @@ ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inode,
int buffer_index;
ssize_t ret;
size_t copy_amount;
+ int open_for_read;
+ int open_for_write;
new_op = op_alloc(ORANGEFS_VFS_OP_FILE_IO);
if (!new_op)
@@ -90,6 +93,38 @@ populate_shared_memory:
new_op->upcall.uid = from_kuid(&init_user_ns, wr->uid);
new_op->upcall.gid = from_kgid(&init_user_ns, wr->gid);
}
+ /*
+ * Orangefs has no open, and orangefs checks file permissions
+ * on each file access. Posix requires that file permissions
+ * be checked on open and nowhere else. Orangefs-through-the-kernel
+ * needs to seem posix compliant.
+ *
+ * The VFS opens files, even if the filesystem provides no
+ * method. We can see if a file was successfully opened for
+ * read and or for write by looking at file->f_mode.
+ *
+ * When writes are flowing from the page cache, file is no
+ * longer available. We can trust the VFS to have checked
+ * file->f_mode before writing to the page cache.
+ *
+ * The mode of a file might change between when it is opened
+ * and IO commences, or it might be created with an arbitrary mode.
+ *
+ * We'll make sure we don't hit EACCES during the IO stage by
+ * using UID 0. Some of the time we have access without changing
+ * to UID 0 - how to check?
+ */
+ if (file) {
+ open_for_write = file->f_mode & FMODE_WRITE;
+ open_for_read = file->f_mode & FMODE_READ;
+ } else {
+ open_for_write = 1;
+ open_for_read = 0; /* not relevant? */
+ }
+ if ((type == ORANGEFS_IO_WRITE) && open_for_write)
+ new_op->upcall.uid = 0;
+ if ((type == ORANGEFS_IO_READ) && open_for_read)
+ new_op->upcall.uid = 0;
gossip_debug(GOSSIP_FILE_DEBUG,
"%s(%pU): offset: %llu total_size: %zd\n",