Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2977

kernel-2.6.18-238.el5.src.rpm

From: Jiri Pirko <jpirko@redhat.com>
Date: Wed, 11 Mar 2009 08:36:47 +0100
Subject: [net] put_cmsg: may cause application memory overflow
Message-id: 20090311073646.GA1591@psychotron.englab.brq.redhat.com
O-Subject: [RHEL5.4 patch] BZ488367 net: Fix function put_cmsg() which may cause usr application memory overflow
Bugzilla: 488367
RH-Acked-by: Anton Arapov <aarapov@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>
RH-Acked-by: Tomas Henzl <thenzl@redhat.com>

BZ488367
https://bugzilla.redhat.com/show_bug.cgi?id=488367

Description:
When used function put_cmsg() to copy kernel information to user
application memory, if the memory length given by user application is
not enough, by the bad length calculate of msg.msg_controllen,
put_cmsg() function may cause the msg.msg_controllen to be a large
value, such as 0xFFFFFFF0, so the following put_cmsg() can also write
data to usr application memory even usr has no valid memory to store
this. This may cause usr application memory overflow.

Upstream:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1ac70e7ad24a88710cf9b6d7ababaefa2b575df0

Brew:
https://brewweb.devel.redhat.com/taskinfo?taskID=1721390

Test:
Booted on x86_64 and tested with reproducer.

Jirka

diff --git a/net/compat.c b/net/compat.c
index 86d3ebc..abea845 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -249,6 +249,8 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat
 	if(copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
 		return -EFAULT;
 	cmlen = CMSG_COMPAT_SPACE(len);
+	if (kmsg->msg_controllen < cmlen)
+		cmlen = kmsg->msg_controllen;
 	kmsg->msg_control += cmlen;
 	kmsg->msg_controllen -= cmlen;
 	return 0;
diff --git a/net/core/scm.c b/net/core/scm.c
index f24b2eb..5e2277b 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -210,6 +210,8 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
 	if (copy_to_user(CMSG_DATA(cm), data, cmlen - sizeof(struct cmsghdr)))
 		goto out;
 	cmlen = CMSG_SPACE(len);
+	if (msg->msg_controllen < cmlen)
+		cmlen = msg->msg_controllen;
 	msg->msg_control += cmlen;
 	msg->msg_controllen -= cmlen;
 	err = 0;