Commit 91ff20f3 authored by Amir Goldstein's avatar Amir Goldstein Committed by Miklos Szeredi

ovl: fix missing override creds in link of a metacopy upper

Theodore Ts'o reported a v4.19 regression with docker-dropbox:
https://marc.info/?l=linux-fsdevel&m=154070089431116&w=2

"I was rebuilding my dropbox Docker container, and it failed in 4.19
 with the following error:
 ...
 dpkg: error: error creating new backup file \
              '/var/lib/dpkg/status-old': Invalid cross-device link"

The problem did not reproduce with metacopy feature disabled.
The error was caused by insufficient credentials to set
"trusted.overlay.redirect" xattr on link of a metacopy file.

Reproducer:

 echo Y > /sys/module/overlay/parameters/redirect_dir
 echo Y > /sys/module/overlay/parameters/metacopy
 cd /tmp
 mkdir l u w m
 chmod 777 l u
 touch l/foo
 ln l/foo l/link
 chmod 666 l/foo
 mount -t overlay none -olowerdir=l,upperdir=u,workdir=w m
 su fsgqa
 ln m/foo m/bar
 [   21.455823] overlayfs: failed to set redirect (-1)
 ln: failed to create hard link 'm/bar' => 'm/foo':\
     Invalid cross-device link
Reported-by: default avatarTheodore Y. Ts'o <tytso@mit.edu>
Reported-by: default avatarMaciej Zięba <maciekz82@gmail.com>
Fixes: 4120fe64 ("ovl: Set redirect on upper inode when it is linked")
Cc: <stable@vger.kernel.org> # v4.19
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Acked-by: default avatarVivek Goyal <vgoyal@redhat.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 9ff01193
...@@ -651,6 +651,18 @@ static int ovl_symlink(struct inode *dir, struct dentry *dentry, ...@@ -651,6 +651,18 @@ static int ovl_symlink(struct inode *dir, struct dentry *dentry,
return ovl_create_object(dentry, S_IFLNK, 0, link); return ovl_create_object(dentry, S_IFLNK, 0, link);
} }
static int ovl_set_link_redirect(struct dentry *dentry)
{
const struct cred *old_cred;
int err;
old_cred = ovl_override_creds(dentry->d_sb);
err = ovl_set_redirect(dentry, false);
revert_creds(old_cred);
return err;
}
static int ovl_link(struct dentry *old, struct inode *newdir, static int ovl_link(struct dentry *old, struct inode *newdir,
struct dentry *new) struct dentry *new)
{ {
...@@ -670,7 +682,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir, ...@@ -670,7 +682,7 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
goto out_drop_write; goto out_drop_write;
if (ovl_is_metacopy_dentry(old)) { if (ovl_is_metacopy_dentry(old)) {
err = ovl_set_redirect(old, false); err = ovl_set_link_redirect(old);
if (err) if (err)
goto out_drop_write; goto out_drop_write;
} }
......
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