]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/net-limit-socket-i-o-iovec-total-length-to-int_max.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / net-limit-socket-i-o-iovec-total-length-to-int_max.patch
CommitLineData
bcd4f083
GKH
1From 8acfe468b0384e834a303f08ebc4953d72fb690a Mon Sep 17 00:00:00 2001
2From: David S. Miller <davem@davemloft.net>
3Date: Thu, 28 Oct 2010 11:41:55 -0700
4Subject: net: Limit socket I/O iovec total length to INT_MAX.
5
6From: David S. Miller <davem@davemloft.net>
7
8commit 8acfe468b0384e834a303f08ebc4953d72fb690a upstream.
9
10This helps protect us from overflow issues down in the
11individual protocol sendmsg/recvmsg handlers. Once
12we hit INT_MAX we truncate out the rest of the iovec
13by setting the iov_len members to zero.
14
15This works because:
16
171) For SOCK_STREAM and SOCK_SEQPACKET sockets, partial
18 writes are allowed and the application will just continue
19 with another write to send the rest of the data.
20
212) For datagram oriented sockets, where there must be a
22 one-to-one correspondance between write() calls and
23 packets on the wire, INT_MAX is going to be far larger
24 than the packet size limit the protocol is going to
25 check for and signal with -EMSGSIZE.
26
27Based upon a patch by Linus Torvalds.
28
29Signed-off-by: David S. Miller <davem@davemloft.net>
30Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
31
32---
33 include/linux/socket.h | 2 +-
34 net/compat.c | 10 ++++++----
35 net/core/iovec.c | 20 +++++++++-----------
36 3 files changed, 16 insertions(+), 16 deletions(-)
37
38--- a/include/linux/socket.h
39+++ b/include/linux/socket.h
40@@ -322,7 +322,7 @@ extern int csum_partial_copy_fromiovecen
41 int offset,
42 unsigned int len, __wsum *csump);
43
44-extern long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
45+extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
46 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
47 extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
48 int offset, int len);
49--- a/net/compat.c
50+++ b/net/compat.c
51@@ -41,10 +41,12 @@ static inline int iov_from_user_compat_t
52 compat_size_t len;
53
54 if (get_user(len, &uiov32->iov_len) ||
55- get_user(buf, &uiov32->iov_base)) {
56- tot_len = -EFAULT;
57- break;
58- }
59+ get_user(buf, &uiov32->iov_base))
60+ return -EFAULT;
61+
62+ if (len > INT_MAX - tot_len)
63+ len = INT_MAX - tot_len;
64+
65 tot_len += len;
66 kiov->iov_base = compat_ptr(buf);
67 kiov->iov_len = (__kernel_size_t) len;
68--- a/net/core/iovec.c
69+++ b/net/core/iovec.c
70@@ -35,10 +35,9 @@
71 * in any case.
72 */
73
74-long verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
75+int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
76 {
77- int size, ct;
78- long err;
79+ int size, ct, err;
80
81 if (m->msg_namelen) {
82 if (mode == VERIFY_READ) {
83@@ -60,14 +59,13 @@ long verify_iovec(struct msghdr *m, stru
84 err = 0;
85
86 for (ct = 0; ct < m->msg_iovlen; ct++) {
87- err += iov[ct].iov_len;
88- /*
89- * Goal is not to verify user data, but to prevent returning
90- * negative value, which is interpreted as errno.
91- * Overflow is still possible, but it is harmless.
92- */
93- if (err < 0)
94- return -EMSGSIZE;
95+ size_t len = iov[ct].iov_len;
96+
97+ if (len > INT_MAX - err) {
98+ len = INT_MAX - err;
99+ iov[ct].iov_len = len;
100+ }
101+ err += len;
102 }
103
104 return err;