Skip to content

Commit c27a3e4

Browse files
committed
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>
1 parent 597cda3 commit c27a3e4

File tree

1 file changed

+29
-35
lines changed

1 file changed

+29
-35
lines changed

Diff for: net/ceph/auth_x.c

+29-35
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#include "auth_x.h"
1414
#include "auth_x_protocol.h"
1515

16-
#define TEMP_TICKET_BUF_LEN 256
17-
1816
static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
1917

2018
static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
6462
}
6563

6664
static 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)
6866
{
6967
struct ceph_x_encrypt_header head;
7068
size_t head_len = sizeof(head);
@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
7573
return -EINVAL;
7674

7775
dout("ceph_x_decrypt len %d\n", len);
78-
ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
79-
*p, len);
76+
if (*obuf == NULL) {
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);
8084
if (ret)
8185
return ret;
8286
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,
131135

132136
static int process_one_ticket(struct ceph_auth_client *ac,
133137
struct ceph_crypto_key *secret,
134-
void **p, void *end,
135-
void *dbuf, void *ticket_buf)
138+
void **p, void *end)
136139
{
137140
struct ceph_x_info *xi = ac->private;
138141
int type;
139142
u8 tkt_struct_v, blob_struct_v;
140143
struct ceph_x_ticket_handler *th;
144+
void *dbuf = NULL;
141145
void *dp, *dend;
142146
int dlen;
143147
char is_enc;
144148
struct timespec validity;
145149
struct ceph_crypto_key old_key;
150+
void *ticket_buf = NULL;
146151
void *tp, *tpend;
147152
struct ceph_timespec new_validity;
148153
struct ceph_crypto_key new_session_key;
@@ -167,8 +172,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
167172
}
168173

169174
/* blob for me */
170-
dlen = ceph_x_decrypt(secret, p, end, dbuf,
171-
TEMP_TICKET_BUF_LEN);
175+
dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
172176
if (dlen <= 0) {
173177
ret = dlen;
174178
goto out;
@@ -195,20 +199,25 @@ static int process_one_ticket(struct ceph_auth_client *ac,
195199

196200
/* ticket blob for service */
197201
ceph_decode_8_safe(p, end, is_enc, bad);
198-
tp = ticket_buf;
199202
if (is_enc) {
200203
/* encrypted */
201204
dout(" encrypted ticket\n");
202-
dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
203-
TEMP_TICKET_BUF_LEN);
205+
dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
204206
if (dlen < 0) {
205207
ret = dlen;
206208
goto out;
207209
}
210+
tp = ticket_buf;
208211
dlen = ceph_decode_32(&tp);
209212
} else {
210213
/* unencrypted */
211214
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;
212221
ceph_decode_need(p, end, dlen, bad);
213222
ceph_decode_copy(p, ticket_buf, dlen);
214223
}
@@ -237,6 +246,8 @@ static int process_one_ticket(struct ceph_auth_client *ac,
237246
xi->have_keys |= th->service;
238247

239248
out:
249+
kfree(ticket_buf);
250+
kfree(dbuf);
240251
return ret;
241252

242253
bad:
@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
249260
void *buf, void *end)
250261
{
251262
void *p = buf;
252-
char *dbuf;
253-
char *ticket_buf;
254263
u8 reply_struct_v;
255264
u32 num;
256265
int ret;
257266

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-
267267
ceph_decode_8_safe(&p, end, reply_struct_v, bad);
268268
if (reply_struct_v != 1)
269269
return -EINVAL;
@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
272272
dout("%d tickets\n", num);
273273

274274
while (num--) {
275-
ret = process_one_ticket(ac, secret, &p, end,
276-
dbuf, ticket_buf);
275+
ret = process_one_ticket(ac, secret, &p, end);
277276
if (ret)
278-
goto out;
277+
return ret;
279278
}
280279

281-
ret = 0;
282-
out:
283-
kfree(ticket_buf);
284-
out_dbuf:
285-
kfree(dbuf);
286-
return ret;
280+
return 0;
287281

288282
bad:
289-
ret = -EINVAL;
290-
goto out;
283+
return -EINVAL;
291284
}
292285

293286
static 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,
603596
struct ceph_x_ticket_handler *th;
604597
int ret = 0;
605598
struct ceph_x_authorize_reply reply;
599+
void *preply = &reply;
606600
void *p = au->reply_buf;
607601
void *end = p + sizeof(au->reply_buf);
608602

609603
th = get_ticket_handler(ac, au->service);
610604
if (IS_ERR(th))
611605
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));
613607
if (ret < 0)
614608
return ret;
615609
if (ret != sizeof(reply))

0 commit comments

Comments
 (0)