summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2015-10-12 11:11:44 -0400
committerMiklos Szeredi <miklos@szeredi.hu>2015-10-12 11:11:44 -0400
commit8d3095f4ad47ac409440a0ba1c80e13519ff867d (patch)
treedad58c7957fd832f1b7fbcbaa8a8fb0091177187 /fs/overlayfs/inode.c
parent5ffdbe8bf1e485026e1c7e4714d2841553cf0b40 (diff)
ovl: default permissions
Add mount option "default_permissions" to alter the way permissions are calculated. Without this option and prior to this patch permissions were calculated by underlying lower or upper filesystem. With this option the permissions are calculated by overlayfs based on the file owner, group and mode bits. This has significance for example when a read-only exported NFS filesystem is used as a lower layer. In this case the underlying NFS filesystem will reply with EROFS, in which case all we know is that the filesystem is read-only. But that's not what we are interested in, we are interested in whether the access would be allowed if the filesystem wasn't read-only; the server doesn't tell us that, and would need updating at various levels, which doesn't seem practicable. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r--fs/overlayfs/inode.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index ec0c2a050043..76546314e35f 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -98,6 +98,29 @@ int ovl_permission(struct inode *inode, int mask)
98 98
99 realdentry = ovl_entry_real(oe, &is_upper); 99 realdentry = ovl_entry_real(oe, &is_upper);
100 100
101 if (ovl_is_default_permissions(inode)) {
102 struct kstat stat;
103 struct path realpath = { .dentry = realdentry };
104
105 if (mask & MAY_NOT_BLOCK)
106 return -ECHILD;
107
108 realpath.mnt = ovl_entry_mnt_real(oe, inode, is_upper);
109
110 err = vfs_getattr(&realpath, &stat);
111 if (err)
112 return err;
113
114 if ((stat.mode ^ inode->i_mode) & S_IFMT)
115 return -ESTALE;
116
117 inode->i_mode = stat.mode;
118 inode->i_uid = stat.uid;
119 inode->i_gid = stat.gid;
120
121 return generic_permission(inode, mask);
122 }
123
101 /* Careful in RCU walk mode */ 124 /* Careful in RCU walk mode */
102 realinode = ACCESS_ONCE(realdentry->d_inode); 125 realinode = ACCESS_ONCE(realdentry->d_inode);
103 if (!realinode) { 126 if (!realinode) {