diff options
-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 | ||