[PATCH] libfuse: callback to invalidate cached children denties

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] libfuse: callback to invalidate cached children denties

Ashish Sangwan
This patch solves the following issue:
([bug #15](https://github.com/libfuse/libfuse/issues/15)): if the
`default_permissions` mount option is not used, the results of the
first permission check performed by the file system for a directory
entry will be re-used for subsequent accesses as long as the inode of
the accessed entry is present in the kernel cache - even if the
permissions have since changed, and even if the subsequent access is
made by a different user.
This bug needs to be fixed in the Linux kernel and has been known
since 2006 but unfortunately no fix has been applied yet. If you
depend on correct permission handling for FUSE file systems, the only
workaround is to use `default_permissions` (which does not currently
support ACLs), or to completely disable caching of directory entry
attributes. Alternatively, the severity of the bug can be somewhat
reduced by not using the `allow_other` mount option.

Now we can use the callback fuse_lowlevel_notify_inval_dircache_entries
to invalidate the cached entries when the execute permission from the
parent directory is revoked.

Signed-off-by: Ashish Sangwan <[hidden email]>
---
 include/fuse_kernel.h   |  5 +++++
 include/fuse_lowlevel.h | 12 ++++++++++++
 lib/fuse_lowlevel.c     | 18 ++++++++++++++++++
 lib/fuse_versionscript  |  1 +
 4 files changed, 36 insertions(+)

diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index c9aca04..a274a10 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -370,6 +370,7 @@ enum fuse_notify_code {
  FUSE_NOTIFY_STORE = 4,
  FUSE_NOTIFY_RETRIEVE = 5,
  FUSE_NOTIFY_DELETE = 6,
+  FUSE_NOTIFY_INVAL_DIRCACHE_ENTRIES = 7,
  FUSE_NOTIFY_CODE_MAX,
 };
 
@@ -711,6 +712,10 @@ struct fuse_direntplus {
 #define FUSE_DIRENTPLUS_SIZE(d) \
  FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
 
+struct fuse_notify_inval_dircache_entries_out {
+  uint64_t parent;
+};
+
 struct fuse_notify_inval_inode_out {
  uint64_t ino;
  int64_t off;
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index a01dbf6..9e0cd63 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1422,6 +1422,18 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
      const char *name, size_t namelen);
 
 /**
+ * Notify to invalidate all the cached children dentries of the
+ * parent directory inode. This will result in further lookups for the
+ * children reaching the library. This could be used when the
+ * low level implementation has its own security checks.
+ *
+ * @param ch the channel through which to send the invalidation.
+ * @param parent inode number
+ * @return zero for success, -errno for failure
+ */
+int fuse_lowlevel_notify_inval_dircache_entries(struct fuse_chan *ch,
+                                                fuse_ino_t parent);
+/**
  * Notify to invalidate parent attributes and delete the dentry matching
  * parent/name if the dentry's inode number matches child (otherwise it
  * will invalidate the matching dentry).
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index d3a8d3b..2f9061a 100755
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -2101,6 +2101,24 @@ int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
  }
 }
 
+int fuse_lowlevel_notify_inval_dircache_entries(struct fuse_chan *ch,
+                                                fuse_ino_t ino)
+{
+  struct fuse_notify_inval_dircache_entries_out outarg;
+  struct fuse_ll *f;
+  struct iovec iov[2];
+
+  if (!ch)
+    return -EINVAL;
+  f = fuse_chan_session(ch)->f;
+  if (!f)
+    return -ENODEV;
+  outarg.parent = ino;
+  iov[1].iov_base = &outarg;
+  iov[1].iov_len = sizeof(outarg);
+  return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_DIRCACHE_ENTRIES, iov, 2);
+}
+
 int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
      off_t off, off_t len)
 {
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 08dafbd..a9cef5f 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -125,6 +125,7 @@ FUSE_3.0 {
  fuse_lowlevel_notify_delete;
  fuse_fs_flock;
  fuse_fs_fallocate;
+ fuse_lowlevel_notify_inval_dircache_entries;
 
  local:
  *;
--
1.9.1


------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are
consuming the most bandwidth. Provides multi-vendor support for NetFlow,
J-Flow, sFlow and other flows. Make informed decisions using capacity
planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e
--
fuse-devel mailing list
To unsubscribe or subscribe, visit https://lists.sourceforge.net/lists/listinfo/fuse-devel