aboutsummaryrefslogtreecommitdiffstats
path: root/net/ceph
diff options
context:
space:
mode:
authorIlya Dryomov <ilya.dryomov@inktank.com>2014-09-09 11:39:15 -0400
committerIlya Dryomov <ilya.dryomov@inktank.com>2014-09-10 12:08:36 -0400
commitc27a3e4d667fdcad3db7b104f75659478e0c68d8 (patch)
treee92bd4ec8ba94b9bf361c8df5f8d32f97b9f441c /net/ceph
parent597cda357716a3cf8d994cb11927af917c8d71fa (diff)
libceph: do not hard code max auth ticket len
We hard code cephx auth ticket buffer size to 256 bytes. This isn't enough for any moderate setups and, in case tickets themselves are not encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but ceph_decode_copy() doesn't - it's just a memcpy() wrapper). Since the buffer is allocated dynamically anyway, allocated it a bit later, at the point where we know how much is going to be needed. Fixes: http://tracker.ceph.com/issues/8979 Cc: stable@vger.kernel.org Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com> Reviewed-by: Sage Weil <sage@redhat.com>
Diffstat (limited to 'net/ceph')
-rw-r--r--net/ceph/auth_x.c64
1 files changed, 29 insertions, 35 deletions
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index 0eb146dce1aa..de6662b14e1f 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -13,8 +13,6 @@
13#include "auth_x.h" 13#include "auth_x.h"
14#include "auth_x_protocol.h" 14#include "auth_x_protocol.h"
15 15
16#define TEMP_TICKET_BUF_LEN 256
17
18static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); 16static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
19 17
20static int ceph_x_is_authenticated(struct ceph_auth_client *ac) 18static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
64} 62}
65 63
66static int ceph_x_decrypt(struct ceph_crypto_key *secret, 64static int ceph_x_decrypt(struct ceph_crypto_key *secret,
67 void **p, void *end, void *obuf, size_t olen) 65 void **p, void *end, void **obuf, size_t olen)
68{ 66{
69 struct ceph_x_encrypt_header head; 67 struct ceph_x_encrypt_header head;
70 size_t head_len = sizeof(head); 68 size_t head_len = sizeof(head);
@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
75 return -EINVAL; 73 return -EINVAL;
76 74
77 dout("ceph_x_decrypt len %d\n", len); 75 dout("ceph_x_decrypt len %d\n", len);
78 ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen, 76 if (*obuf == NULL) {
79 *p, len); 77 *obuf = kmalloc(len, GFP_NOFS);
78 if (!*obuf)
79 return -ENOMEM;
80 olen = len;
81 }
82
83 ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
80 if (ret) 84 if (ret)
81 return ret; 85 return ret;
82 if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) 86 if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct ceph_auth_client *ac,
131 135
132static int process_one_ticket(struct ceph_auth_client *ac, 136static int process_one_ticket(struct ceph_auth_client *ac,
133 struct ceph_crypto_key *secret, 137 struct ceph_crypto_key *secret,
134 void **p, void *end, 138 void **p, void *end)
135 void *dbuf, void *ticket_buf)
136{ 139{
137 struct ceph_x_info *xi = ac->private; 140 struct ceph_x_info *xi = ac->private;
138 int type; 141 int type;
139 u8 tkt_struct_v, blob_struct_v; 142 u8 tkt_struct_v, blob_struct_v;
140 struct ceph_x_ticket_handler *th; 143 struct ceph_x_ticket_handler *th;
144 void *dbuf = NULL;
141 void *dp, *dend; 145 void *dp, *dend;
142 int dlen; 146 int dlen;
143 char is_enc; 147 char is_enc;
144 struct timespec validity; 148 struct timespec validity;
145 struct ceph_crypto_key old_key; 149 struct ceph_crypto_key old_key;
150 void *ticket_buf = NULL;
146 void *tp, *tpend; 151 void *tp, *tpend;
147 struct ceph_timespec new_validity; 152 struct ceph_timespec new_validity;
148 struct ceph_crypto_key new_session_key; 153 struct ceph_crypto_key new_session_key;
@@ -167,8 +172,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
167 } 172 }
168 173
169 /* blob for me */ 174 /* blob for me */
170 dlen = ceph_x_decrypt(secret, p, end, dbuf, 175 dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
171 TEMP_TICKET_BUF_LEN);
172 if (dlen <= 0) { 176 if (dlen <= 0) {
173 ret = dlen; 177 ret = dlen;
174 goto out; 178 goto out;
@@ -195,20 +199,25 @@ static int process_one_ticket(struct ceph_auth_client *ac,
195 199
196 /* ticket blob for service */ 200 /* ticket blob for service */
197 ceph_decode_8_safe(p, end, is_enc, bad); 201 ceph_decode_8_safe(p, end, is_enc, bad);
198 tp = ticket_buf;
199 if (is_enc) { 202 if (is_enc) {
200 /* encrypted */ 203 /* encrypted */
201 dout(" encrypted ticket\n"); 204 dout(" encrypted ticket\n");
202 dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf, 205 dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
203 TEMP_TICKET_BUF_LEN);
204 if (dlen < 0) { 206 if (dlen < 0) {
205 ret = dlen; 207 ret = dlen;
206 goto out; 208 goto out;
207 } 209 }
210 tp = ticket_buf;
208 dlen = ceph_decode_32(&tp); 211 dlen = ceph_decode_32(&tp);
209 } else { 212 } else {
210 /* unencrypted */ 213 /* unencrypted */
211 ceph_decode_32_safe(p, end, dlen, bad); 214 ceph_decode_32_safe(p, end, dlen, bad);
215 ticket_buf = kmalloc(dlen, GFP_NOFS);
216 if (!ticket_buf) {
217 ret = -ENOMEM;
218 goto out;
219 }
220 tp = ticket_buf;
212 ceph_decode_need(p, end, dlen, bad); 221 ceph_decode_need(p, end, dlen, bad);
213 ceph_decode_copy(p, ticket_buf, dlen); 222 ceph_decode_copy(p, ticket_buf, dlen);
214 } 223 }
@@ -237,6 +246,8 @@ static int process_one_ticket(struct ceph_auth_client *ac,
237 xi->have_keys |= th->service; 246 xi->have_keys |= th->service;
238 247
239out: 248out:
249 kfree(ticket_buf);
250 kfree(dbuf);
240 return ret; 251 return ret;
241 252
242bad: 253bad:
@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
249 void *buf, void *end) 260 void *buf, void *end)
250{ 261{
251 void *p = buf; 262 void *p = buf;
252 char *dbuf;
253 char *ticket_buf;
254 u8 reply_struct_v; 263 u8 reply_struct_v;
255 u32 num; 264 u32 num;
256 int ret; 265 int ret;
257 266
258 dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
259 if (!dbuf)
260 return -ENOMEM;
261
262 ret = -ENOMEM;
263 ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
264 if (!ticket_buf)
265 goto out_dbuf;
266
267 ceph_decode_8_safe(&p, end, reply_struct_v, bad); 267 ceph_decode_8_safe(&p, end, reply_struct_v, bad);
268 if (reply_struct_v != 1) 268 if (reply_struct_v != 1)
269 return -EINVAL; 269 return -EINVAL;
@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
272 dout("%d tickets\n", num); 272 dout("%d tickets\n", num);
273 273
274 while (num--) { 274 while (num--) {
275 ret = process_one_ticket(ac, secret, &p, end, 275 ret = process_one_ticket(ac, secret, &p, end);
276 dbuf, ticket_buf);
277 if (ret) 276 if (ret)
278 goto out; 277 return ret;
279 } 278 }
280 279
281 ret = 0; 280 return 0;
282out:
283 kfree(ticket_buf);
284out_dbuf:
285 kfree(dbuf);
286 return ret;
287 281
288bad: 282bad:
289 ret = -EINVAL; 283 return -EINVAL;
290 goto out;
291} 284}
292 285
293static int ceph_x_build_authorizer(struct ceph_auth_client *ac, 286static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
603 struct ceph_x_ticket_handler *th; 596 struct ceph_x_ticket_handler *th;
604 int ret = 0; 597 int ret = 0;
605 struct ceph_x_authorize_reply reply; 598 struct ceph_x_authorize_reply reply;
599 void *preply = &reply;
606 void *p = au->reply_buf; 600 void *p = au->reply_buf;
607 void *end = p + sizeof(au->reply_buf); 601 void *end = p + sizeof(au->reply_buf);
608 602
609 th = get_ticket_handler(ac, au->service); 603 th = get_ticket_handler(ac, au->service);
610 if (IS_ERR(th)) 604 if (IS_ERR(th))
611 return PTR_ERR(th); 605 return PTR_ERR(th);
612 ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply)); 606 ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
613 if (ret < 0) 607 if (ret < 0)
614 return ret; 608 return ret;
615 if (ret != sizeof(reply)) 609 if (ret != sizeof(reply))