aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2012-08-09 16:47:21 +0100
committerJohn Rigby <john.rigby@linaro.org>2012-08-15 23:46:27 -0600
commit40c80f09ec3ca6f4d5ed87017eaee4254b1ad768 (patch)
tree0f3349650e2d4ec7bd4e0ba1cc2e02be38f2a83d
parent7d9db60a6490dae9e643914700b72e731492d532 (diff)
overlayfs: copy up i_uid/i_gid from the underlying inode
YAMA et al rely on on i_uid/i_gid to be populated in order to perform their checks. While these really cannot be guarenteed as the underlying filesystem may not even have the concept, they are expected to be filled when possible. To quote Al Viro: "Ideally, yes, we'd want to have ->i_uid used only by fs-specific code and helpers used by that fs (including those that are implicit defaults). [...] In practice we have enough places where uid/gid is used directly to make setting them practically a requirement - places like /proc/<pid>/ can get away with not doing that, but only because shitloads of syscalls are not allowed on those anyway, permissions or no permissions. In anything general-purpose you really need to set it." Copy up the underlying filesystem information into the overlayfs inode when we create it. BugLink: http://bugs.launchpad.net/bugs/944386 Signed-off-by: Andy Whitcroft <apw@canonical.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r--fs/overlayfs/dir.c2
-rw-r--r--fs/overlayfs/inode.c2
-rw-r--r--fs/overlayfs/overlayfs.h6
-rw-r--r--fs/overlayfs/super.c1
4 files changed, 11 insertions, 0 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 40650c43f5c..c4446c45280 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -304,6 +304,7 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
}
}
ovl_dentry_update(dentry, newdentry);
+ ovl_copyattr(newdentry->d_inode, inode);
d_instantiate(dentry, inode);
inode = NULL;
newdentry = NULL;
@@ -446,6 +447,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
new->d_fsdata);
if (!newinode)
goto link_fail;
+ ovl_copyattr(upperdir->d_inode, newinode);
ovl_dentry_version_inc(new->d_parent);
ovl_dentry_update(new, newdentry);
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index f3a534fbb31..e7ab09bda2c 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -31,6 +31,8 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
mutex_lock(&upperdentry->d_inode->i_mutex);
err = notify_change(upperdentry, attr);
+ if (!err)
+ ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
mutex_unlock(&upperdentry->d_inode->i_mutex);
return err;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index fe1241dd331..1cba38ff39a 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -56,6 +56,12 @@ int ovl_removexattr(struct dentry *dentry, const char *name);
struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
struct ovl_entry *oe);
+static inline void ovl_copyattr(struct inode *from, struct inode *to)
+{
+ to->i_uid = from->i_uid;
+ to->i_gid = from->i_gid;
+}
+
/* dir.c */
extern const struct inode_operations ovl_dir_inode_operations;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 64d26959eb7..9808408b579 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -343,6 +343,7 @@ static int ovl_do_lookup(struct dentry *dentry)
oe);
if (!inode)
goto out_dput;
+ ovl_copyattr(realdentry->d_inode, inode);
}
if (upperdentry)