From 8d11f28e89a4f18e90ad718d6b03785b84011435 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 6 Sep 2016 13:40:32 -0400 Subject: [PATCH] ovl: during copy up, switch to mounter's creds early Now, we have the notion that copy up of a file is done with the creds of mounter of overlay filesystem (as opposed to task). Right now before we switch creds, we do some vfs_getattr() operations in the context of task and that itself can fail. We should do that getattr() using the creds of mounter instead. So this patch switches to mounter's creds early during copy up process so that even vfs_getattr() is done with mounter's creds. Do not call revert_creds() unless we have already called ovl_override_creds(). [Reported by Arnd Bergmann] Signed-off-by: Vivek Goyal Signed-off-by: Miklos Szeredi Orabug: 25684456 (backport upstream commit 8eac98b8beb4711c4ab61822cac077fd6660e820) Signed-off-by: Anand Jain Acked-by: James Morris Reviewed-by: James Morris --- fs/overlayfs/copy_up.c | 9 +++------ fs/overlayfs/inode.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index a9b98cc12f18..aa2fcb7baeb8 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -325,7 +325,6 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, struct path parentpath; struct dentry *upperdir; struct dentry *upperdentry; - const struct cred *old_cred; char *link = NULL; if (WARN_ON(!workdir)) @@ -344,8 +343,6 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, return PTR_ERR(link); } - old_cred = ovl_override_creds(dentry->d_sb); - err = -EIO; if (lock_rename(workdir, upperdir) != NULL) { pr_err("overlayfs: failed to lock workdir+upperdir\n"); @@ -366,7 +363,6 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, } out_unlock: unlock_rename(workdir, upperdir); - revert_creds(old_cred); if (link) free_page((unsigned long) link); @@ -376,9 +372,9 @@ out_unlock: int ovl_copy_up(struct dentry *dentry) { - int err; + int err = 0; + const struct cred *old_cred = ovl_override_creds(dentry->d_sb); - err = 0; while (!err) { struct dentry *next; struct dentry *parent; @@ -410,6 +406,7 @@ int ovl_copy_up(struct dentry *dentry) dput(parent); dput(next); } + revert_creds(old_cred); return err; } diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 4d3643d17cd4..fcede74c4775 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -20,6 +20,7 @@ static int ovl_copy_up_truncate(struct dentry *dentry) struct dentry *parent; struct kstat stat; struct path lowerpath; + const struct cred *old_cred; parent = dget_parent(dentry); err = ovl_copy_up(parent); @@ -27,12 +28,14 @@ static int ovl_copy_up_truncate(struct dentry *dentry) goto out_dput_parent; ovl_path_lower(dentry, &lowerpath); - err = vfs_getattr(&lowerpath, &stat); - if (err) - goto out_dput_parent; - stat.size = 0; - err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); + old_cred = ovl_override_creds(dentry->d_sb); + err = vfs_getattr(&lowerpath, &stat); + if (!err) { + stat.size = 0; + err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat); + } + revert_creds(old_cred); out_dput_parent: dput(parent); -- 2.50.1