Bug#327416: marked as done (CAN-2005-2490/CAN-2005-2492: Two sendmsg() related vulnerabilites)

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Bug#327416: marked as done (CAN-2005-2490/CAN-2005-2492: Two sendmsg() related vulnerabilites)

Debian Bug Tracking System
Your message dated Sat, 5 Nov 2005 21:42:21 -0800 (PST)
with message-id <Pine.LNX.4.63.0511052139500.2920@bobcat>
and subject line CAN-2005-2490/CAN-2005-2492: Two sendmsg() related vulnerabilites
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--------------------------------------
Received: (at submit) by bugs.debian.org; 9 Sep 2005 23:29:08 +0000
>From [hidden email] Fri Sep 09 16:29:08 2005
Return-path: <[hidden email]>
Received: from (vserver151.vserver151.serverflex.de) [193.22.164.111]
        by spohr.debian.org with esmtp (Exim 3.36 1 (Debian))
        id 1EDsIt-0002oA-00; Fri, 09 Sep 2005 16:29:07 -0700
Received: from dsl-084-059-136-208.arcor-ip.net ([84.59.136.208] helo=localhost.localdomain)
        by vserver151.vserver151.serverflex.de with esmtpsa (TLS-1.0:RSA_AES_256_CBC_SHA:32)
        (Exim 4.50)
        id 1EDsIo-0007FW-Ph
        for [hidden email]; Sat, 10 Sep 2005 01:29:03 +0200
Received: from jmm by localhost.localdomain with local (Exim 4.52)
        id 1EDsJe-0001ps-KU; Sat, 10 Sep 2005 01:29:54 +0200
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
From: Moritz Muehlenhoff <[hidden email]>
To: Debian Bug Tracking System <[hidden email]>
Subject: CAN-2005-2490/CAN-2005-2492: Two sendmsg() related vulnerabilites
X-Mailer: reportbug 3.17
Date: Sat, 10 Sep 2005 01:29:54 +0200
X-Debbugs-Cc: Debian Security Team <[hidden email]>
Message-Id: <[hidden email]>
X-SA-Exim-Connect-IP: 84.59.136.208
X-SA-Exim-Mail-From: [hidden email]
X-SA-Exim-Scanned: No (on vserver151.vserver151.serverflex.de); SAEximRunCond expanded to false
Delivered-To: [hidden email]
X-Spam-Checker-Version: SpamAssassin 2.60-bugs.debian.org_2005_01_02
        (1.212-2003-09-23-exp) on spohr.debian.org
X-Spam-Level:
X-Spam-Status: No, hits=-11.0 required=4.0 tests=BAYES_00,HAS_PACKAGE,
        X_DEBBUGS_CC autolearn=ham version=2.60-bugs.debian.org_2005_01_02

Package: linux-2.6
Severity: important
Tags: security

[Severity important only, as amd64 is not yet officially in the archive]

These patches were posted as part of the stable review cycle on linux-kernel,
they're probably available in git already.

CAN-2005-2490: (local privilege escalation on amd64)
When we copy 32bit ->msg_control contents to kernel, we walk the same
userland data twice without sanity checks on the second pass.

Second version of this patch: the original broke with 64-bit arches
running 32-bit-compat-mode executables doing sendmsg() syscalls with
unaligned CMSG data areas

Another thing is that we use kmalloc() to allocate and sock_kfree_s()
to free afterwards; less serious, but also needs fixing.

Patch by Al Viro, David Miller, David Woodhouse

Signed-off-by: Chris Wright <[hidden email]>
---
 include/net/compat.h |    2 +-
 net/compat.c         |   44 ++++++++++++++++++++++++++------------------
 net/socket.c         |    3 ++-
 3 files changed, 29 insertions(+), 20 deletions(-)

Index: linux-2.6.13.y/include/net/compat.h
===================================================================
--- linux-2.6.13.y.orig/include/net/compat.h
+++ linux-2.6.13.y/include/net/compat.h
@@ -33,7 +33,7 @@ extern asmlinkage long compat_sys_sendms
 extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
 extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
 extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
-extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, unsigned char *,
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *,
  int);
 
 #endif /* NET_COMPAT_H */
Index: linux-2.6.13.y/net/compat.c
===================================================================
--- linux-2.6.13.y.orig/net/compat.c
+++ linux-2.6.13.y/net/compat.c
@@ -135,13 +135,14 @@ static inline struct compat_cmsghdr __us
  * thus placement) of cmsg headers and length are different for
  * 32-bit apps.  -DaveM
  */
-int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
+int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
        unsigned char *stackbuf, int stackbuf_size)
 {
  struct compat_cmsghdr __user *ucmsg;
  struct cmsghdr *kcmsg, *kcmsg_base;
  compat_size_t ucmlen;
  __kernel_size_t kcmlen, tmp;
+ int err = -EFAULT;
 
  kcmlen = 0;
  kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
@@ -156,6 +157,7 @@ int cmsghdr_from_user_compat_to_kern(str
 
  tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
        CMSG_ALIGN(sizeof(struct cmsghdr)));
+ tmp = CMSG_ALIGN(tmp);
  kcmlen += tmp;
  ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
  }
@@ -167,30 +169,34 @@ int cmsghdr_from_user_compat_to_kern(str
  * until we have successfully copied over all of the data
  * from the user.
  */
- if(kcmlen > stackbuf_size)
- kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
- if(kcmsg == NULL)
+ if (kcmlen > stackbuf_size)
+ kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
+ if (kcmsg == NULL)
  return -ENOBUFS;
 
  /* Now copy them over neatly. */
  memset(kcmsg, 0, kcmlen);
  ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
  while(ucmsg != NULL) {
- __get_user(ucmlen, &ucmsg->cmsg_len);
+ if (__get_user(ucmlen, &ucmsg->cmsg_len))
+ goto Efault;
+ if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
+ goto Einval;
  tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
        CMSG_ALIGN(sizeof(struct cmsghdr)));
+ if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
+ goto Einval;
  kcmsg->cmsg_len = tmp;
- __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
- __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
- /* Copy over the data. */
- if(copy_from_user(CMSG_DATA(kcmsg),
-  CMSG_COMPAT_DATA(ucmsg),
-  (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
- goto out_free_efault;
+ tmp = CMSG_ALIGN(tmp);
+ if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
+    __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
+    copy_from_user(CMSG_DATA(kcmsg),
+   CMSG_COMPAT_DATA(ucmsg),
+   (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
+ goto Efault;
 
  /* Advance. */
- kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+ kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
  ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
  }
 
@@ -199,10 +205,12 @@ int cmsghdr_from_user_compat_to_kern(str
  kmsg->msg_controllen = kcmlen;
  return 0;
 
-out_free_efault:
- if(kcmsg_base != (struct cmsghdr *)stackbuf)
- kfree(kcmsg_base);
- return -EFAULT;
+Einval:
+ err = -EINVAL;
+Efault:
+ if (kcmsg_base != (struct cmsghdr *)stackbuf)
+ sock_kfree_s(sk, kcmsg_base, kcmlen);
+ return err;
 }
 
 int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
Index: linux-2.6.13.y/net/socket.c
===================================================================
--- linux-2.6.13.y.orig/net/socket.c
+++ linux-2.6.13.y/net/socket.c
@@ -1739,10 +1739,11 @@ asmlinkage long sys_sendmsg(int fd, stru
  goto out_freeiov;
  ctl_len = msg_sys.msg_controllen;
  if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
- err = cmsghdr_from_user_compat_to_kern(&msg_sys, ctl, sizeof(ctl));
+ err = cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, sizeof(ctl));
  if (err)
  goto out_freeiov;
  ctl_buf = msg_sys.msg_control;
+ ctl_len = msg_sys.msg_controllen;
  } else if (ctl_len) {
  if (ctl_len > sizeof(ctl))
  {


Minor update from David Miller for clean sparc64 build.

diff --git a/include/net/compat.h b/include/net/compat.h
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -33,7 +33,8 @@ extern asmlinkage long compat_sys_sendms
 extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
 extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
 extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
-extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *,
-               int);
+
+struct sock;
+extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);

 #endif /* NET_COMPAT_H */



CAN-2005-2492 (information leakage / DoS)
From: Al Viro <[hidden email]>

Fix unchecked __get_user that could be tricked into generating a
memory read on an arbitrary address.  The result of the read is not
returned directly but you may be able to divine some information about
it, or use the read to cause a crash on some architectures by reading
hardware state.  CAN-2005-2492.

Fix from Al Viro, ack from Dave Miller.

Signed-off-by: Chris Wright <[hidden email]>
---
 net/ipv4/raw.c |    2 +-
 net/ipv6/raw.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6.13.y/net/ipv4/raw.c
===================================================================
--- linux-2.6.13.y.orig/net/ipv4/raw.c
+++ linux-2.6.13.y/net/ipv4/raw.c
@@ -358,7 +358,7 @@ static void raw_probe_proto_opt(struct f
 
  if (type && code) {
  get_user(fl->fl_icmp_type, type);
- __get_user(fl->fl_icmp_code, code);
+        get_user(fl->fl_icmp_code, code);
  probed = 1;
  }
  break;
Index: linux-2.6.13.y/net/ipv6/raw.c
===================================================================
--- linux-2.6.13.y.orig/net/ipv6/raw.c
+++ linux-2.6.13.y/net/ipv6/raw.c
@@ -619,7 +619,7 @@ static void rawv6_probe_proto_opt(struct
 
  if (type && code) {
  get_user(fl->fl_icmp_type, type);
- __get_user(fl->fl_icmp_code, code);
+ get_user(fl->fl_icmp_code, code);
  probed = 1;
  }
  break;


Cheers,
        Moritz

-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.13
Locale: LANG=C, LC_CTYPE=de_DE.ISO-8859-15@euro (charmap=ISO-8859-15)

---------------------------------------
Received: (at 327416-done) by bugs.debian.org; 6 Nov 2005 05:42:09 +0000
>From [hidden email] Sat Nov 05 21:42:09 2005
Return-path: <[hidden email]>
Received: from mouth.voxel.net (mail.squishy.cc) [69.9.180.118] (postfix)
        by spohr.debian.org with esmtp (Exim 3.36 1 (Debian))
        id 1EYdI9-0000bY-00; Sat, 05 Nov 2005 21:42:09 -0800
Received: from localhost (localhost.localdomain [127.0.0.1])
        by mail.squishy.cc (Postfix) with ESMTP id 0FE1E5898007
        for <[hidden email]>; Sun,  6 Nov 2005 00:42:08 -0500 (EST)
Date: Sat, 5 Nov 2005 21:42:21 -0800 (PST)
From: Jurij Smakov <[hidden email]>
Reply-To: [hidden email]
To: [hidden email]
Subject: Re: CAN-2005-2490/CAN-2005-2492: Two sendmsg() related vulnerabilites
Message-ID: <Pine.LNX.4.63.0511052139500.2920@bobcat>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed
Delivered-To: [hidden email]
X-Spam-Checker-Version: SpamAssassin 2.60-bugs.debian.org_2005_01_02
        (1.212-2003-09-23-exp) on spohr.debian.org
X-Spam-Level:
X-Spam-Status: No, hits=-3.0 required=4.0 tests=BAYES_00 autolearn=no
        version=2.60-bugs.debian.org_2005_01_02

Version: 2.6.13-1

According to information from

people/horms/patch_notes/cve/CAN-2005-2490
people/horms/patch_notes/cve/CAN-2005-2492

in svn, these bugs have been taken care of in 2.6.13-1. Closing
accordingly (with approval from Horms).

Jurij Smakov                                        [hidden email]
Key: http://www.wooyd.org/pgpkey/                   KeyID: C99E03CC


--
To UNSUBSCRIBE, email to [hidden email]
with a subject of "unsubscribe". Trouble? Contact [hidden email]