diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2017-09-05 12:53:12 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2017-09-05 12:53:12 +0200 |
commit | 7c6893e3c9abf6a9676e060a1e35e5caca673d57 (patch) | |
tree | c14dda085d44e13a67c0d8f8d03113620f45bb7a /fs/xattr.c | |
parent | cd91304e7190b4c4802f8e413ab2214b233e0260 (diff) |
ovl: don't allow writing ioctl on lower layer
Problem with ioctl() is that it's a file operation, yet often used as an
inode operation (i.e. modify the inode despite the file being opened for
read-only).
mnt_want_write_file() is used by filesystems in such cases to get write
access on an arbitrary open file.
Since overlayfs lets filesystems do all file operations, including ioctl,
this can lead to mnt_want_write_file() returning OK for a lower file and
modification of that lower file.
This patch prevents modification by checking if the file is from an
overlayfs lower layer and returning EPERM in that case.
Need to introduce a mnt_want_write_file_path() variant that still does the
old thing for inode operations that can do the copy up + modification
correctly in such cases (fchown, fsetxattr, fremovexattr).
This does not address the correctness of such ioctls on overlayfs (the
correct way would be to copy up and attempt to perform ioctl on upper
file).
In theory this could be a regression. We very much hope that nobody is
relying on such a hack in any sane setup.
While this patch meddles in VFS code, it has no effect on non-overlayfs
filesystems.
Reported-by: "zhangyi (F)" <yi.zhang@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 464c94bf65f9..d7c2cf7817bb 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -23,6 +23,7 @@ #include <linux/posix_acl_xattr.h> #include <linux/uaccess.h> +#include "internal.h" static const char * strcmp_prefix(const char *a, const char *a_prefix) @@ -496,10 +497,10 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, if (!f.file) return error; audit_file(f.file); - error = mnt_want_write_file(f.file); + error = mnt_want_write_file_path(f.file); if (!error) { error = setxattr(f.file->f_path.dentry, name, value, size, flags); - mnt_drop_write_file(f.file); + mnt_drop_write_file_path(f.file); } fdput(f); return error; @@ -728,10 +729,10 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) if (!f.file) return error; audit_file(f.file); - error = mnt_want_write_file(f.file); + error = mnt_want_write_file_path(f.file); if (!error) { error = removexattr(f.file->f_path.dentry, name); - mnt_drop_write_file(f.file); + mnt_drop_write_file_path(f.file); } fdput(f); return error; |