]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/econet-fix-cve-2010-3848.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / econet-fix-cve-2010-3848.patch
CommitLineData
6dcefc2a
GKH
1From a27e13d370415add3487949c60810e36069a23a6 Mon Sep 17 00:00:00 2001
2From: Phil Blundell <philb@gnu.org>
3Date: Wed, 24 Nov 2010 11:51:47 -0800
4Subject: econet: fix CVE-2010-3848
5
6From: Phil Blundell <philb@gnu.org>
7
8commit a27e13d370415add3487949c60810e36069a23a6 upstream.
9
10Don't declare variable sized array of iovecs on the stack since this
11could cause stack overflow if msg->msgiovlen is large. Instead, coalesce
12the user-supplied data into a new buffer and use a single iovec for it.
13
14Signed-off-by: Phil Blundell <philb@gnu.org>
15Signed-off-by: David S. Miller <davem@davemloft.net>
16Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
17
18---
19 net/econet/af_econet.c | 62 ++++++++++++++++++++++++-------------------------
20 1 file changed, 31 insertions(+), 31 deletions(-)
21
22--- a/net/econet/af_econet.c
23+++ b/net/econet/af_econet.c
24@@ -31,6 +31,7 @@
25 #include <linux/skbuff.h>
26 #include <linux/udp.h>
27 #include <linux/slab.h>
28+#include <linux/vmalloc.h>
29 #include <net/sock.h>
30 #include <net/inet_common.h>
31 #include <linux/stat.h>
32@@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *
33 #endif
34 #ifdef CONFIG_ECONET_AUNUDP
35 struct msghdr udpmsg;
36- struct iovec iov[msg->msg_iovlen+1];
37+ struct iovec iov[2];
38 struct aunhdr ah;
39 struct sockaddr_in udpdest;
40 __kernel_size_t size;
41- int i;
42 mm_segment_t oldfs;
43+ char *userbuf;
44 #endif
45
46 /*
47@@ -319,17 +320,17 @@ static int econet_sendmsg(struct kiocb *
48 }
49 }
50
51- if (len + 15 > dev->mtu) {
52- mutex_unlock(&econet_mutex);
53- return -EMSGSIZE;
54- }
55-
56 if (dev->type == ARPHRD_ECONET) {
57 /* Real hardware Econet. We're not worthy etc. */
58 #ifdef CONFIG_ECONET_NATIVE
59 unsigned short proto = 0;
60 int res;
61
62+ if (len + 15 > dev->mtu) {
63+ mutex_unlock(&econet_mutex);
64+ return -EMSGSIZE;
65+ }
66+
67 dev_hold(dev);
68
69 skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
70@@ -405,6 +406,11 @@ static int econet_sendmsg(struct kiocb *
71 return -ENETDOWN; /* No socket - can't send */
72 }
73
74+ if (len > 32768) {
75+ err = -E2BIG;
76+ goto error;
77+ }
78+
79 /* Make up a UDP datagram and hand it off to some higher intellect. */
80
81 memset(&udpdest, 0, sizeof(udpdest));
82@@ -436,36 +442,26 @@ static int econet_sendmsg(struct kiocb *
83
84 /* tack our header on the front of the iovec */
85 size = sizeof(struct aunhdr);
86- /*
87- * XXX: that is b0rken. We can't mix userland and kernel pointers
88- * in iovec, since on a lot of platforms copy_from_user() will
89- * *not* work with the kernel and userland ones at the same time,
90- * regardless of what we do with set_fs(). And we are talking about
91- * econet-over-ethernet here, so "it's only ARM anyway" doesn't
92- * apply. Any suggestions on fixing that code? -- AV
93- */
94 iov[0].iov_base = (void *)&ah;
95 iov[0].iov_len = size;
96- for (i = 0; i < msg->msg_iovlen; i++) {
97- void __user *base = msg->msg_iov[i].iov_base;
98- size_t iov_len = msg->msg_iov[i].iov_len;
99- /* Check it now since we switch to KERNEL_DS later. */
100- if (!access_ok(VERIFY_READ, base, iov_len)) {
101- mutex_unlock(&econet_mutex);
102- return -EFAULT;
103- }
104- iov[i+1].iov_base = base;
105- iov[i+1].iov_len = iov_len;
106- size += iov_len;
107+
108+ userbuf = vmalloc(len);
109+ if (userbuf == NULL) {
110+ err = -ENOMEM;
111+ goto error;
112 }
113
114+ iov[1].iov_base = userbuf;
115+ iov[1].iov_len = len;
116+ err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
117+ if (err)
118+ goto error_free_buf;
119+
120 /* Get a skbuff (no data, just holds our cb information) */
121 if ((skb = sock_alloc_send_skb(sk, 0,
122 msg->msg_flags & MSG_DONTWAIT,
123- &err)) == NULL) {
124- mutex_unlock(&econet_mutex);
125- return err;
126- }
127+ &err)) == NULL)
128+ goto error_free_buf;
129
130 eb = (struct ec_cb *)&skb->cb;
131
132@@ -481,7 +477,7 @@ static int econet_sendmsg(struct kiocb *
133 udpmsg.msg_name = (void *)&udpdest;
134 udpmsg.msg_namelen = sizeof(udpdest);
135 udpmsg.msg_iov = &iov[0];
136- udpmsg.msg_iovlen = msg->msg_iovlen + 1;
137+ udpmsg.msg_iovlen = 2;
138 udpmsg.msg_control = NULL;
139 udpmsg.msg_controllen = 0;
140 udpmsg.msg_flags=0;
141@@ -489,9 +485,13 @@ static int econet_sendmsg(struct kiocb *
142 oldfs = get_fs(); set_fs(KERNEL_DS); /* More privs :-) */
143 err = sock_sendmsg(udpsock, &udpmsg, size);
144 set_fs(oldfs);
145+
146+error_free_buf:
147+ vfree(userbuf);
148 #else
149 err = -EPROTOTYPE;
150 #endif
151+ error:
152 mutex_unlock(&econet_mutex);
153
154 return err;