forked from curl/curl-www
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CVE-2017-8818.patch
142 lines (126 loc) · 5.15 KB
/
CVE-2017-8818.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
From 3888095ed2fa32870c2a5452bd91ca21efa70907 Mon Sep 17 00:00:00 2001
From: Jay Satiro <[email protected]>
Date: Mon, 20 Nov 2017 01:26:19 -0500
Subject: [PATCH] url: fix alignment of ssl_backend_data struct
- Align the array of ssl_backend_data on a max 32 byte boundary.
8 is likely to be ok but I went with 32 for posterity should one of
the ssl_backend_data structs change to contain a larger sized variable
in the future.
Prior to this change (since dev 70f1db3, release 7.56) the connectdata
structure was undersized by 4 bytes in 32-bit builds with ssl enabled
because long long * was mistakenly used for alignment instead of
long long, with the intention being an 8 byte boundary. Also long long
may not be an available type.
The undersized connectdata could lead to oob read/write past the end in
what was expected to be the last 4 bytes of the connection's secondary
socket https proxy ssl_backend_data struct (the secondary socket in a
connection is used by ftp, others?).
Closes https://github.com/curl/curl/issues/2093
CVE-2017-8818
Bug: https://curl.se/docs/adv_2017-af0a.html
---
lib/url.c | 51 ++++++++++++++++++++++++++++++---------------------
lib/urldata.h | 10 ----------
2 files changed, 30 insertions(+), 31 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index 9f9fa0c43..47f69c9f1 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1791,19 +1791,45 @@ static void llist_dtor(void *user, void *element)
/*
* Allocate and initialize a new connectdata object.
*/
static struct connectdata *allocate_conn(struct Curl_easy *data)
{
+ struct connectdata *conn;
+ size_t connsize = sizeof(struct connectdata);
+
#ifdef USE_SSL
-#define SSL_EXTRA + 4 * Curl_ssl->sizeof_ssl_backend_data - sizeof(long long)
-#else
-#define SSL_EXTRA 0
+/* SSLBK_MAX_ALIGN: The max byte alignment a CPU would use */
+#define SSLBK_MAX_ALIGN 32
+ /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
+ part of connectdata at the end. To ensure suitable alignment we will
+ assume a maximum of SSLBK_MAX_ALIGN for alignment. Since calloc returns a
+ pointer suitably aligned for any variable this will ensure the
+ ssl_backend_data array has proper alignment, even if that alignment turns
+ out to be less than SSLBK_MAX_ALIGN. */
+ size_t paddingsize = sizeof(struct connectdata) % SSLBK_MAX_ALIGN;
+ size_t alignsize = paddingsize ? (SSLBK_MAX_ALIGN - paddingsize) : 0;
+ size_t sslbksize = Curl_ssl->sizeof_ssl_backend_data;
+ connsize += alignsize + (4 * sslbksize);
#endif
- struct connectdata *conn = calloc(1, sizeof(struct connectdata) + SSL_EXTRA);
+
+ conn = calloc(1, connsize);
if(!conn)
return NULL;
+#ifdef USE_SSL
+ /* Point to the ssl_backend_data objects at the end of connectdata.
+ Note that these backend pointers can be swapped by vtls (eg ssl backend
+ data becomes proxy backend data). */
+ {
+ char *end = (char *)conn + connsize;
+ conn->ssl[0].backend = ((void *)(end - (4 * sslbksize)));
+ conn->ssl[1].backend = ((void *)(end - (3 * sslbksize)));
+ conn->proxy_ssl[0].backend = ((void *)(end - (2 * sslbksize)));
+ conn->proxy_ssl[1].backend = ((void *)(end - (1 * sslbksize)));
+ }
+#endif
+
conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
already from start to avoid NULL
situations and checks */
/* and we setup a few fields in case we end up actually using this struct */
@@ -1879,27 +1905,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
conn->ip_version = data->set.ipver;
-#ifdef USE_SSL
- /*
- * To save on malloc()s, the SSL backend-specific data has been allocated
- * at the end of the connectdata struct.
- */
- {
- char *p = (char *)&conn->align_data__do_not_use;
- conn->ssl[0].backend = (struct ssl_backend_data *)p;
- conn->ssl[1].backend =
- (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data);
- conn->proxy_ssl[0].backend =
- (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 2);
- conn->proxy_ssl[1].backend =
- (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 3);
- }
-#endif
-
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
conn->ntlm_auth_hlpr_pid = 0;
conn->challenge_header = NULL;
diff --git a/lib/urldata.h b/lib/urldata.h
index 94f692223..edd1fd9ac 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1002,20 +1002,10 @@ struct connectdata {
#ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
bool abstract_unix_socket;
#endif
-
-#ifdef USE_SSL
- /*
- * To avoid multiple malloc() calls, the ssl_connect_data structures
- * associated with a connectdata struct are allocated in the same block
- * as the latter. This field forces alignment to an 8-byte boundary so
- * that this all works.
- */
- long long *align_data__do_not_use;
-#endif
};
/* The end of connectdata. */
/*
--
2.15.0