diff options
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8adc1eed164b..0950455914dd 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -418,7 +418,8 @@ static int fuse_revalidate(struct dentry *entry) | |||
418 | struct fuse_conn *fc = get_fuse_conn(inode); | 418 | struct fuse_conn *fc = get_fuse_conn(inode); |
419 | 419 | ||
420 | if (get_node_id(inode) == FUSE_ROOT_ID) { | 420 | if (get_node_id(inode) == FUSE_ROOT_ID) { |
421 | if (current->fsuid != fc->user_id) | 421 | if (!(fc->flags & FUSE_ALLOW_OTHER) && |
422 | current->fsuid != fc->user_id) | ||
422 | return -EACCES; | 423 | return -EACCES; |
423 | } else if (time_before_eq(jiffies, fi->i_time)) | 424 | } else if (time_before_eq(jiffies, fi->i_time)) |
424 | return 0; | 425 | return 0; |
@@ -430,9 +431,31 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
430 | { | 431 | { |
431 | struct fuse_conn *fc = get_fuse_conn(inode); | 432 | struct fuse_conn *fc = get_fuse_conn(inode); |
432 | 433 | ||
433 | if (current->fsuid != fc->user_id) | 434 | if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id) |
434 | return -EACCES; | 435 | return -EACCES; |
435 | else { | 436 | else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { |
437 | int err = generic_permission(inode, mask, NULL); | ||
438 | |||
439 | /* If permission is denied, try to refresh file | ||
440 | attributes. This is also needed, because the root | ||
441 | node will at first have no permissions */ | ||
442 | if (err == -EACCES) { | ||
443 | err = fuse_do_getattr(inode); | ||
444 | if (!err) | ||
445 | err = generic_permission(inode, mask, NULL); | ||
446 | } | ||
447 | |||
448 | /* FIXME: Need some mechanism to revoke permissions: | ||
449 | currently if the filesystem suddenly changes the | ||
450 | file mode, we will not be informed about it, and | ||
451 | continue to allow access to the file/directory. | ||
452 | |||
453 | This is actually not so grave, since the user can | ||
454 | simply keep access to the file/directory anyway by | ||
455 | keeping it open... */ | ||
456 | |||
457 | return err; | ||
458 | } else { | ||
436 | int mode = inode->i_mode; | 459 | int mode = inode->i_mode; |
437 | if ((mask & MAY_WRITE) && IS_RDONLY(inode) && | 460 | if ((mask & MAY_WRITE) && IS_RDONLY(inode) && |
438 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | 461 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) |
@@ -636,6 +659,12 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) | |||
636 | int err; | 659 | int err; |
637 | int is_truncate = 0; | 660 | int is_truncate = 0; |
638 | 661 | ||
662 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | ||
663 | err = inode_change_ok(inode, attr); | ||
664 | if (err) | ||
665 | return err; | ||
666 | } | ||
667 | |||
639 | if (attr->ia_valid & ATTR_SIZE) { | 668 | if (attr->ia_valid & ATTR_SIZE) { |
640 | unsigned long limit; | 669 | unsigned long limit; |
641 | is_truncate = 1; | 670 | is_truncate = 1; |