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