Unionfs: fix readonly nfs2/3 permission handling
authorErez Zadok <ezk@cs.sunysb.edu>
Tue, 22 Sep 2009 21:44:09 +0000 (17:44 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Tue, 22 Sep 2009 21:44:09 +0000 (17:44 -0400)
In unionfs_permission: NFSv2/3 return EACCES on readonly-exported, locally
readonly-mounted file systems, instead of EROFS like other file systems do.
So we have no choice here but to intercept this and ignore it for NFS
branches marked readonly.  Specifically, we avoid using NFS's own "broken"
->permission method, and rely on generic_permission() to do basic checking
for us.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/compat.h
fs/unionfs/inode.c

index 3d93798f39bee9be7dd761d804fce078d8515d54..42f5ce353297f673d0872e70cd1987d3b3b76275 100644 (file)
@@ -24,6 +24,9 @@ extern void *krealloc2(size_t oldsize, void *ptr, size_t newsize, int flags);
 #define        i_mutex                 i_sem
 #define kzalloc(num, flags)    kcalloc(1, (num), (flags))
 #define UNIONFS_SUPER_MAGIC    0xf15f083d
+#ifndef NFS_SUPER_MAGIC
+# define NFS_SUPER_MAGIC 0x6969 /* from <linx/nfs_fs.h> */
+#endif /* not NFS_SUPER_MAGIC */
 #define        POISON_INUSE    0x5a    /* for use-uninitialised poisoning */
 #define SEEK_SET       0       /* seek relative to beginning of file */
 #define SEEK_CUR       1       /* seek relative to current file position */
index 2b4fceb57000b567659decfb50580981f834d106..afd21e2f64111ec14a2122af358627e6646df761 100644 (file)
@@ -836,6 +836,20 @@ static int unionfs_permission(struct inode *inode, int mask,
                                err = 0;
                }
 
+               /*
+                * NFS HACK: NFSv2/3 return EACCES on readonly-exported,
+                * locally readonly-mounted file systems, instead of EROFS
+                * like other file systems do.  So we have no choice here
+                * but to intercept this and ignore it for NFS branches
+                * marked readonly.  Specifically, we avoid using NFS's own
+                * "broken" ->permission method, and rely on
+                * generic_permission() to do basic checking for us.
+                */
+               if (err && err == -EACCES &&
+                   is_robranch_super(inode->i_sb, bindex) &&
+                   lower_inode->i_sb->s_magic == NFS_SUPER_MAGIC)
+                       err = permission(lower_inode, mask, NULL);
+
                /*
                 * The permissions are an intersection of the overall directory
                 * permissions, so we fail if one fails.