4.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein amir73il@gmail.com
commit 91ff20f34e94424e586f57f4f593beae16504f86 upstream.
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: Theodore Y. Ts'o tytso@mit.edu Reported-by: Maciej Zięba maciekz82@gmail.com Fixes: 4120fe64dce4 ("ovl: Set redirect on upper inode when it is linked") Cc: stable@vger.kernel.org # v4.19 Signed-off-by: Amir Goldstein amir73il@gmail.com Acked-by: Vivek Goyal vgoyal@redhat.com Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- fs/overlayfs/dir.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
--- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -652,6 +652,18 @@ static int ovl_symlink(struct inode *dir 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, struct dentry *new) { @@ -672,7 +684,7 @@ static int ovl_link(struct dentry *old, goto out_drop_write;
if (ovl_is_metacopy_dentry(old)) { - err = ovl_set_redirect(old, false); + err = ovl_set_link_redirect(old); if (err) goto out_drop_write; }