]> git.proxmox.com Git - pve-kernel.git/blob - CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
937d6a640a42acc235909cd88664f0b83c96119d
[pve-kernel.git] / CVE-2017-7482-rxrpc-Fix-several-cases-where-a-padded-len-isn-t-che.patch
1 From 453b5039843f7dac534ee23af6b34c2d0a116416 Mon Sep 17 00:00:00 2001
2 From: David Howells <dhowells@redhat.com>
3 Date: Wed, 12 Jul 2017 16:30:25 +0200
4 Subject: [PATCH 3/3] rxrpc: Fix several cases where a padded len isn't checked
5 in ticket decode
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 This fixes CVE-2017-7482.
11
12 When a kerberos 5 ticket is being decoded so that it can be loaded into an
13 rxrpc-type key, there are several places in which the length of a
14 variable-length field is checked to make sure that it's not going to
15 overrun the available data - but the data is padded to the nearest
16 four-byte boundary and the code doesn't check for this extra. This could
17 lead to the size-remaining variable wrapping and the data pointer going
18 over the end of the buffer.
19
20 Fix this by making the various variable-length data checks use the padded
21 length.
22
23 Reported-by: 石磊 <shilei-c@360.cn>
24 Signed-off-by: David Howells <dhowells@redhat.com>
25 Reviewed-by: Marc Dionne <marc.c.dionne@auristor.com>
26 Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
27 Signed-off-by: David S. Miller <davem@davemloft.net>
28
29 CVE-2017-7482
30
31 (cherry-picked from commit 5f2f97656ada8d811d3c1bef503ced266fcd53a0)
32 Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
33 Acked-by: Seth Forshee <seth.forshee@canonical.com>
34 Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
35 Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
36
37 Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
38 ---
39 net/rxrpc/key.c | 64 ++++++++++++++++++++++++++++++---------------------------
40 1 file changed, 34 insertions(+), 30 deletions(-)
41
42 diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
43 index 18c737a61d80..7fc340726d03 100644
44 --- a/net/rxrpc/key.c
45 +++ b/net/rxrpc/key.c
46 @@ -217,7 +217,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
47 unsigned int *_toklen)
48 {
49 const __be32 *xdr = *_xdr;
50 - unsigned int toklen = *_toklen, n_parts, loop, tmp;
51 + unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen;
52
53 /* there must be at least one name, and at least #names+1 length
54 * words */
55 @@ -247,16 +247,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
56 toklen -= 4;
57 if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
58 return -EINVAL;
59 - if (tmp > toklen)
60 + paddedlen = (tmp + 3) & ~3;
61 + if (paddedlen > toklen)
62 return -EINVAL;
63 princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
64 if (!princ->name_parts[loop])
65 return -ENOMEM;
66 memcpy(princ->name_parts[loop], xdr, tmp);
67 princ->name_parts[loop][tmp] = 0;
68 - tmp = (tmp + 3) & ~3;
69 - toklen -= tmp;
70 - xdr += tmp >> 2;
71 + toklen -= paddedlen;
72 + xdr += paddedlen >> 2;
73 }
74
75 if (toklen < 4)
76 @@ -265,16 +265,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
77 toklen -= 4;
78 if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
79 return -EINVAL;
80 - if (tmp > toklen)
81 + paddedlen = (tmp + 3) & ~3;
82 + if (paddedlen > toklen)
83 return -EINVAL;
84 princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
85 if (!princ->realm)
86 return -ENOMEM;
87 memcpy(princ->realm, xdr, tmp);
88 princ->realm[tmp] = 0;
89 - tmp = (tmp + 3) & ~3;
90 - toklen -= tmp;
91 - xdr += tmp >> 2;
92 + toklen -= paddedlen;
93 + xdr += paddedlen >> 2;
94
95 _debug("%s/...@%s", princ->name_parts[0], princ->realm);
96
97 @@ -293,7 +293,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
98 unsigned int *_toklen)
99 {
100 const __be32 *xdr = *_xdr;
101 - unsigned int toklen = *_toklen, len;
102 + unsigned int toklen = *_toklen, len, paddedlen;
103
104 /* there must be at least one tag and one length word */
105 if (toklen <= 8)
106 @@ -307,15 +307,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
107 toklen -= 8;
108 if (len > max_data_size)
109 return -EINVAL;
110 + paddedlen = (len + 3) & ~3;
111 + if (paddedlen > toklen)
112 + return -EINVAL;
113 td->data_len = len;
114
115 if (len > 0) {
116 td->data = kmemdup(xdr, len, GFP_KERNEL);
117 if (!td->data)
118 return -ENOMEM;
119 - len = (len + 3) & ~3;
120 - toklen -= len;
121 - xdr += len >> 2;
122 + toklen -= paddedlen;
123 + xdr += paddedlen >> 2;
124 }
125
126 _debug("tag %x len %x", td->tag, td->data_len);
127 @@ -387,7 +389,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
128 const __be32 **_xdr, unsigned int *_toklen)
129 {
130 const __be32 *xdr = *_xdr;
131 - unsigned int toklen = *_toklen, len;
132 + unsigned int toklen = *_toklen, len, paddedlen;
133
134 /* there must be at least one length word */
135 if (toklen <= 4)
136 @@ -399,6 +401,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
137 toklen -= 4;
138 if (len > AFSTOKEN_K5_TIX_MAX)
139 return -EINVAL;
140 + paddedlen = (len + 3) & ~3;
141 + if (paddedlen > toklen)
142 + return -EINVAL;
143 *_tktlen = len;
144
145 _debug("ticket len %u", len);
146 @@ -407,9 +412,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
147 *_ticket = kmemdup(xdr, len, GFP_KERNEL);
148 if (!*_ticket)
149 return -ENOMEM;
150 - len = (len + 3) & ~3;
151 - toklen -= len;
152 - xdr += len >> 2;
153 + toklen -= paddedlen;
154 + xdr += paddedlen >> 2;
155 }
156
157 *_xdr = xdr;
158 @@ -552,7 +556,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
159 {
160 const __be32 *xdr = prep->data, *token;
161 const char *cp;
162 - unsigned int len, tmp, loop, ntoken, toklen, sec_ix;
163 + unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
164 size_t datalen = prep->datalen;
165 int ret;
166
167 @@ -578,22 +582,21 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
168 if (len < 1 || len > AFSTOKEN_CELL_MAX)
169 goto not_xdr;
170 datalen -= 4;
171 - tmp = (len + 3) & ~3;
172 - if (tmp > datalen)
173 + paddedlen = (len + 3) & ~3;
174 + if (paddedlen > datalen)
175 goto not_xdr;
176
177 cp = (const char *) xdr;
178 for (loop = 0; loop < len; loop++)
179 if (!isprint(cp[loop]))
180 goto not_xdr;
181 - if (len < tmp)
182 - for (; loop < tmp; loop++)
183 - if (cp[loop])
184 - goto not_xdr;
185 + for (; loop < paddedlen; loop++)
186 + if (cp[loop])
187 + goto not_xdr;
188 _debug("cellname: [%u/%u] '%*.*s'",
189 - len, tmp, len, len, (const char *) xdr);
190 - datalen -= tmp;
191 - xdr += tmp >> 2;
192 + len, paddedlen, len, len, (const char *) xdr);
193 + datalen -= paddedlen;
194 + xdr += paddedlen >> 2;
195
196 /* get the token count */
197 if (datalen < 12)
198 @@ -614,10 +617,11 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
199 sec_ix = ntohl(*xdr);
200 datalen -= 4;
201 _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
202 - if (toklen < 20 || toklen > datalen)
203 + paddedlen = (toklen + 3) & ~3;
204 + if (toklen < 20 || toklen > datalen || paddedlen > datalen)
205 goto not_xdr;
206 - datalen -= (toklen + 3) & ~3;
207 - xdr += (toklen + 3) >> 2;
208 + datalen -= paddedlen;
209 + xdr += paddedlen >> 2;
210
211 } while (--loop > 0);
212
213 --
214 2.11.0
215