Skip to content

Commit

Permalink
libceph: do not hard code max auth ticket len
Browse files Browse the repository at this point in the history
commit c27a3e4 upstream.

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

Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: Sage Weil <sage@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
idryomov authored and gregkh committed Sep 17, 2014
1 parent 5083cbc commit 9956752
Showing 1 changed file with 29 additions and 35 deletions.
64 changes: 29 additions & 35 deletions net/ceph/auth_x.c
Expand Up @@ -13,8 +13,6 @@
#include "auth_x.h"
#include "auth_x_protocol.h"

#define TEMP_TICKET_BUF_LEN 256

static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);

static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
Expand Down Expand Up @@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
}

static int ceph_x_decrypt(struct ceph_crypto_key *secret,
void **p, void *end, void *obuf, size_t olen)
void **p, void *end, void **obuf, size_t olen)
{
struct ceph_x_encrypt_header head;
size_t head_len = sizeof(head);
Expand All @@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
return -EINVAL;

dout("ceph_x_decrypt len %d\n", len);
ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
*p, len);
if (*obuf == NULL) {
*obuf = kmalloc(len, GFP_NOFS);
if (!*obuf)
return -ENOMEM;
olen = len;
}

ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
if (ret)
return ret;
if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
Expand Down Expand Up @@ -131,18 +135,19 @@ static void remove_ticket_handler(struct ceph_auth_client *ac,

static int process_one_ticket(struct ceph_auth_client *ac,
struct ceph_crypto_key *secret,
void **p, void *end,
void *dbuf, void *ticket_buf)
void **p, void *end)
{
struct ceph_x_info *xi = ac->private;
int type;
u8 tkt_struct_v, blob_struct_v;
struct ceph_x_ticket_handler *th;
void *dbuf = NULL;
void *dp, *dend;
int dlen;
char is_enc;
struct timespec validity;
struct ceph_crypto_key old_key;
void *ticket_buf = NULL;
void *tp, *tpend;
struct ceph_timespec new_validity;
struct ceph_crypto_key new_session_key;
Expand All @@ -167,8 +172,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
}

/* blob for me */
dlen = ceph_x_decrypt(secret, p, end, dbuf,
TEMP_TICKET_BUF_LEN);
dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
if (dlen <= 0) {
ret = dlen;
goto out;
Expand All @@ -195,20 +199,25 @@ static int process_one_ticket(struct ceph_auth_client *ac,

/* ticket blob for service */
ceph_decode_8_safe(p, end, is_enc, bad);
tp = ticket_buf;
if (is_enc) {
/* encrypted */
dout(" encrypted ticket\n");
dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
TEMP_TICKET_BUF_LEN);
dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
if (dlen < 0) {
ret = dlen;
goto out;
}
tp = ticket_buf;
dlen = ceph_decode_32(&tp);
} else {
/* unencrypted */
ceph_decode_32_safe(p, end, dlen, bad);
ticket_buf = kmalloc(dlen, GFP_NOFS);
if (!ticket_buf) {
ret = -ENOMEM;
goto out;
}
tp = ticket_buf;
ceph_decode_need(p, end, dlen, bad);
ceph_decode_copy(p, ticket_buf, dlen);
}
Expand Down Expand Up @@ -237,6 +246,8 @@ static int process_one_ticket(struct ceph_auth_client *ac,
xi->have_keys |= th->service;

out:
kfree(ticket_buf);
kfree(dbuf);
return ret;

bad:
Expand All @@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
void *buf, void *end)
{
void *p = buf;
char *dbuf;
char *ticket_buf;
u8 reply_struct_v;
u32 num;
int ret;

dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
if (!dbuf)
return -ENOMEM;

ret = -ENOMEM;
ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
if (!ticket_buf)
goto out_dbuf;

ceph_decode_8_safe(&p, end, reply_struct_v, bad);
if (reply_struct_v != 1)
return -EINVAL;
Expand All @@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
dout("%d tickets\n", num);

while (num--) {
ret = process_one_ticket(ac, secret, &p, end,
dbuf, ticket_buf);
ret = process_one_ticket(ac, secret, &p, end);
if (ret)
goto out;
return ret;
}

ret = 0;
out:
kfree(ticket_buf);
out_dbuf:
kfree(dbuf);
return ret;
return 0;

bad:
ret = -EINVAL;
goto out;
return -EINVAL;
}

static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
Expand Down Expand Up @@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
struct ceph_x_ticket_handler *th;
int ret = 0;
struct ceph_x_authorize_reply reply;
void *preply = &reply;
void *p = au->reply_buf;
void *end = p + sizeof(au->reply_buf);

th = get_ticket_handler(ac, au->service);
if (IS_ERR(th))
return PTR_ERR(th);
ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
if (ret < 0)
return ret;
if (ret != sizeof(reply))
Expand Down

0 comments on commit 9956752

Please sign in to comment.