BugLink: https://bugs.launchpad.net/bugs/1860041
All non-special files (For shiftfs this only includes fifos and - for
this case - unix sockets - since we don't allow character and block
devices to be created.) go through shiftfs_open() and have their dentry
pinned through this codepath preventing it from going negative. But
fifos don't use the shiftfs fops but rather use the pipefifo_fops which
means they do not go through shiftfs_open() and thus don't have their
dentry pinned that way. Thus, the lower dentries for such files can go
negative on unlink causing segfaults. The following C program can be
used to reproduce the crash:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
struct stat stat;
unlink("./bbb");
int ret = mknod("./bbb", S_IFIFO|0666, 0);
if (ret < 0)
exit(1);
int fd = open("./bbb", O_RDWR);
if (fd < 0)
exit(2);
if (unlink("./bbb"))
exit(4);
fstat(fd, &stat);
return 0;
}
Similar to ecryptfs we need to dget() the lower dentry before calling
vfs_unlink() on it and dput() it afterwards.
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Link: https://travis-ci.community/t/arm64-ppc64le-segfaults/6158/3
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
int err;
const struct cred *oldcred;
+ dget(lowerd);
oldcred = shiftfs_override_creds(dentry->d_sb);
inode_lock_nested(loweri, I_MUTEX_PARENT);
if (rmdir)
inode_unlock(loweri);
shiftfs_copyattr(loweri, dir);
+ dput(lowerd);
return err;
}