summaryrefslogtreecommitdiff
path: root/fs/overlayfs/copy_up.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/overlayfs/copy_up.c')
-rw-r--r--fs/overlayfs/copy_up.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index daf2afa603d3..9d8ebf0e7237 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -131,7 +131,8 @@ out:
return error;
}
-static int ovl_copy_fileattr(struct path *old, struct path *new)
+static int ovl_copy_fileattr(struct inode *inode, struct path *old,
+ struct path *new)
{
struct fileattr oldfa = { .flags_valid = true };
struct fileattr newfa = { .flags_valid = true };
@@ -145,6 +146,18 @@ static int ovl_copy_fileattr(struct path *old, struct path *new)
if (err)
return err;
+ /*
+ * We cannot set immutable and append-only flags on upper inode,
+ * because we would not be able to link upper inode to upper dir
+ * not set overlay private xattr on upper inode.
+ * Store these flags in overlay.protattr xattr instead.
+ */
+ if (oldfa.flags & OVL_PROT_FS_FLAGS_MASK) {
+ err = ovl_set_protattr(inode, new->dentry, &oldfa);
+ if (err)
+ return err;
+ }
+
BUILD_BUG_ON(OVL_COPY_FS_FLAGS_MASK & ~FS_COMMON_FL);
newfa.flags &= ~OVL_COPY_FS_FLAGS_MASK;
newfa.flags |= (oldfa.flags & OVL_COPY_FS_FLAGS_MASK);
@@ -550,7 +563,7 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
* Copy the fileattr inode flags that are the source of already
* copied i_flags
*/
- err = ovl_copy_fileattr(&c->lowerpath, &upperpath);
+ err = ovl_copy_fileattr(inode, &c->lowerpath, &upperpath);
if (err)
return err;
}