Commit 0956254a authored by Miklos Szeredi's avatar Miklos Szeredi

ovl: don't copy up opaqueness

When a copy up of a directory occurs which has the opaque xattr set, the
xattr remains in the upper directory. The immediate behavior with overlayfs
is that the upper directory is not treated as opaque, however after a
remount the opaque flag is used and upper directory is treated as opaque.
This causes files created in the lower layer to be hidden when using
multiple lower directories.

Fix by not copying up the opaque flag.

To reproduce:

 ----8<---------8<---------8<---------8<---------8<---------8<----
mkdir -p l/d/s u v w mnt
mount -t overlay overlay -olowerdir=l,upperdir=u,workdir=w mnt
rm -rf mnt/d/
mkdir -p mnt/d/n
umount mnt
mount -t overlay overlay -olowerdir=u:l,upperdir=v,workdir=w mnt
touch mnt/d/foo
umount mnt
mount -t overlay overlay -olowerdir=u:l,upperdir=v,workdir=w mnt
ls mnt/d
 ----8<---------8<---------8<---------8<---------8<---------8<----
 
output should be:  "foo  n"
Reported-by: default avatarDerek McGowan <dmcg@drizz.net>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=151291Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
Cc: <stable@vger.kernel.org>
parent 29b4817d
...@@ -80,6 +80,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) ...@@ -80,6 +80,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
} }
for (name = buf; name < (buf + list_size); name += strlen(name) + 1) { for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
if (ovl_is_private_xattr(name))
continue;
retry: retry:
size = vfs_getxattr(old, name, value, value_size); size = vfs_getxattr(old, name, value, value_size);
if (size == -ERANGE) if (size == -ERANGE)
......
...@@ -191,7 +191,7 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) ...@@ -191,7 +191,7 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
return err; return err;
} }
static bool ovl_is_private_xattr(const char *name) bool ovl_is_private_xattr(const char *name)
{ {
#define OVL_XATTR_PRE_NAME OVL_XATTR_PREFIX "." #define OVL_XATTR_PRE_NAME OVL_XATTR_PREFIX "."
return strncmp(name, OVL_XATTR_PRE_NAME, return strncmp(name, OVL_XATTR_PRE_NAME,
......
...@@ -193,6 +193,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name); ...@@ -193,6 +193,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name);
struct posix_acl *ovl_get_acl(struct inode *inode, int type); struct posix_acl *ovl_get_acl(struct inode *inode, int type);
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags); int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
int ovl_update_time(struct inode *inode, struct timespec *ts, int flags); int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
bool ovl_is_private_xattr(const char *name);
struct inode *ovl_new_inode(struct super_block *sb, umode_t mode); struct inode *ovl_new_inode(struct super_block *sb, umode_t mode);
struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode); struct inode *ovl_get_inode(struct super_block *sb, struct inode *realinode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment