mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
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. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJd6qoUAAoJEM9EDqnrzg2+SHQQAI8osluG1xDle0Ur0y/XQrWR z/1+mA/ZJpkaC2KPJ3F/B93ZR7TSSb6xB/u/EoxfqVQDoVpodP3PzcvSosRsePOk OYo67xit7YRcg2nQF5kEjR+wYbW/T1j55oQzrWxLvYr+FhlDZLJyn0xuSaGvvuKQ kWqNwPQpIZwNR1ZJ6Yjif86kR4sWF5htoy976x5ScvoeOb08dNHQn2je5oXH/eKH zwWBVYTeZTAIVCs9YV2UM4gi5/0pysjSL58jP7+ckLj79ozBoyhc9cRB4ez0cFyc 4+4dW9zZ1GAfvmbsFzvCfKb2Syz4JkStGJQGST+cgH9ldp70R8AdRjzYfZGXa2af 9I/jRgrVBsU/jo++a1npMy2j44+2GvhoValzKePwiCGTOB/f80XsmB9p9qci8JCv ucVzJwbhjxPKphUpnW8Gg7F2gWr2ULhv+wKRmAb3tF+bIFPjn7KjyzFfUAS3FY1s iwgci0Mw9NLLlvX511N0wiUGo6V9A9r7XsZQjScmm/3ybUhMyJAYoe81OO60Xwnv 2s+V0Tv9ah4b+EF0J0qtQ7GzsoKDBu+ZWqGieiOXDWTVixY2gV6CetnR7veeSeQh s9OeqY8qaSYiV9KtBNZp56IS4PuADDgxnRB1pXTUUPgapuElEtvYC1BUovidMMmh kLQEpYdSGrkLRah4hKsg =9AOz -----END PGP SIGNATURE----- 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...
This commit is contained in:
commit
316933cf74
@ -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",
|
||||
|
@ -55,7 +55,7 @@ static int orangefs_writepage_locked(struct page *page,
|
||||
iov_iter_bvec(&iter, WRITE, &bv, 1, wlen);
|
||||
|
||||
ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
|
||||
len, wr, NULL);
|
||||
len, wr, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
SetPageError(page);
|
||||
mapping_set_error(page->mapping, ret);
|
||||
@ -126,7 +126,7 @@ static int orangefs_writepages_work(struct orangefs_writepages *ow,
|
||||
wr.uid = ow->uid;
|
||||
wr.gid = ow->gid;
|
||||
ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, ow->len,
|
||||
0, &wr, NULL);
|
||||
0, &wr, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
for (i = 0; i < ow->npages; i++) {
|
||||
SetPageError(ow->pages[i]);
|
||||
@ -311,7 +311,7 @@ static int orangefs_readpage(struct file *file, struct page *page)
|
||||
iov_iter_bvec(&iter, READ, &bv, 1, PAGE_SIZE);
|
||||
|
||||
ret = wait_for_direct_io(ORANGEFS_IO_READ, inode, &off, &iter,
|
||||
read_size, inode->i_size, NULL, &buffer_index);
|
||||
read_size, inode->i_size, NULL, &buffer_index, file);
|
||||
remaining = ret;
|
||||
/* this will only zero remaining unread portions of the page data */
|
||||
iov_iter_zero(~0U, &iter);
|
||||
@ -651,7 +651,7 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb,
|
||||
(int)*offset);
|
||||
|
||||
ret = wait_for_direct_io(type, inode, offset, iter,
|
||||
each_count, 0, NULL, NULL);
|
||||
each_count, 0, NULL, NULL, file);
|
||||
gossip_debug(GOSSIP_FILE_DEBUG,
|
||||
"%s(%pU): return from wait_for_io:%d\n",
|
||||
__func__,
|
||||
|
@ -398,7 +398,8 @@ bool __is_daemon_in_service(void);
|
||||
*/
|
||||
int orangefs_revalidate_mapping(struct inode *);
|
||||
ssize_t wait_for_direct_io(enum ORANGEFS_io_type, struct inode *, loff_t *,
|
||||
struct iov_iter *, size_t, loff_t, struct orangefs_write_range *, int *);
|
||||
struct iov_iter *, size_t, loff_t, struct orangefs_write_range *, int *,
|
||||
struct file *);
|
||||
ssize_t do_readv_writev(enum ORANGEFS_io_type, struct file *, loff_t *,
|
||||
struct iov_iter *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user