diff options
author | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2009-11-03 12:45:11 -0500 |
---|---|---|
committer | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2010-08-09 11:33:04 -0400 |
commit | c43f7b8fb03be8bcc579bfc4e6ab70eac887ab55 (patch) | |
tree | ec4f169d9260b78ef93e39c554fc32532b399b18 /fs/ecryptfs | |
parent | a1275c3b21e433888994f7b979cd1129d384ec9c (diff) |
eCryptfs: Handle ioctl calls with unlocked and compat functions
Lower filesystems that only implemented unlocked_ioctl weren't being
passed ioctl calls because eCryptfs only checked for
lower_file->f_op->ioctl and returned -ENOTTY if it was NULL.
eCryptfs shouldn't implement ioctl(), since it doesn't require the BKL.
This patch introduces ecryptfs_unlocked_ioctl() and
ecryptfs_compat_ioctl(), which passes the calls on to the lower file
system.
https://bugs.launchpad.net/ecryptfs/+bug/469664
Reported-by: James Dupin <james.dupin@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/file.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index e8fcf4e2ed7d..6e4f84cf73e8 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -292,12 +292,40 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag) | |||
292 | return rc; | 292 | return rc; |
293 | } | 293 | } |
294 | 294 | ||
295 | static int ecryptfs_ioctl(struct inode *inode, struct file *file, | 295 | static long |
296 | unsigned int cmd, unsigned long arg); | 296 | ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
297 | { | ||
298 | struct file *lower_file = NULL; | ||
299 | long rc = -ENOTTY; | ||
300 | |||
301 | if (ecryptfs_file_to_private(file)) | ||
302 | lower_file = ecryptfs_file_to_lower(file); | ||
303 | if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl) | ||
304 | rc = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg); | ||
305 | return rc; | ||
306 | } | ||
307 | |||
308 | #ifdef CONFIG_COMPAT | ||
309 | static long | ||
310 | ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
311 | { | ||
312 | struct file *lower_file = NULL; | ||
313 | long rc = -ENOIOCTLCMD; | ||
314 | |||
315 | if (ecryptfs_file_to_private(file)) | ||
316 | lower_file = ecryptfs_file_to_lower(file); | ||
317 | if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl) | ||
318 | rc = lower_file->f_op->compat_ioctl(lower_file, cmd, arg); | ||
319 | return rc; | ||
320 | } | ||
321 | #endif | ||
297 | 322 | ||
298 | const struct file_operations ecryptfs_dir_fops = { | 323 | const struct file_operations ecryptfs_dir_fops = { |
299 | .readdir = ecryptfs_readdir, | 324 | .readdir = ecryptfs_readdir, |
300 | .ioctl = ecryptfs_ioctl, | 325 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, |
326 | #ifdef CONFIG_COMPAT | ||
327 | .compat_ioctl = ecryptfs_compat_ioctl, | ||
328 | #endif | ||
301 | .open = ecryptfs_open, | 329 | .open = ecryptfs_open, |
302 | .flush = ecryptfs_flush, | 330 | .flush = ecryptfs_flush, |
303 | .release = ecryptfs_release, | 331 | .release = ecryptfs_release, |
@@ -313,7 +341,10 @@ const struct file_operations ecryptfs_main_fops = { | |||
313 | .write = do_sync_write, | 341 | .write = do_sync_write, |
314 | .aio_write = generic_file_aio_write, | 342 | .aio_write = generic_file_aio_write, |
315 | .readdir = ecryptfs_readdir, | 343 | .readdir = ecryptfs_readdir, |
316 | .ioctl = ecryptfs_ioctl, | 344 | .unlocked_ioctl = ecryptfs_unlocked_ioctl, |
345 | #ifdef CONFIG_COMPAT | ||
346 | .compat_ioctl = ecryptfs_compat_ioctl, | ||
347 | #endif | ||
317 | .mmap = generic_file_mmap, | 348 | .mmap = generic_file_mmap, |
318 | .open = ecryptfs_open, | 349 | .open = ecryptfs_open, |
319 | .flush = ecryptfs_flush, | 350 | .flush = ecryptfs_flush, |
@@ -322,20 +353,3 @@ const struct file_operations ecryptfs_main_fops = { | |||
322 | .fasync = ecryptfs_fasync, | 353 | .fasync = ecryptfs_fasync, |
323 | .splice_read = generic_file_splice_read, | 354 | .splice_read = generic_file_splice_read, |
324 | }; | 355 | }; |
325 | |||
326 | static int | ||
327 | ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
328 | unsigned long arg) | ||
329 | { | ||
330 | int rc = 0; | ||
331 | struct file *lower_file = NULL; | ||
332 | |||
333 | if (ecryptfs_file_to_private(file)) | ||
334 | lower_file = ecryptfs_file_to_lower(file); | ||
335 | if (lower_file && lower_file->f_op && lower_file->f_op->ioctl) | ||
336 | rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode), | ||
337 | lower_file, cmd, arg); | ||
338 | else | ||
339 | rc = -ENOTTY; | ||
340 | return rc; | ||
341 | } | ||