aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTyler Hicks <tyhicks@canonical.com>2015-02-24 20:28:10 -0500
committerTyler Hicks <tyhicks@canonical.com>2015-03-03 03:03:56 -0500
commit6d65261a09adaa374c05de807f73a144d783669e (patch)
treec9fceb28a3097d7885df1ae6b67af0bd154a4708 /fs
parent2a559a8bdeae853b6a8abb477c88875e1d4de591 (diff)
eCryptfs: don't pass fs-specific ioctl commands through
eCryptfs can't be aware of what to expect when after passing an arbitrary ioctl command through to the lower filesystem. The ioctl command may trigger an action in the lower filesystem that is incompatible with eCryptfs. One specific example is when one attempts to use the Btrfs clone ioctl command when the source file is in the Btrfs filesystem that eCryptfs is mounted on top of and the destination fd is from a new file created in the eCryptfs mount. The ioctl syscall incorrectly returns success because the command is passed down to Btrfs which thinks that it was able to do the clone operation. However, the result is an empty eCryptfs file. This patch allows the trim, {g,s}etflags, and {g,s}etversion ioctl commands through and then copies up the inode metadata from the lower inode to the eCryptfs inode to catch any changes made to the lower inode's metadata. Those five ioctl commands are mostly common across all filesystems but the whitelist may need to be further pruned in the future. https://bugzilla.kernel.org/show_bug.cgi?id=93691 https://launchpad.net/bugs/1305335 Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Cc: Rocko <rockorequin@hotmail.com> Cc: Colin Ian King <colin.king@canonical.com> Cc: stable@vger.kernel.org # v2.6.36+: c43f7b8 eCryptfs: Handle ioctl calls with unlocked and compat functions
Diffstat (limited to 'fs')
-rw-r--r--fs/ecryptfs/file.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index b07731e68c0b..fd39bad6f1bd 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -303,9 +303,22 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
303 struct file *lower_file = ecryptfs_file_to_lower(file); 303 struct file *lower_file = ecryptfs_file_to_lower(file);
304 long rc = -ENOTTY; 304 long rc = -ENOTTY;
305 305
306 if (lower_file->f_op->unlocked_ioctl) 306 if (!lower_file->f_op->unlocked_ioctl)
307 return rc;
308
309 switch (cmd) {
310 case FITRIM:
311 case FS_IOC_GETFLAGS:
312 case FS_IOC_SETFLAGS:
313 case FS_IOC_GETVERSION:
314 case FS_IOC_SETVERSION:
307 rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); 315 rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
308 return rc; 316 fsstack_copy_attr_all(file_inode(file), file_inode(lower_file));
317
318 return rc;
319 default:
320 return rc;
321 }
309} 322}
310 323
311#ifdef CONFIG_COMPAT 324#ifdef CONFIG_COMPAT
@@ -315,9 +328,22 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
315 struct file *lower_file = ecryptfs_file_to_lower(file); 328 struct file *lower_file = ecryptfs_file_to_lower(file);
316 long rc = -ENOIOCTLCMD; 329 long rc = -ENOIOCTLCMD;
317 330
318 if (lower_file->f_op->compat_ioctl) 331 if (!lower_file->f_op->compat_ioctl)
332 return rc;
333
334 switch (cmd) {
335 case FITRIM:
336 case FS_IOC32_GETFLAGS:
337 case FS_IOC32_SETFLAGS:
338 case FS_IOC32_GETVERSION:
339 case FS_IOC32_SETVERSION:
319 rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); 340 rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
320 return rc; 341 fsstack_copy_attr_all(file_inode(file), file_inode(lower_file));
342
343 return rc;
344 default:
345 return rc;
346 }
321} 347}
322#endif 348#endif
323 349