| From 5e2b8828ff3d79aca8c3a1730652758753205b61 Mon Sep 17 00:00:00 2001 |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| Date: Sat, 1 Oct 2016 07:32:32 +0200 |
| Subject: fuse: invalidate dir dentry after chmod |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| |
| commit 5e2b8828ff3d79aca8c3a1730652758753205b61 upstream. |
| |
| Without "default_permissions" the userspace filesystem's lookup operation |
| needs to perform the check for search permission on the directory. |
| |
| If directory does not allow search for everyone (this is quite rare) then |
| userspace filesystem has to set entry timeout to zero to make sure |
| permissions are always performed. |
| |
| Changing the mode bits of the directory should also invalidate the |
| (previously cached) dentry to make sure the next lookup will have a chance |
| of updating the timeout, if needed. |
| |
| Reported-by: Jean-Pierre André <jean-pierre.andre@wanadoo.fr> |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/fuse/dir.c | 12 ++++++++++-- |
| 1 file changed, 10 insertions(+), 2 deletions(-) |
| |
| --- a/fs/fuse/dir.c |
| +++ b/fs/fuse/dir.c |
| @@ -1697,14 +1697,22 @@ error: |
| static int fuse_setattr(struct dentry *entry, struct iattr *attr) |
| { |
| struct inode *inode = d_inode(entry); |
| + int ret; |
| |
| if (!fuse_allow_current_process(get_fuse_conn(inode))) |
| return -EACCES; |
| |
| if (attr->ia_valid & ATTR_FILE) |
| - return fuse_do_setattr(inode, attr, attr->ia_file); |
| + ret = fuse_do_setattr(inode, attr, attr->ia_file); |
| else |
| - return fuse_do_setattr(inode, attr, NULL); |
| + ret = fuse_do_setattr(inode, attr, NULL); |
| + |
| + if (!ret) { |
| + /* Directory mode changed, may need to revalidate access */ |
| + if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) |
| + fuse_invalidate_entry_cache(entry); |
| + } |
| + return ret; |
| } |
| |
| static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, |