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 | |
| 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>
| -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 | } | ||
