From: Chris Wright <chrisw@osdl.org>

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: Chris Wright <chrisw@osdl.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/compat.c        |   12 ++++++------
 25-akpm/fs/ioctl.c         |   36 +++++++++++++++++++++++-------------
 25-akpm/include/linux/fs.h |    2 ++
 3 files changed, 31 insertions(+), 19 deletions(-)

diff -puN fs/compat.c~compat-ioctl-security-hook-fixup fs/compat.c
--- 25/fs/compat.c~compat-ioctl-security-hook-fixup	2005-01-23 01:40:50.441060096 -0800
+++ 25-akpm/fs/compat.c	2005-01-23 01:40:50.449058880 -0800
@@ -439,6 +439,11 @@ asmlinkage long compat_sys_ioctl(unsigne
 	if (!filp)
 		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
 	 * we need to check the common ioctls here first.
@@ -496,11 +501,6 @@ asmlinkage long compat_sys_ioctl(unsigne
 
  found_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();
 		error = t->handler(fd, cmd, arg, filp);
 		unlock_kernel();
@@ -510,7 +510,7 @@ asmlinkage long compat_sys_ioctl(unsigne
 
 	up_read(&ioctl32_sem);
  do_ioctl:
-	error = sys_ioctl(fd, cmd, arg);
+	error = vfs_ioctl(filp, fd, cmd, arg);
  out_fput:
 	fput_light(filp, fput_needed);
  out:
diff -puN fs/ioctl.c~compat-ioctl-security-hook-fixup fs/ioctl.c
--- 25/fs/ioctl.c~compat-ioctl-security-hook-fixup	2005-01-23 01:40:50.442059944 -0800
+++ 25-akpm/fs/ioctl.c	2005-01-23 01:40:50.448059032 -0800
@@ -77,25 +77,17 @@ static int file_ioctl(struct file *filp,
 	return do_ioctl(filp, cmd, arg);
 }
 
-
 /*
  * When you add any new common ioctls to the switches above and below
  * 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;
-	int on, 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;
+	int on, error = 0;
 
 	switch (cmd) {
 		case FIOCLEX:
@@ -161,6 +153,24 @@ asmlinkage long sys_ioctl(unsigned int f
 				error = do_ioctl(filp, cmd, arg);
 			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:
 	fput_light(filp, fput_needed);
  out:
diff -puN include/linux/fs.h~compat-ioctl-security-hook-fixup include/linux/fs.h
--- 25/include/linux/fs.h~compat-ioctl-security-hook-fixup	2005-01-23 01:40:50.445059488 -0800
+++ 25-akpm/include/linux/fs.h	2005-01-23 01:40:50.451058576 -0800
@@ -1566,6 +1566,8 @@ extern int vfs_stat(char __user *, struc
 extern int vfs_lstat(char __user *, 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 super_block *get_super(struct block_device *);
 extern struct super_block *user_get_super(dev_t);
_