]>
Commit | Line | Data |
---|---|---|
d177b838 GKH |
1 | From 6d65261a09adaa374c05de807f73a144d783669e Mon Sep 17 00:00:00 2001 |
2 | From: Tyler Hicks <tyhicks@canonical.com> | |
3 | Date: Tue, 24 Feb 2015 19:28:10 -0600 | |
4 | Subject: eCryptfs: don't pass fs-specific ioctl commands through | |
5 | ||
6 | From: Tyler Hicks <tyhicks@canonical.com> | |
7 | ||
8 | commit 6d65261a09adaa374c05de807f73a144d783669e upstream. | |
9 | ||
10 | eCryptfs can't be aware of what to expect when after passing an | |
11 | arbitrary ioctl command through to the lower filesystem. The ioctl | |
12 | command may trigger an action in the lower filesystem that is | |
13 | incompatible with eCryptfs. | |
14 | ||
15 | One specific example is when one attempts to use the Btrfs clone | |
16 | ioctl command when the source file is in the Btrfs filesystem that | |
17 | eCryptfs is mounted on top of and the destination fd is from a new file | |
18 | created in the eCryptfs mount. The ioctl syscall incorrectly returns | |
19 | success because the command is passed down to Btrfs which thinks that it | |
20 | was able to do the clone operation. However, the result is an empty | |
21 | eCryptfs file. | |
22 | ||
23 | This patch allows the trim, {g,s}etflags, and {g,s}etversion ioctl | |
24 | commands through and then copies up the inode metadata from the lower | |
25 | inode to the eCryptfs inode to catch any changes made to the lower | |
26 | inode's metadata. Those five ioctl commands are mostly common across all | |
27 | filesystems but the whitelist may need to be further pruned in the | |
28 | future. | |
29 | ||
30 | https://bugzilla.kernel.org/show_bug.cgi?id=93691 | |
31 | https://launchpad.net/bugs/1305335 | |
32 | ||
33 | Signed-off-by: Tyler Hicks <tyhicks@canonical.com> | |
34 | Cc: Rocko <rockorequin@hotmail.com> | |
35 | Cc: Colin Ian King <colin.king@canonical.com> | |
36 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
37 | ||
38 | --- | |
39 | fs/ecryptfs/file.c | 34 ++++++++++++++++++++++++++++++---- | |
40 | 1 file changed, 30 insertions(+), 4 deletions(-) | |
41 | ||
42 | --- a/fs/ecryptfs/file.c | |
43 | +++ b/fs/ecryptfs/file.c | |
44 | @@ -303,9 +303,22 @@ ecryptfs_unlocked_ioctl(struct file *fil | |
45 | struct file *lower_file = ecryptfs_file_to_lower(file); | |
46 | long rc = -ENOTTY; | |
47 | ||
48 | - if (lower_file->f_op->unlocked_ioctl) | |
49 | + if (!lower_file->f_op->unlocked_ioctl) | |
50 | + return rc; | |
51 | + | |
52 | + switch (cmd) { | |
53 | + case FITRIM: | |
54 | + case FS_IOC_GETFLAGS: | |
55 | + case FS_IOC_SETFLAGS: | |
56 | + case FS_IOC_GETVERSION: | |
57 | + case FS_IOC_SETVERSION: | |
58 | rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); | |
59 | - return rc; | |
60 | + fsstack_copy_attr_all(file_inode(file), file_inode(lower_file)); | |
61 | + | |
62 | + return rc; | |
63 | + default: | |
64 | + return rc; | |
65 | + } | |
66 | } | |
67 | ||
68 | #ifdef CONFIG_COMPAT | |
69 | @@ -315,9 +328,22 @@ ecryptfs_compat_ioctl(struct file *file, | |
70 | struct file *lower_file = ecryptfs_file_to_lower(file); | |
71 | long rc = -ENOIOCTLCMD; | |
72 | ||
73 | - if (lower_file->f_op->compat_ioctl) | |
74 | + if (!lower_file->f_op->compat_ioctl) | |
75 | + return rc; | |
76 | + | |
77 | + switch (cmd) { | |
78 | + case FITRIM: | |
79 | + case FS_IOC32_GETFLAGS: | |
80 | + case FS_IOC32_SETFLAGS: | |
81 | + case FS_IOC32_GETVERSION: | |
82 | + case FS_IOC32_SETVERSION: | |
83 | rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); | |
84 | - return rc; | |
85 | + fsstack_copy_attr_all(file_inode(file), file_inode(lower_file)); | |
86 | + | |
87 | + return rc; | |
88 | + default: | |
89 | + return rc; | |
90 | + } | |
91 | } | |
92 | #endif | |
93 |