Commit 0a57f3e6 authored by Chris Wright's avatar Chris Wright Committed by Linus Torvalds

[PATCH] compat ioctl security hook fixup

Fix a bug spotted by "Michael S. Tsirkin" <mst@mellanox.co.il>

Introduce a simple helper, vfs_ioctl(), so that both sys_ioctl() and
compat_sys_ioctl() call the security hook in all cases and without
duplication.
Signed-off-by: default avatarChris Wright <chrisw@osdl.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d360d565
...@@ -439,6 +439,11 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, ...@@ -439,6 +439,11 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
if (!filp) if (!filp)
goto out; goto out;
/* RED-PEN how should LSM module know it's handling 32bit? */
error = security_file_ioctl(filp, cmd, arg);
if (error)
goto out_fput;
/* /*
* To allow the compat_ioctl handlers to be self contained * To allow the compat_ioctl handlers to be self contained
* we need to check the common ioctls here first. * we need to check the common ioctls here first.
...@@ -496,11 +501,6 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, ...@@ -496,11 +501,6 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
found_handler: found_handler:
if (t->handler) { if (t->handler) {
/* RED-PEN how should LSM module know it's handling 32bit? */
error = security_file_ioctl(filp, cmd, arg);
if (error)
goto out_fput;
lock_kernel(); lock_kernel();
error = t->handler(fd, cmd, arg, filp); error = t->handler(fd, cmd, arg, filp);
unlock_kernel(); unlock_kernel();
...@@ -510,7 +510,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, ...@@ -510,7 +510,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
up_read(&ioctl32_sem); up_read(&ioctl32_sem);
do_ioctl: do_ioctl:
error = sys_ioctl(fd, cmd, arg); error = vfs_ioctl(filp, fd, cmd, arg);
out_fput: out_fput:
fput_light(filp, fput_needed); fput_light(filp, fput_needed);
out: out:
......
...@@ -77,25 +77,17 @@ static int file_ioctl(struct file *filp, unsigned int cmd, ...@@ -77,25 +77,17 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
return do_ioctl(filp, cmd, arg); return do_ioctl(filp, cmd, arg);
} }
/* /*
* When you add any new common ioctls to the switches above and below * When you add any new common ioctls to the switches above and below
* please update compat_sys_ioctl() too. * please update compat_sys_ioctl() too.
*
* vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
* It's just a simple helper for sys_ioctl and compat_sys_ioctl.
*/ */
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp;
unsigned int flag; unsigned int flag;
int on, error = -EBADF; int on, error = 0;
int fput_needed;
filp = fget_light(fd, &fput_needed);
if (!filp)
goto out;
error = security_file_ioctl(filp, cmd, arg);
if (error)
goto out_fput;
switch (cmd) { switch (cmd) {
case FIOCLEX: case FIOCLEX:
...@@ -161,6 +153,24 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -161,6 +153,24 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
error = do_ioctl(filp, cmd, arg); error = do_ioctl(filp, cmd, arg);
break; break;
} }
return error;
}
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
int error = -EBADF;
int fput_needed;
filp = fget_light(fd, &fput_needed);
if (!filp)
goto out;
error = security_file_ioctl(filp, cmd, arg);
if (error)
goto out_fput;
error = vfs_ioctl(filp, fd, cmd, arg);
out_fput: out_fput:
fput_light(filp, fput_needed); fput_light(filp, fput_needed);
out: out:
......
...@@ -1560,6 +1560,8 @@ extern int vfs_stat(char __user *, struct kstat *); ...@@ -1560,6 +1560,8 @@ extern int vfs_stat(char __user *, struct kstat *);
extern int vfs_lstat(char __user *, struct kstat *); extern int vfs_lstat(char __user *, struct kstat *);
extern int vfs_fstat(unsigned int, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *);
extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
extern struct file_system_type *get_fs_type(const char *name); extern struct file_system_type *get_fs_type(const char *name);
extern struct super_block *get_super(struct block_device *); extern struct super_block *get_super(struct block_device *);
extern struct super_block *user_get_super(dev_t); extern struct super_block *user_get_super(dev_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment