l2tp: fix race in pppol2tp_release with session object destroy
[pandora-kernel.git] / crypto / algif_hash.c
1 /*
2  * algif_hash: User-space interface for hash algorithms
3  *
4  * This file provides the user-space API for hash algorithms.
5  *
6  * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
7  *
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
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  */
14
15 #include <crypto/hash.h>
16 #include <crypto/if_alg.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/module.h>
21 #include <linux/net.h>
22 #include <net/sock.h>
23
24 struct hash_ctx {
25         struct af_alg_sgl sgl;
26
27         u8 *result;
28
29         struct af_alg_completion completion;
30
31         unsigned int len;
32         bool more;
33
34         struct ahash_request req;
35 };
36
37 static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
38                         struct msghdr *msg, size_t ignored)
39 {
40         int limit = ALG_MAX_PAGES * PAGE_SIZE;
41         struct sock *sk = sock->sk;
42         struct alg_sock *ask = alg_sk(sk);
43         struct hash_ctx *ctx = ask->private;
44         unsigned long iovlen;
45         struct iovec *iov;
46         long copied = 0;
47         int err;
48
49         if (limit > sk->sk_sndbuf)
50                 limit = sk->sk_sndbuf;
51
52         lock_sock(sk);
53         if (!ctx->more) {
54                 err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
55                                                 &ctx->completion);
56                 if (err)
57                         goto unlock;
58         }
59
60         ctx->more = 0;
61
62         for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
63              iovlen--, iov++) {
64                 unsigned long seglen = iov->iov_len;
65                 char __user *from = iov->iov_base;
66
67                 while (seglen) {
68                         int len = min_t(unsigned long, seglen, limit);
69                         int newlen;
70
71                         newlen = af_alg_make_sg(&ctx->sgl, from, len, 0);
72                         if (newlen < 0) {
73                                 err = copied ? 0 : newlen;
74                                 goto unlock;
75                         }
76
77                         ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
78                                                 newlen);
79
80                         err = af_alg_wait_for_completion(
81                                 crypto_ahash_update(&ctx->req),
82                                 &ctx->completion);
83
84                         af_alg_free_sg(&ctx->sgl);
85
86                         if (err)
87                                 goto unlock;
88
89                         seglen -= newlen;
90                         from += newlen;
91                         copied += newlen;
92                 }
93         }
94
95         err = 0;
96
97         ctx->more = msg->msg_flags & MSG_MORE;
98         if (!ctx->more) {
99                 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
100                 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
101                                                  &ctx->completion);
102         }
103
104 unlock:
105         release_sock(sk);
106
107         return err ?: copied;
108 }
109
110 static ssize_t hash_sendpage(struct socket *sock, struct page *page,
111                              int offset, size_t size, int flags)
112 {
113         struct sock *sk = sock->sk;
114         struct alg_sock *ask = alg_sk(sk);
115         struct hash_ctx *ctx = ask->private;
116         int err;
117
118         if (flags & MSG_SENDPAGE_NOTLAST)
119                 flags |= MSG_MORE;
120
121         lock_sock(sk);
122         sg_init_table(ctx->sgl.sg, 1);
123         sg_set_page(ctx->sgl.sg, page, size, offset);
124
125         ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
126
127         if (!(flags & MSG_MORE)) {
128                 if (ctx->more)
129                         err = crypto_ahash_finup(&ctx->req);
130                 else
131                         err = crypto_ahash_digest(&ctx->req);
132         } else {
133                 if (!ctx->more) {
134                         err = crypto_ahash_init(&ctx->req);
135                         err = af_alg_wait_for_completion(err, &ctx->completion);
136                         if (err)
137                                 goto unlock;
138                 }
139
140                 err = crypto_ahash_update(&ctx->req);
141         }
142
143         err = af_alg_wait_for_completion(err, &ctx->completion);
144         if (err)
145                 goto unlock;
146
147         ctx->more = flags & MSG_MORE;
148
149 unlock:
150         release_sock(sk);
151
152         return err ?: size;
153 }
154
155 static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
156                         struct msghdr *msg, size_t len, int flags)
157 {
158         struct sock *sk = sock->sk;
159         struct alg_sock *ask = alg_sk(sk);
160         struct hash_ctx *ctx = ask->private;
161         unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
162         int err;
163
164         if (len > ds)
165                 len = ds;
166         else if (len < ds)
167                 msg->msg_flags |= MSG_TRUNC;
168
169         lock_sock(sk);
170         if (ctx->more) {
171                 ctx->more = 0;
172                 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
173                 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
174                                                  &ctx->completion);
175                 if (err)
176                         goto unlock;
177         }
178
179         err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
180
181 unlock:
182         release_sock(sk);
183
184         return err ?: len;
185 }
186
187 static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
188 {
189         struct sock *sk = sock->sk;
190         struct alg_sock *ask = alg_sk(sk);
191         struct hash_ctx *ctx = ask->private;
192         struct ahash_request *req = &ctx->req;
193         char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))];
194         struct sock *sk2;
195         struct alg_sock *ask2;
196         struct hash_ctx *ctx2;
197         bool more;
198         int err;
199
200         lock_sock(sk);
201         more = ctx->more;
202         err = more ? crypto_ahash_export(req, state) : 0;
203         release_sock(sk);
204
205         if (err)
206                 return err;
207
208         err = af_alg_accept(ask->parent, newsock);
209         if (err)
210                 return err;
211
212         sk2 = newsock->sk;
213         ask2 = alg_sk(sk2);
214         ctx2 = ask2->private;
215         ctx2->more = more;
216
217         if (!more)
218                 return err;
219
220         err = crypto_ahash_import(&ctx2->req, state);
221         if (err) {
222                 sock_orphan(sk2);
223                 sock_put(sk2);
224         }
225
226         return err;
227 }
228
229 static struct proto_ops algif_hash_ops = {
230         .family         =       PF_ALG,
231
232         .connect        =       sock_no_connect,
233         .socketpair     =       sock_no_socketpair,
234         .getname        =       sock_no_getname,
235         .ioctl          =       sock_no_ioctl,
236         .listen         =       sock_no_listen,
237         .shutdown       =       sock_no_shutdown,
238         .getsockopt     =       sock_no_getsockopt,
239         .mmap           =       sock_no_mmap,
240         .bind           =       sock_no_bind,
241         .setsockopt     =       sock_no_setsockopt,
242         .poll           =       sock_no_poll,
243
244         .release        =       af_alg_release,
245         .sendmsg        =       hash_sendmsg,
246         .sendpage       =       hash_sendpage,
247         .recvmsg        =       hash_recvmsg,
248         .accept         =       hash_accept,
249 };
250
251 static int hash_check_key(struct socket *sock)
252 {
253         int err = 0;
254         struct sock *psk;
255         struct alg_sock *pask;
256         struct crypto_ahash *tfm;
257         struct sock *sk = sock->sk;
258         struct alg_sock *ask = alg_sk(sk);
259
260         lock_sock(sk);
261         if (ask->refcnt)
262                 goto unlock_child;
263
264         psk = ask->parent;
265         pask = alg_sk(ask->parent);
266         tfm = pask->private;
267
268         err = -ENOKEY;
269         lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
270         if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
271                 goto unlock;
272
273         if (!pask->refcnt++)
274                 sock_hold(psk);
275
276         ask->refcnt = 1;
277         sock_put(psk);
278
279         err = 0;
280
281 unlock:
282         release_sock(psk);
283 unlock_child:
284         release_sock(sk);
285
286         return err;
287 }
288
289 static int hash_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
290                               struct msghdr *msg, size_t size)
291 {
292         int err;
293
294         err = hash_check_key(sock);
295         if (err)
296                 return err;
297
298         return hash_sendmsg(unused, sock, msg, size);
299 }
300
301 static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
302                                    int offset, size_t size, int flags)
303 {
304         int err;
305
306         err = hash_check_key(sock);
307         if (err)
308                 return err;
309
310         return hash_sendpage(sock, page, offset, size, flags);
311 }
312
313 static int hash_recvmsg_nokey(struct kiocb *unused, struct socket *sock,
314                               struct msghdr *msg, size_t ignored, int flags)
315 {
316         int err;
317
318         err = hash_check_key(sock);
319         if (err)
320                 return err;
321
322         return hash_recvmsg(unused, sock, msg, ignored, flags);
323 }
324
325 static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
326                              int flags)
327 {
328         int err;
329
330         err = hash_check_key(sock);
331         if (err)
332                 return err;
333
334         return hash_accept(sock, newsock, flags);
335 }
336
337 static struct proto_ops algif_hash_ops_nokey = {
338         .family         =       PF_ALG,
339
340         .connect        =       sock_no_connect,
341         .socketpair     =       sock_no_socketpair,
342         .getname        =       sock_no_getname,
343         .ioctl          =       sock_no_ioctl,
344         .listen         =       sock_no_listen,
345         .shutdown       =       sock_no_shutdown,
346         .getsockopt     =       sock_no_getsockopt,
347         .mmap           =       sock_no_mmap,
348         .bind           =       sock_no_bind,
349         .setsockopt     =       sock_no_setsockopt,
350         .poll           =       sock_no_poll,
351
352         .release        =       af_alg_release,
353         .sendmsg        =       hash_sendmsg_nokey,
354         .sendpage       =       hash_sendpage_nokey,
355         .recvmsg        =       hash_recvmsg_nokey,
356         .accept         =       hash_accept_nokey,
357 };
358
359 static void *hash_bind(const char *name, u32 type, u32 mask)
360 {
361         return crypto_alloc_ahash(name, type, mask);
362 }
363
364 static void hash_release(void *private)
365 {
366         crypto_free_ahash(private);
367 }
368
369 static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
370 {
371         return crypto_ahash_setkey(private, key, keylen);
372 }
373
374 static void hash_sock_destruct(struct sock *sk)
375 {
376         struct alg_sock *ask = alg_sk(sk);
377         struct hash_ctx *ctx = ask->private;
378
379         sock_kfree_s(sk, ctx->result,
380                      crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
381         sock_kfree_s(sk, ctx, ctx->len);
382         af_alg_release_parent(sk);
383 }
384
385 static int hash_accept_parent_nokey(void *private, struct sock *sk)
386 {
387         struct crypto_ahash *tfm = private;
388         struct alg_sock *ask = alg_sk(sk);
389         struct hash_ctx *ctx;
390         unsigned int len = sizeof(*ctx) + crypto_ahash_reqsize(tfm);
391         unsigned ds = crypto_ahash_digestsize(tfm);
392
393         ctx = sock_kmalloc(sk, len, GFP_KERNEL);
394         if (!ctx)
395                 return -ENOMEM;
396
397         ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
398         if (!ctx->result) {
399                 sock_kfree_s(sk, ctx, len);
400                 return -ENOMEM;
401         }
402
403         memset(ctx->result, 0, ds);
404
405         ctx->len = len;
406         ctx->more = 0;
407         af_alg_init_completion(&ctx->completion);
408
409         ask->private = ctx;
410
411         ahash_request_set_tfm(&ctx->req, tfm);
412         ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
413                                    af_alg_complete, &ctx->completion);
414
415         sk->sk_destruct = hash_sock_destruct;
416
417         return 0;
418 }
419
420 static int hash_accept_parent(void *private, struct sock *sk)
421 {
422         struct crypto_ahash *tfm = private;
423
424         if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
425                 return -ENOKEY;
426
427         return hash_accept_parent_nokey(private, sk);
428 }
429
430 static const struct af_alg_type algif_type_hash = {
431         .bind           =       hash_bind,
432         .release        =       hash_release,
433         .setkey         =       hash_setkey,
434         .accept         =       hash_accept_parent,
435         .accept_nokey   =       hash_accept_parent_nokey,
436         .ops            =       &algif_hash_ops,
437         .ops_nokey      =       &algif_hash_ops_nokey,
438         .name           =       "hash",
439         .owner          =       THIS_MODULE
440 };
441
442 static int __init algif_hash_init(void)
443 {
444         return af_alg_register_type(&algif_type_hash);
445 }
446
447 static void __exit algif_hash_exit(void)
448 {
449         int err = af_alg_unregister_type(&algif_type_hash);
450         BUG_ON(err);
451 }
452
453 module_init(algif_hash_init);
454 module_exit(algif_hash_exit);
455 MODULE_LICENSE("GPL");