OSDN Git Service

[PATCH] Lost sockfd_put() in routing_ioctl()
authorKirill Korotaev <dev@sw.ru>
Fri, 9 Sep 2005 09:59:48 +0000 (13:59 +0400)
committerMarcelo Tosatti <marcelo@dmt.cnet>
Mon, 19 Sep 2005 14:57:19 +0000 (11:57 -0300)
This patch adds lost sockfd_put() in 32bit compat rounting_ioctl() on
64bit platforms

I believe this is a security issues, since user can fget() file as many
times as he wants to. So file refcounter can be overlapped and first
fput() will free resources though there will be still structures
pointing to the file, mnt, dentry etc.
Also fput() sets f_dentry and f_vfsmnt to NULL,
so other file users will OOPS.

The oops can be done under files_lock and others, so this can be an
exploitable DoS on SMP. Didn't checked it on practice actually.

Signed-Off-By: Kirill Korotaev <dev@sw.ru>
Signed-Off-By: Maxim Giryaev <gem@sw.ru>
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c

arch/ppc64/kernel/ioctl32.c
arch/sparc64/kernel/ioctl32.c
arch/x86_64/ia32/ia32_ioctl.c

index 9890cc7..1cc4c39 100644 (file)
@@ -876,13 +876,15 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                r = (void *) &r4;
        }
 
-       if (ret)
-               return -EFAULT;
+       if (ret) {
+               ret = -EFAULT;
+               goto out;
+       }
 
        set_fs (KERNEL_DS);
        ret = sys_ioctl (fd, cmd, (long) r);
        set_fs (old_fs);
-
+out:
        if (mysock)
                sockfd_put(mysock);
 
index 6f0c52b..9b09c42 100644 (file)
@@ -809,13 +809,15 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                r = (void *) &r4;
        }
 
-       if (ret)
-               return -EFAULT;
+       if (ret) {
+               ret = -EFAULT;
+               goto out;
+       }
 
        set_fs (KERNEL_DS);
        ret = sys_ioctl (fd, cmd, (long) r);
        set_fs (old_fs);
-
+out:
        if (mysock)
                sockfd_put(mysock);
 
index 0056562..a51984c 100644 (file)
@@ -816,6 +816,11 @@ struct in6_rtmsg32 {
 
 extern struct socket *sockfd_lookup(int fd, int *err);
 
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+       fput(sock->file);
+}
+
 static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
        int ret;
@@ -857,12 +862,17 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                r = (void *) &r4;
        }
 
-       if (ret)
-               return -EFAULT;
+       if (ret) {
+               ret = -EFAULT;
+               goto out;
+       }
 
        set_fs (KERNEL_DS);
        ret = sys_ioctl (fd, cmd, (long) r);
        set_fs (old_fs);
+out:
+       if (mysock)
+               sockfd_put(mysock);
 
        return ret;
 }