diff options
author | David Howells <dhowells@redhat.com> | 2015-07-07 10:04:44 -0400 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2016-03-21 12:31:45 -0400 |
commit | fb5bb2c3b73df060d588b6521de5ab03589283f7 (patch) | |
tree | 1b55a911a8e69efee962e65e7935b815a0c15fd6 /fs/overlayfs | |
parent | 07f2af7bfd247857b1bf16ae7f479b5b6f4ef305 (diff) |
ovl: Warn on copy up if a process has a R/O fd open to the lower file
Print a warning when overlayfs copies up a file if the process that
triggered the copy up has a R/O fd open to the lower file being copied up.
This can help catch applications that do things like the following:
fd1 = open("foo", O_RDONLY);
fd2 = open("foo", O_RDWR);
where they expect fd1 and fd2 to refer to the same file - which will no
longer be the case post-copy up.
With this patch, the following commands:
bash 5</mnt/a/foo128
6<>/mnt/a/foo128
assuming /mnt/a/foo128 to be an un-copied up file on an overlay will
produce the following warning in the kernel log:
overlayfs: Copying up foo129, but open R/O on fd 5 which will cease
to be coherent [pid=3818 bash]
This is enabled by setting:
/sys/module/overlay/parameters/check_copy_up
to 1.
The warnings are ratelimited and are also limited to one warning per file -
assuming the copy up completes in each case.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/copy_up.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index d894e7cd9a86..959bdcf2f9e8 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | ||
10 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
12 | #include <linux/file.h> | 13 | #include <linux/file.h> |
@@ -16,10 +17,41 @@ | |||
16 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
17 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
18 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
20 | #include <linux/fdtable.h> | ||
21 | #include <linux/ratelimit.h> | ||
19 | #include "overlayfs.h" | 22 | #include "overlayfs.h" |
20 | 23 | ||
21 | #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) | 24 | #define OVL_COPY_UP_CHUNK_SIZE (1 << 20) |
22 | 25 | ||
26 | static bool __read_mostly ovl_check_copy_up; | ||
27 | module_param_named(check_copy_up, ovl_check_copy_up, bool, | ||
28 | S_IWUSR | S_IRUGO); | ||
29 | MODULE_PARM_DESC(ovl_check_copy_up, | ||
30 | "Warn on copy-up when causing process also has a R/O fd open"); | ||
31 | |||
32 | static int ovl_check_fd(const void *data, struct file *f, unsigned int fd) | ||
33 | { | ||
34 | const struct dentry *dentry = data; | ||
35 | |||
36 | if (f->f_inode == d_inode(dentry)) | ||
37 | pr_warn_ratelimited("overlayfs: Warning: Copying up %pD, but open R/O on fd %u which will cease to be coherent [pid=%d %s]\n", | ||
38 | f, fd, current->pid, current->comm); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | * Check the fds open by this process and warn if something like the following | ||
44 | * scenario is about to occur: | ||
45 | * | ||
46 | * fd1 = open("foo", O_RDONLY); | ||
47 | * fd2 = open("foo", O_RDWR); | ||
48 | */ | ||
49 | static void ovl_do_check_copy_up(struct dentry *dentry) | ||
50 | { | ||
51 | if (ovl_check_copy_up) | ||
52 | iterate_fd(current->files, 0, ovl_check_fd, dentry); | ||
53 | } | ||
54 | |||
23 | int ovl_copy_xattr(struct dentry *old, struct dentry *new) | 55 | int ovl_copy_xattr(struct dentry *old, struct dentry *new) |
24 | { | 56 | { |
25 | ssize_t list_size, size, value_size = 0; | 57 | ssize_t list_size, size, value_size = 0; |
@@ -309,6 +341,8 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, | |||
309 | if (WARN_ON(!workdir)) | 341 | if (WARN_ON(!workdir)) |
310 | return -EROFS; | 342 | return -EROFS; |
311 | 343 | ||
344 | ovl_do_check_copy_up(lowerpath->dentry); | ||
345 | |||
312 | ovl_path_upper(parent, &parentpath); | 346 | ovl_path_upper(parent, &parentpath); |
313 | upperdir = parentpath.dentry; | 347 | upperdir = parentpath.dentry; |
314 | 348 | ||