rpms/kernel/FC-4 linux-2.6-CAN-2005-2490.patch, NONE, 1.1 linux-2.6-CAN-2005-2492.patch, NONE, 1.1 kernel-2.6.spec, 1.1454, 1.1455

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Wed Sep 14 06:51:33 UTC 2005


Author: davej

Update of /cvs/dist/rpms/kernel/FC-4
In directory cvs.devel.redhat.com:/tmp/cvs-serv1606

Modified Files:
	kernel-2.6.spec 
Added Files:
	linux-2.6-CAN-2005-2490.patch linux-2.6-CAN-2005-2492.patch 
Log Message:
security fixes de jour


linux-2.6-CAN-2005-2490.patch:
 include/net/compat.h |    5 +++--
 net/compat.c         |   44 ++++++++++++++++++++++++++------------------
 net/socket.c         |    4 ++--
 3 files changed, 31 insertions(+), 22 deletions(-)

--- NEW FILE linux-2.6-CAN-2005-2490.patch ---

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
(sparc64 clean compile fix from David Miller)

Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
Signed-off-by: David Woodhouse <dwmw2 at infradead.org>
Signed-off-by: Chris Wright <chrisw at osdl.org>
---
 include/net/compat.h |    5 +++--
 net/compat.c         |   44 ++++++++++++++++++++++++++------------------
 net/socket.c         |    3 ++-
 3 files changed, 31 insertions(+), 21 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,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 *, unsigned char *,
-		int);
+
+struct sock;
+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))
 		{
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


linux-2.6-CAN-2005-2492.patch:
 ipv4/raw.c |    2 +-
 ipv6/raw.c |    3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

--- NEW FILE linux-2.6-CAN-2005-2492.patch ---

From: Al Viro <aviro at redhat.com>

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 <chrisw at osdl.org>
---
 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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/FC-4/kernel-2.6.spec,v
retrieving revision 1.1454
retrieving revision 1.1455
diff -u -r1.1454 -r1.1455
--- kernel-2.6.spec	9 Sep 2005 02:55:31 -0000	1.1454
+++ kernel-2.6.spec	14 Sep 2005 06:51:31 -0000	1.1455
@@ -365,6 +365,9 @@
 
 Patch2999: linux-2.6.3-printopen.patch
 
+Patch3000: linux-2.6-CAN-2005-2490.patch
+Patch3001: linux-2.6-CAN-2005-2492.patch
+
 #
 # External drivers that are about to get accepted upstream
 #
@@ -852,6 +855,10 @@
 #
 #%patch2999 -p1
 
+# Security fixes.
+%patch3000 -p1
+%patch3001 -p1
+
 #
 # External drivers that are about to get accepted upstream
 #
@@ -1292,6 +1299,9 @@
 %endif
 
 %changelog
+* Wed Sep 14 2005 Dave Jones <davej at redhat.com> [2.6.12-1.1455_FC4]
+- Fixes for CAN-2005-2490 and CAN-2005-2492
+
 * Thu Sep  8 2005 Rik van Riel <riel at redhat.com>
 - upgrade to a newer Xen snapshot
 - exclude Xen TPM bits, since those conflict with 2.6.12.5




More information about the fedora-cvs-commits mailing list