]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.16.3/libceph-do-not-hard-code-max-auth-ticket-len.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.16.3 / libceph-do-not-hard-code-max-auth-ticket-len.patch
CommitLineData
9515b5a6
GKH
1From c27a3e4d667fdcad3db7b104f75659478e0c68d8 Mon Sep 17 00:00:00 2001
2From: Ilya Dryomov <ilya.dryomov@inktank.com>
3Date: Tue, 9 Sep 2014 19:39:15 +0400
4Subject: libceph: do not hard code max auth ticket len
5
6From: Ilya Dryomov <ilya.dryomov@inktank.com>
7
8commit c27a3e4d667fdcad3db7b104f75659478e0c68d8 upstream.
9
10We hard code cephx auth ticket buffer size to 256 bytes. This isn't
11enough for any moderate setups and, in case tickets themselves are not
12encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but
13ceph_decode_copy() doesn't - it's just a memcpy() wrapper). Since the
14buffer is allocated dynamically anyway, allocated it a bit later, at
15the point where we know how much is going to be needed.
16
17Fixes: http://tracker.ceph.com/issues/8979
18
19Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
20Reviewed-by: Sage Weil <sage@redhat.com>
21Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23---
24 net/ceph/auth_x.c | 64 ++++++++++++++++++++++++------------------------------
25 1 file changed, 29 insertions(+), 35 deletions(-)
26
27--- a/net/ceph/auth_x.c
28+++ b/net/ceph/auth_x.c
29@@ -13,8 +13,6 @@
30 #include "auth_x.h"
31 #include "auth_x_protocol.h"
32
33-#define TEMP_TICKET_BUF_LEN 256
34-
35 static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
36
37 static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
38@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_cr
39 }
40
41 static int ceph_x_decrypt(struct ceph_crypto_key *secret,
42- void **p, void *end, void *obuf, size_t olen)
43+ void **p, void *end, void **obuf, size_t olen)
44 {
45 struct ceph_x_encrypt_header head;
46 size_t head_len = sizeof(head);
47@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_cr
48 return -EINVAL;
49
50 dout("ceph_x_decrypt len %d\n", len);
51- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
52- *p, len);
53+ if (*obuf == NULL) {
54+ *obuf = kmalloc(len, GFP_NOFS);
55+ if (!*obuf)
56+ return -ENOMEM;
57+ olen = len;
58+ }
59+
60+ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
61 if (ret)
62 return ret;
63 if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
64@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct
65
66 static int process_one_ticket(struct ceph_auth_client *ac,
67 struct ceph_crypto_key *secret,
68- void **p, void *end,
69- void *dbuf, void *ticket_buf)
70+ void **p, void *end)
71 {
72 struct ceph_x_info *xi = ac->private;
73 int type;
74 u8 tkt_struct_v, blob_struct_v;
75 struct ceph_x_ticket_handler *th;
76+ void *dbuf = NULL;
77 void *dp, *dend;
78 int dlen;
79 char is_enc;
80 struct timespec validity;
81 struct ceph_crypto_key old_key;
82+ void *ticket_buf = NULL;
83 void *tp, *tpend;
84 struct ceph_timespec new_validity;
85 struct ceph_crypto_key new_session_key;
86@@ -167,8 +172,7 @@ static int process_one_ticket(struct cep
87 }
88
89 /* blob for me */
90- dlen = ceph_x_decrypt(secret, p, end, dbuf,
91- TEMP_TICKET_BUF_LEN);
92+ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
93 if (dlen <= 0) {
94 ret = dlen;
95 goto out;
96@@ -195,20 +199,25 @@ static int process_one_ticket(struct cep
97
98 /* ticket blob for service */
99 ceph_decode_8_safe(p, end, is_enc, bad);
100- tp = ticket_buf;
101 if (is_enc) {
102 /* encrypted */
103 dout(" encrypted ticket\n");
104- dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf,
105- TEMP_TICKET_BUF_LEN);
106+ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
107 if (dlen < 0) {
108 ret = dlen;
109 goto out;
110 }
111+ tp = ticket_buf;
112 dlen = ceph_decode_32(&tp);
113 } else {
114 /* unencrypted */
115 ceph_decode_32_safe(p, end, dlen, bad);
116+ ticket_buf = kmalloc(dlen, GFP_NOFS);
117+ if (!ticket_buf) {
118+ ret = -ENOMEM;
119+ goto out;
120+ }
121+ tp = ticket_buf;
122 ceph_decode_need(p, end, dlen, bad);
123 ceph_decode_copy(p, ticket_buf, dlen);
124 }
125@@ -237,6 +246,8 @@ static int process_one_ticket(struct cep
126 xi->have_keys |= th->service;
127
128 out:
129+ kfree(ticket_buf);
130+ kfree(dbuf);
131 return ret;
132
133 bad:
134@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(stru
135 void *buf, void *end)
136 {
137 void *p = buf;
138- char *dbuf;
139- char *ticket_buf;
140 u8 reply_struct_v;
141 u32 num;
142 int ret;
143
144- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
145- if (!dbuf)
146- return -ENOMEM;
147-
148- ret = -ENOMEM;
149- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
150- if (!ticket_buf)
151- goto out_dbuf;
152-
153 ceph_decode_8_safe(&p, end, reply_struct_v, bad);
154 if (reply_struct_v != 1)
155 return -EINVAL;
156@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(stru
157 dout("%d tickets\n", num);
158
159 while (num--) {
160- ret = process_one_ticket(ac, secret, &p, end,
161- dbuf, ticket_buf);
162+ ret = process_one_ticket(ac, secret, &p, end);
163 if (ret)
164- goto out;
165+ return ret;
166 }
167
168- ret = 0;
169-out:
170- kfree(ticket_buf);
171-out_dbuf:
172- kfree(dbuf);
173- return ret;
174+ return 0;
175
176 bad:
177- ret = -EINVAL;
178- goto out;
179+ return -EINVAL;
180 }
181
182 static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
183@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_repl
184 struct ceph_x_ticket_handler *th;
185 int ret = 0;
186 struct ceph_x_authorize_reply reply;
187+ void *preply = &reply;
188 void *p = au->reply_buf;
189 void *end = p + sizeof(au->reply_buf);
190
191 th = get_ticket_handler(ac, au->service);
192 if (IS_ERR(th))
193 return PTR_ERR(th);
194- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
195+ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
196 if (ret < 0)
197 return ret;
198 if (ret != sizeof(reply))