Skip to content

Commit 316933c

Browse files
committed
Merge tag 'for-linus-5.5-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux
Pull orangefs update from Mike Marshall: "orangefs: posix open permission checking... 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" [ This is "posixish", but not a great solution in the long run, since a proper secure network server shouldn't really trust the client like this. But proper and secure POSIX behavior requires an open method and a resulting cookie for IO of some kind, or similar. - Linus ] * tag 'for-linus-5.5-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux: orangefs: posix open permission checking...
2 parents 911d137 + f9bbb68 commit 316933c

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

fs/orangefs/file.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,18 @@ static int flush_racache(struct inode *inode)
4646
* Post and wait for the I/O upcall to finish
4747
*/
4848
ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inode,
49-
loff_t *offset, struct iov_iter *iter, size_t total_size,
50-
loff_t readahead_size, struct orangefs_write_range *wr, int *index_return)
49+
loff_t *offset, struct iov_iter *iter, size_t total_size,
50+
loff_t readahead_size, struct orangefs_write_range *wr,
51+
int *index_return, struct file *file)
5152
{
5253
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
5354
struct orangefs_khandle *handle = &orangefs_inode->refn.khandle;
5455
struct orangefs_kernel_op_s *new_op = NULL;
5556
int buffer_index;
5657
ssize_t ret;
5758
size_t copy_amount;
59+
int open_for_read;
60+
int open_for_write;
5861

5962
new_op = op_alloc(ORANGEFS_VFS_OP_FILE_IO);
6063
if (!new_op)
@@ -90,6 +93,38 @@ ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inode,
9093
new_op->upcall.uid = from_kuid(&init_user_ns, wr->uid);
9194
new_op->upcall.gid = from_kgid(&init_user_ns, wr->gid);
9295
}
96+
/*
97+
* Orangefs has no open, and orangefs checks file permissions
98+
* on each file access. Posix requires that file permissions
99+
* be checked on open and nowhere else. Orangefs-through-the-kernel
100+
* needs to seem posix compliant.
101+
*
102+
* The VFS opens files, even if the filesystem provides no
103+
* method. We can see if a file was successfully opened for
104+
* read and or for write by looking at file->f_mode.
105+
*
106+
* When writes are flowing from the page cache, file is no
107+
* longer available. We can trust the VFS to have checked
108+
* file->f_mode before writing to the page cache.
109+
*
110+
* The mode of a file might change between when it is opened
111+
* and IO commences, or it might be created with an arbitrary mode.
112+
*
113+
* We'll make sure we don't hit EACCES during the IO stage by
114+
* using UID 0. Some of the time we have access without changing
115+
* to UID 0 - how to check?
116+
*/
117+
if (file) {
118+
open_for_write = file->f_mode & FMODE_WRITE;
119+
open_for_read = file->f_mode & FMODE_READ;
120+
} else {
121+
open_for_write = 1;
122+
open_for_read = 0; /* not relevant? */
123+
}
124+
if ((type == ORANGEFS_IO_WRITE) && open_for_write)
125+
new_op->upcall.uid = 0;
126+
if ((type == ORANGEFS_IO_READ) && open_for_read)
127+
new_op->upcall.uid = 0;
93128

94129
gossip_debug(GOSSIP_FILE_DEBUG,
95130
"%s(%pU): offset: %llu total_size: %zd\n",

fs/orangefs/inode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static int orangefs_writepage_locked(struct page *page,
5555
iov_iter_bvec(&iter, WRITE, &bv, 1, wlen);
5656

5757
ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
58-
len, wr, NULL);
58+
len, wr, NULL, NULL);
5959
if (ret < 0) {
6060
SetPageError(page);
6161
mapping_set_error(page->mapping, ret);
@@ -126,7 +126,7 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow,
126126
wr.uid = ow->uid;
127127
wr.gid = ow->gid;
128128
ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, ow->len,
129-
0, &wr, NULL);
129+
0, &wr, NULL, NULL);
130130
if (ret < 0) {
131131
for (i = 0; i < ow->npages; i++) {
132132
SetPageError(ow->pages[i]);
@@ -311,7 +311,7 @@ static int orangefs_readpage(struct file *file, struct page *page)
311311
iov_iter_bvec(&iter, READ, &bv, 1, PAGE_SIZE);
312312

313313
ret = wait_for_direct_io(ORANGEFS_IO_READ, inode, &off, &iter,
314-
read_size, inode->i_size, NULL, &buffer_index);
314+
read_size, inode->i_size, NULL, &buffer_index, file);
315315
remaining = ret;
316316
/* this will only zero remaining unread portions of the page data */
317317
iov_iter_zero(~0U, &iter);
@@ -651,7 +651,7 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb,
651651
(int)*offset);
652652

653653
ret = wait_for_direct_io(type, inode, offset, iter,
654-
each_count, 0, NULL, NULL);
654+
each_count, 0, NULL, NULL, file);
655655
gossip_debug(GOSSIP_FILE_DEBUG,
656656
"%s(%pU): return from wait_for_io:%d\n",
657657
__func__,

fs/orangefs/orangefs-kernel.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ bool __is_daemon_in_service(void);
398398
*/
399399
int orangefs_revalidate_mapping(struct inode *);
400400
ssize_t wait_for_direct_io(enum ORANGEFS_io_type, struct inode *, loff_t *,
401-
struct iov_iter *, size_t, loff_t, struct orangefs_write_range *, int *);
401+
struct iov_iter *, size_t, loff_t, struct orangefs_write_range *, int *,
402+
struct file *);
402403
ssize_t do_readv_writev(enum ORANGEFS_io_type, struct file *, loff_t *,
403404
struct iov_iter *);
404405

0 commit comments

Comments
 (0)