Commit 3f62b3ed08611edc3b68ad7534c991cf0a62c135

Authored by Rabin Vincent
Committed by Greg Kroah-Hartman
1 parent 1cfececcbc

crypto: af_alg - fix backlog handling

commit 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e upstream.

If a request is backlogged, it's complete() handler will get called
twice: once with -EINPROGRESS, and once with the final error code.

af_alg's complete handler, unlike other users, does not handle the
-EINPROGRESS but instead always completes the completion that recvmsg()
is waiting on.  This can lead to a return to user space while the
request is still pending in the driver.  If userspace closes the sockets
before the requests are handled by the driver, this will lead to
use-after-frees (and potential crashes) in the kernel due to the tfm
having been freed.

The crashes can be easily reproduced (for example) by reducing the max
queue length in cryptod.c and running the following (from
http://www.chronox.de/libkcapi.html) on AES-NI capable hardware:

 $ while true; do kcapi -x 1 -e -c '__ecb-aes-aesni' \
    -k 00000000000000000000000000000000 \
    -p 00000000000000000000000000000000 >/dev/null & done

Signed-off-by: Rabin Vincent <rabin.vincent@axis.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 3 additions and 0 deletions Inline Diff

1 /* 1 /*
2 * af_alg: User-space algorithm interface 2 * af_alg: User-space algorithm interface
3 * 3 *
4 * This file provides the user-space API for algorithms. 4 * This file provides the user-space API for algorithms.
5 * 5 *
6 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> 6 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free 9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option) 10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version. 11 * any later version.
12 * 12 *
13 */ 13 */
14 14
15 #include <linux/atomic.h> 15 #include <linux/atomic.h>
16 #include <crypto/if_alg.h> 16 #include <crypto/if_alg.h>
17 #include <linux/crypto.h> 17 #include <linux/crypto.h>
18 #include <linux/init.h> 18 #include <linux/init.h>
19 #include <linux/kernel.h> 19 #include <linux/kernel.h>
20 #include <linux/list.h> 20 #include <linux/list.h>
21 #include <linux/module.h> 21 #include <linux/module.h>
22 #include <linux/net.h> 22 #include <linux/net.h>
23 #include <linux/rwsem.h> 23 #include <linux/rwsem.h>
24 #include <linux/security.h> 24 #include <linux/security.h>
25 25
26 struct alg_type_list { 26 struct alg_type_list {
27 const struct af_alg_type *type; 27 const struct af_alg_type *type;
28 struct list_head list; 28 struct list_head list;
29 }; 29 };
30 30
31 static atomic_long_t alg_memory_allocated; 31 static atomic_long_t alg_memory_allocated;
32 32
33 static struct proto alg_proto = { 33 static struct proto alg_proto = {
34 .name = "ALG", 34 .name = "ALG",
35 .owner = THIS_MODULE, 35 .owner = THIS_MODULE,
36 .memory_allocated = &alg_memory_allocated, 36 .memory_allocated = &alg_memory_allocated,
37 .obj_size = sizeof(struct alg_sock), 37 .obj_size = sizeof(struct alg_sock),
38 }; 38 };
39 39
40 static LIST_HEAD(alg_types); 40 static LIST_HEAD(alg_types);
41 static DECLARE_RWSEM(alg_types_sem); 41 static DECLARE_RWSEM(alg_types_sem);
42 42
43 static const struct af_alg_type *alg_get_type(const char *name) 43 static const struct af_alg_type *alg_get_type(const char *name)
44 { 44 {
45 const struct af_alg_type *type = ERR_PTR(-ENOENT); 45 const struct af_alg_type *type = ERR_PTR(-ENOENT);
46 struct alg_type_list *node; 46 struct alg_type_list *node;
47 47
48 down_read(&alg_types_sem); 48 down_read(&alg_types_sem);
49 list_for_each_entry(node, &alg_types, list) { 49 list_for_each_entry(node, &alg_types, list) {
50 if (strcmp(node->type->name, name)) 50 if (strcmp(node->type->name, name))
51 continue; 51 continue;
52 52
53 if (try_module_get(node->type->owner)) 53 if (try_module_get(node->type->owner))
54 type = node->type; 54 type = node->type;
55 break; 55 break;
56 } 56 }
57 up_read(&alg_types_sem); 57 up_read(&alg_types_sem);
58 58
59 return type; 59 return type;
60 } 60 }
61 61
62 int af_alg_register_type(const struct af_alg_type *type) 62 int af_alg_register_type(const struct af_alg_type *type)
63 { 63 {
64 struct alg_type_list *node; 64 struct alg_type_list *node;
65 int err = -EEXIST; 65 int err = -EEXIST;
66 66
67 down_write(&alg_types_sem); 67 down_write(&alg_types_sem);
68 list_for_each_entry(node, &alg_types, list) { 68 list_for_each_entry(node, &alg_types, list) {
69 if (!strcmp(node->type->name, type->name)) 69 if (!strcmp(node->type->name, type->name))
70 goto unlock; 70 goto unlock;
71 } 71 }
72 72
73 node = kmalloc(sizeof(*node), GFP_KERNEL); 73 node = kmalloc(sizeof(*node), GFP_KERNEL);
74 err = -ENOMEM; 74 err = -ENOMEM;
75 if (!node) 75 if (!node)
76 goto unlock; 76 goto unlock;
77 77
78 type->ops->owner = THIS_MODULE; 78 type->ops->owner = THIS_MODULE;
79 node->type = type; 79 node->type = type;
80 list_add(&node->list, &alg_types); 80 list_add(&node->list, &alg_types);
81 err = 0; 81 err = 0;
82 82
83 unlock: 83 unlock:
84 up_write(&alg_types_sem); 84 up_write(&alg_types_sem);
85 85
86 return err; 86 return err;
87 } 87 }
88 EXPORT_SYMBOL_GPL(af_alg_register_type); 88 EXPORT_SYMBOL_GPL(af_alg_register_type);
89 89
90 int af_alg_unregister_type(const struct af_alg_type *type) 90 int af_alg_unregister_type(const struct af_alg_type *type)
91 { 91 {
92 struct alg_type_list *node; 92 struct alg_type_list *node;
93 int err = -ENOENT; 93 int err = -ENOENT;
94 94
95 down_write(&alg_types_sem); 95 down_write(&alg_types_sem);
96 list_for_each_entry(node, &alg_types, list) { 96 list_for_each_entry(node, &alg_types, list) {
97 if (strcmp(node->type->name, type->name)) 97 if (strcmp(node->type->name, type->name))
98 continue; 98 continue;
99 99
100 list_del(&node->list); 100 list_del(&node->list);
101 kfree(node); 101 kfree(node);
102 err = 0; 102 err = 0;
103 break; 103 break;
104 } 104 }
105 up_write(&alg_types_sem); 105 up_write(&alg_types_sem);
106 106
107 return err; 107 return err;
108 } 108 }
109 EXPORT_SYMBOL_GPL(af_alg_unregister_type); 109 EXPORT_SYMBOL_GPL(af_alg_unregister_type);
110 110
111 static void alg_do_release(const struct af_alg_type *type, void *private) 111 static void alg_do_release(const struct af_alg_type *type, void *private)
112 { 112 {
113 if (!type) 113 if (!type)
114 return; 114 return;
115 115
116 type->release(private); 116 type->release(private);
117 module_put(type->owner); 117 module_put(type->owner);
118 } 118 }
119 119
120 int af_alg_release(struct socket *sock) 120 int af_alg_release(struct socket *sock)
121 { 121 {
122 if (sock->sk) 122 if (sock->sk)
123 sock_put(sock->sk); 123 sock_put(sock->sk);
124 return 0; 124 return 0;
125 } 125 }
126 EXPORT_SYMBOL_GPL(af_alg_release); 126 EXPORT_SYMBOL_GPL(af_alg_release);
127 127
128 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) 128 static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
129 { 129 {
130 struct sock *sk = sock->sk; 130 struct sock *sk = sock->sk;
131 struct alg_sock *ask = alg_sk(sk); 131 struct alg_sock *ask = alg_sk(sk);
132 struct sockaddr_alg *sa = (void *)uaddr; 132 struct sockaddr_alg *sa = (void *)uaddr;
133 const struct af_alg_type *type; 133 const struct af_alg_type *type;
134 void *private; 134 void *private;
135 135
136 if (sock->state == SS_CONNECTED) 136 if (sock->state == SS_CONNECTED)
137 return -EINVAL; 137 return -EINVAL;
138 138
139 if (addr_len != sizeof(*sa)) 139 if (addr_len != sizeof(*sa))
140 return -EINVAL; 140 return -EINVAL;
141 141
142 sa->salg_type[sizeof(sa->salg_type) - 1] = 0; 142 sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
143 sa->salg_name[sizeof(sa->salg_name) - 1] = 0; 143 sa->salg_name[sizeof(sa->salg_name) - 1] = 0;
144 144
145 type = alg_get_type(sa->salg_type); 145 type = alg_get_type(sa->salg_type);
146 if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) { 146 if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
147 request_module("algif-%s", sa->salg_type); 147 request_module("algif-%s", sa->salg_type);
148 type = alg_get_type(sa->salg_type); 148 type = alg_get_type(sa->salg_type);
149 } 149 }
150 150
151 if (IS_ERR(type)) 151 if (IS_ERR(type))
152 return PTR_ERR(type); 152 return PTR_ERR(type);
153 153
154 private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask); 154 private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
155 if (IS_ERR(private)) { 155 if (IS_ERR(private)) {
156 module_put(type->owner); 156 module_put(type->owner);
157 return PTR_ERR(private); 157 return PTR_ERR(private);
158 } 158 }
159 159
160 lock_sock(sk); 160 lock_sock(sk);
161 161
162 swap(ask->type, type); 162 swap(ask->type, type);
163 swap(ask->private, private); 163 swap(ask->private, private);
164 164
165 release_sock(sk); 165 release_sock(sk);
166 166
167 alg_do_release(type, private); 167 alg_do_release(type, private);
168 168
169 return 0; 169 return 0;
170 } 170 }
171 171
172 static int alg_setkey(struct sock *sk, char __user *ukey, 172 static int alg_setkey(struct sock *sk, char __user *ukey,
173 unsigned int keylen) 173 unsigned int keylen)
174 { 174 {
175 struct alg_sock *ask = alg_sk(sk); 175 struct alg_sock *ask = alg_sk(sk);
176 const struct af_alg_type *type = ask->type; 176 const struct af_alg_type *type = ask->type;
177 u8 *key; 177 u8 *key;
178 int err; 178 int err;
179 179
180 key = sock_kmalloc(sk, keylen, GFP_KERNEL); 180 key = sock_kmalloc(sk, keylen, GFP_KERNEL);
181 if (!key) 181 if (!key)
182 return -ENOMEM; 182 return -ENOMEM;
183 183
184 err = -EFAULT; 184 err = -EFAULT;
185 if (copy_from_user(key, ukey, keylen)) 185 if (copy_from_user(key, ukey, keylen))
186 goto out; 186 goto out;
187 187
188 err = type->setkey(ask->private, key, keylen); 188 err = type->setkey(ask->private, key, keylen);
189 189
190 out: 190 out:
191 sock_kfree_s(sk, key, keylen); 191 sock_kfree_s(sk, key, keylen);
192 192
193 return err; 193 return err;
194 } 194 }
195 195
196 static int alg_setsockopt(struct socket *sock, int level, int optname, 196 static int alg_setsockopt(struct socket *sock, int level, int optname,
197 char __user *optval, unsigned int optlen) 197 char __user *optval, unsigned int optlen)
198 { 198 {
199 struct sock *sk = sock->sk; 199 struct sock *sk = sock->sk;
200 struct alg_sock *ask = alg_sk(sk); 200 struct alg_sock *ask = alg_sk(sk);
201 const struct af_alg_type *type; 201 const struct af_alg_type *type;
202 int err = -ENOPROTOOPT; 202 int err = -ENOPROTOOPT;
203 203
204 lock_sock(sk); 204 lock_sock(sk);
205 type = ask->type; 205 type = ask->type;
206 206
207 if (level != SOL_ALG || !type) 207 if (level != SOL_ALG || !type)
208 goto unlock; 208 goto unlock;
209 209
210 switch (optname) { 210 switch (optname) {
211 case ALG_SET_KEY: 211 case ALG_SET_KEY:
212 if (sock->state == SS_CONNECTED) 212 if (sock->state == SS_CONNECTED)
213 goto unlock; 213 goto unlock;
214 if (!type->setkey) 214 if (!type->setkey)
215 goto unlock; 215 goto unlock;
216 216
217 err = alg_setkey(sk, optval, optlen); 217 err = alg_setkey(sk, optval, optlen);
218 } 218 }
219 219
220 unlock: 220 unlock:
221 release_sock(sk); 221 release_sock(sk);
222 222
223 return err; 223 return err;
224 } 224 }
225 225
226 int af_alg_accept(struct sock *sk, struct socket *newsock) 226 int af_alg_accept(struct sock *sk, struct socket *newsock)
227 { 227 {
228 struct alg_sock *ask = alg_sk(sk); 228 struct alg_sock *ask = alg_sk(sk);
229 const struct af_alg_type *type; 229 const struct af_alg_type *type;
230 struct sock *sk2; 230 struct sock *sk2;
231 int err; 231 int err;
232 232
233 lock_sock(sk); 233 lock_sock(sk);
234 type = ask->type; 234 type = ask->type;
235 235
236 err = -EINVAL; 236 err = -EINVAL;
237 if (!type) 237 if (!type)
238 goto unlock; 238 goto unlock;
239 239
240 sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto); 240 sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto);
241 err = -ENOMEM; 241 err = -ENOMEM;
242 if (!sk2) 242 if (!sk2)
243 goto unlock; 243 goto unlock;
244 244
245 sock_init_data(newsock, sk2); 245 sock_init_data(newsock, sk2);
246 sock_graft(sk2, newsock); 246 sock_graft(sk2, newsock);
247 security_sk_clone(sk, sk2); 247 security_sk_clone(sk, sk2);
248 248
249 err = type->accept(ask->private, sk2); 249 err = type->accept(ask->private, sk2);
250 if (err) { 250 if (err) {
251 sk_free(sk2); 251 sk_free(sk2);
252 goto unlock; 252 goto unlock;
253 } 253 }
254 254
255 sk2->sk_family = PF_ALG; 255 sk2->sk_family = PF_ALG;
256 256
257 sock_hold(sk); 257 sock_hold(sk);
258 alg_sk(sk2)->parent = sk; 258 alg_sk(sk2)->parent = sk;
259 alg_sk(sk2)->type = type; 259 alg_sk(sk2)->type = type;
260 260
261 newsock->ops = type->ops; 261 newsock->ops = type->ops;
262 newsock->state = SS_CONNECTED; 262 newsock->state = SS_CONNECTED;
263 263
264 err = 0; 264 err = 0;
265 265
266 unlock: 266 unlock:
267 release_sock(sk); 267 release_sock(sk);
268 268
269 return err; 269 return err;
270 } 270 }
271 EXPORT_SYMBOL_GPL(af_alg_accept); 271 EXPORT_SYMBOL_GPL(af_alg_accept);
272 272
273 static int alg_accept(struct socket *sock, struct socket *newsock, int flags) 273 static int alg_accept(struct socket *sock, struct socket *newsock, int flags)
274 { 274 {
275 return af_alg_accept(sock->sk, newsock); 275 return af_alg_accept(sock->sk, newsock);
276 } 276 }
277 277
278 static const struct proto_ops alg_proto_ops = { 278 static const struct proto_ops alg_proto_ops = {
279 .family = PF_ALG, 279 .family = PF_ALG,
280 .owner = THIS_MODULE, 280 .owner = THIS_MODULE,
281 281
282 .connect = sock_no_connect, 282 .connect = sock_no_connect,
283 .socketpair = sock_no_socketpair, 283 .socketpair = sock_no_socketpair,
284 .getname = sock_no_getname, 284 .getname = sock_no_getname,
285 .ioctl = sock_no_ioctl, 285 .ioctl = sock_no_ioctl,
286 .listen = sock_no_listen, 286 .listen = sock_no_listen,
287 .shutdown = sock_no_shutdown, 287 .shutdown = sock_no_shutdown,
288 .getsockopt = sock_no_getsockopt, 288 .getsockopt = sock_no_getsockopt,
289 .mmap = sock_no_mmap, 289 .mmap = sock_no_mmap,
290 .sendpage = sock_no_sendpage, 290 .sendpage = sock_no_sendpage,
291 .sendmsg = sock_no_sendmsg, 291 .sendmsg = sock_no_sendmsg,
292 .recvmsg = sock_no_recvmsg, 292 .recvmsg = sock_no_recvmsg,
293 .poll = sock_no_poll, 293 .poll = sock_no_poll,
294 294
295 .bind = alg_bind, 295 .bind = alg_bind,
296 .release = af_alg_release, 296 .release = af_alg_release,
297 .setsockopt = alg_setsockopt, 297 .setsockopt = alg_setsockopt,
298 .accept = alg_accept, 298 .accept = alg_accept,
299 }; 299 };
300 300
301 static void alg_sock_destruct(struct sock *sk) 301 static void alg_sock_destruct(struct sock *sk)
302 { 302 {
303 struct alg_sock *ask = alg_sk(sk); 303 struct alg_sock *ask = alg_sk(sk);
304 304
305 alg_do_release(ask->type, ask->private); 305 alg_do_release(ask->type, ask->private);
306 } 306 }
307 307
308 static int alg_create(struct net *net, struct socket *sock, int protocol, 308 static int alg_create(struct net *net, struct socket *sock, int protocol,
309 int kern) 309 int kern)
310 { 310 {
311 struct sock *sk; 311 struct sock *sk;
312 int err; 312 int err;
313 313
314 if (sock->type != SOCK_SEQPACKET) 314 if (sock->type != SOCK_SEQPACKET)
315 return -ESOCKTNOSUPPORT; 315 return -ESOCKTNOSUPPORT;
316 if (protocol != 0) 316 if (protocol != 0)
317 return -EPROTONOSUPPORT; 317 return -EPROTONOSUPPORT;
318 318
319 err = -ENOMEM; 319 err = -ENOMEM;
320 sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto); 320 sk = sk_alloc(net, PF_ALG, GFP_KERNEL, &alg_proto);
321 if (!sk) 321 if (!sk)
322 goto out; 322 goto out;
323 323
324 sock->ops = &alg_proto_ops; 324 sock->ops = &alg_proto_ops;
325 sock_init_data(sock, sk); 325 sock_init_data(sock, sk);
326 326
327 sk->sk_family = PF_ALG; 327 sk->sk_family = PF_ALG;
328 sk->sk_destruct = alg_sock_destruct; 328 sk->sk_destruct = alg_sock_destruct;
329 329
330 return 0; 330 return 0;
331 out: 331 out:
332 return err; 332 return err;
333 } 333 }
334 334
335 static const struct net_proto_family alg_family = { 335 static const struct net_proto_family alg_family = {
336 .family = PF_ALG, 336 .family = PF_ALG,
337 .create = alg_create, 337 .create = alg_create,
338 .owner = THIS_MODULE, 338 .owner = THIS_MODULE,
339 }; 339 };
340 340
341 int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len, 341 int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
342 int write) 342 int write)
343 { 343 {
344 unsigned long from = (unsigned long)addr; 344 unsigned long from = (unsigned long)addr;
345 unsigned long npages; 345 unsigned long npages;
346 unsigned off; 346 unsigned off;
347 int err; 347 int err;
348 int i; 348 int i;
349 349
350 err = -EFAULT; 350 err = -EFAULT;
351 if (!access_ok(write ? VERIFY_READ : VERIFY_WRITE, addr, len)) 351 if (!access_ok(write ? VERIFY_READ : VERIFY_WRITE, addr, len))
352 goto out; 352 goto out;
353 353
354 off = from & ~PAGE_MASK; 354 off = from & ~PAGE_MASK;
355 npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT; 355 npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
356 if (npages > ALG_MAX_PAGES) 356 if (npages > ALG_MAX_PAGES)
357 npages = ALG_MAX_PAGES; 357 npages = ALG_MAX_PAGES;
358 358
359 err = get_user_pages_fast(from, npages, write, sgl->pages); 359 err = get_user_pages_fast(from, npages, write, sgl->pages);
360 if (err < 0) 360 if (err < 0)
361 goto out; 361 goto out;
362 362
363 npages = err; 363 npages = err;
364 err = -EINVAL; 364 err = -EINVAL;
365 if (WARN_ON(npages == 0)) 365 if (WARN_ON(npages == 0))
366 goto out; 366 goto out;
367 367
368 err = 0; 368 err = 0;
369 369
370 sg_init_table(sgl->sg, npages); 370 sg_init_table(sgl->sg, npages);
371 371
372 for (i = 0; i < npages; i++) { 372 for (i = 0; i < npages; i++) {
373 int plen = min_t(int, len, PAGE_SIZE - off); 373 int plen = min_t(int, len, PAGE_SIZE - off);
374 374
375 sg_set_page(sgl->sg + i, sgl->pages[i], plen, off); 375 sg_set_page(sgl->sg + i, sgl->pages[i], plen, off);
376 376
377 off = 0; 377 off = 0;
378 len -= plen; 378 len -= plen;
379 err += plen; 379 err += plen;
380 } 380 }
381 381
382 out: 382 out:
383 return err; 383 return err;
384 } 384 }
385 EXPORT_SYMBOL_GPL(af_alg_make_sg); 385 EXPORT_SYMBOL_GPL(af_alg_make_sg);
386 386
387 void af_alg_free_sg(struct af_alg_sgl *sgl) 387 void af_alg_free_sg(struct af_alg_sgl *sgl)
388 { 388 {
389 int i; 389 int i;
390 390
391 i = 0; 391 i = 0;
392 do { 392 do {
393 put_page(sgl->pages[i]); 393 put_page(sgl->pages[i]);
394 } while (!sg_is_last(sgl->sg + (i++))); 394 } while (!sg_is_last(sgl->sg + (i++)));
395 } 395 }
396 EXPORT_SYMBOL_GPL(af_alg_free_sg); 396 EXPORT_SYMBOL_GPL(af_alg_free_sg);
397 397
398 int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) 398 int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
399 { 399 {
400 struct cmsghdr *cmsg; 400 struct cmsghdr *cmsg;
401 401
402 for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { 402 for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
403 if (!CMSG_OK(msg, cmsg)) 403 if (!CMSG_OK(msg, cmsg))
404 return -EINVAL; 404 return -EINVAL;
405 if (cmsg->cmsg_level != SOL_ALG) 405 if (cmsg->cmsg_level != SOL_ALG)
406 continue; 406 continue;
407 407
408 switch(cmsg->cmsg_type) { 408 switch(cmsg->cmsg_type) {
409 case ALG_SET_IV: 409 case ALG_SET_IV:
410 if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv))) 410 if (cmsg->cmsg_len < CMSG_LEN(sizeof(*con->iv)))
411 return -EINVAL; 411 return -EINVAL;
412 con->iv = (void *)CMSG_DATA(cmsg); 412 con->iv = (void *)CMSG_DATA(cmsg);
413 if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen + 413 if (cmsg->cmsg_len < CMSG_LEN(con->iv->ivlen +
414 sizeof(*con->iv))) 414 sizeof(*con->iv)))
415 return -EINVAL; 415 return -EINVAL;
416 break; 416 break;
417 417
418 case ALG_SET_OP: 418 case ALG_SET_OP:
419 if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32))) 419 if (cmsg->cmsg_len < CMSG_LEN(sizeof(u32)))
420 return -EINVAL; 420 return -EINVAL;
421 con->op = *(u32 *)CMSG_DATA(cmsg); 421 con->op = *(u32 *)CMSG_DATA(cmsg);
422 break; 422 break;
423 423
424 default: 424 default:
425 return -EINVAL; 425 return -EINVAL;
426 } 426 }
427 } 427 }
428 428
429 return 0; 429 return 0;
430 } 430 }
431 EXPORT_SYMBOL_GPL(af_alg_cmsg_send); 431 EXPORT_SYMBOL_GPL(af_alg_cmsg_send);
432 432
433 int af_alg_wait_for_completion(int err, struct af_alg_completion *completion) 433 int af_alg_wait_for_completion(int err, struct af_alg_completion *completion)
434 { 434 {
435 switch (err) { 435 switch (err) {
436 case -EINPROGRESS: 436 case -EINPROGRESS:
437 case -EBUSY: 437 case -EBUSY:
438 wait_for_completion(&completion->completion); 438 wait_for_completion(&completion->completion);
439 reinit_completion(&completion->completion); 439 reinit_completion(&completion->completion);
440 err = completion->err; 440 err = completion->err;
441 break; 441 break;
442 }; 442 };
443 443
444 return err; 444 return err;
445 } 445 }
446 EXPORT_SYMBOL_GPL(af_alg_wait_for_completion); 446 EXPORT_SYMBOL_GPL(af_alg_wait_for_completion);
447 447
448 void af_alg_complete(struct crypto_async_request *req, int err) 448 void af_alg_complete(struct crypto_async_request *req, int err)
449 { 449 {
450 struct af_alg_completion *completion = req->data; 450 struct af_alg_completion *completion = req->data;
451 451
452 if (err == -EINPROGRESS)
453 return;
454
452 completion->err = err; 455 completion->err = err;
453 complete(&completion->completion); 456 complete(&completion->completion);
454 } 457 }
455 EXPORT_SYMBOL_GPL(af_alg_complete); 458 EXPORT_SYMBOL_GPL(af_alg_complete);
456 459
457 static int __init af_alg_init(void) 460 static int __init af_alg_init(void)
458 { 461 {
459 int err = proto_register(&alg_proto, 0); 462 int err = proto_register(&alg_proto, 0);
460 463
461 if (err) 464 if (err)
462 goto out; 465 goto out;
463 466
464 err = sock_register(&alg_family); 467 err = sock_register(&alg_family);
465 if (err != 0) 468 if (err != 0)
466 goto out_unregister_proto; 469 goto out_unregister_proto;
467 470
468 out: 471 out:
469 return err; 472 return err;
470 473
471 out_unregister_proto: 474 out_unregister_proto:
472 proto_unregister(&alg_proto); 475 proto_unregister(&alg_proto);
473 goto out; 476 goto out;
474 } 477 }
475 478
476 static void __exit af_alg_exit(void) 479 static void __exit af_alg_exit(void)
477 { 480 {
478 sock_unregister(PF_ALG); 481 sock_unregister(PF_ALG);
479 proto_unregister(&alg_proto); 482 proto_unregister(&alg_proto);
480 } 483 }
481 484
482 module_init(af_alg_init); 485 module_init(af_alg_init);
483 module_exit(af_alg_exit); 486 module_exit(af_alg_exit);
484 MODULE_LICENSE("GPL"); 487 MODULE_LICENSE("GPL");
485 MODULE_ALIAS_NETPROTO(AF_ALG); 488 MODULE_ALIAS_NETPROTO(AF_ALG);
486 489