~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/crypto/af_alg.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /crypto/af_alg.c (Version linux-6.12-rc7) and /crypto/af_alg.c (Version ccs-tools-1.8.12)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  * af_alg: User-space algorithm interface         
  4  *                                                
  5  * This file provides the user-space API for a    
  6  *                                                
  7  * Copyright (c) 2010 Herbert Xu <herbert@gond    
  8  */                                               
  9                                                   
 10 #include <linux/atomic.h>                         
 11 #include <crypto/if_alg.h>                        
 12 #include <linux/crypto.h>                         
 13 #include <linux/init.h>                           
 14 #include <linux/kernel.h>                         
 15 #include <linux/key.h>                            
 16 #include <linux/key-type.h>                       
 17 #include <linux/list.h>                           
 18 #include <linux/module.h>                         
 19 #include <linux/net.h>                            
 20 #include <linux/rwsem.h>                          
 21 #include <linux/sched.h>                          
 22 #include <linux/sched/signal.h>                   
 23 #include <linux/security.h>                       
 24 #include <linux/string.h>                         
 25 #include <keys/user-type.h>                       
 26 #include <keys/trusted-type.h>                    
 27 #include <keys/encrypted-type.h>                  
 28                                                   
 29 struct alg_type_list {                            
 30         const struct af_alg_type *type;           
 31         struct list_head list;                    
 32 };                                                
 33                                                   
 34 static struct proto alg_proto = {                 
 35         .name                   = "ALG",          
 36         .owner                  = THIS_MODULE,    
 37         .obj_size               = sizeof(struc    
 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(    
 44 {                                                 
 45         const struct af_alg_type *type = ERR_P    
 46         struct alg_type_list *node;               
 47                                                   
 48         down_read(&alg_types_sem);                
 49         list_for_each_entry(node, &alg_types,     
 50                 if (strcmp(node->type->name, n    
 51                         continue;                 
 52                                                   
 53                 if (try_module_get(node->type-    
 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_t    
 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,     
 69                 if (!strcmp(node->type->name,     
 70                         goto unlock;              
 71         }                                         
 72                                                   
 73         node = kmalloc(sizeof(*node), GFP_KERN    
 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_    
 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    
 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,     
 99                 if (strcmp(node->type->name, t    
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    
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                 sock->sk = NULL;                  
127         }                                         
128         return 0;                                 
129 }                                                 
130 EXPORT_SYMBOL_GPL(af_alg_release);                
131                                                   
132 void af_alg_release_parent(struct sock *sk)       
133 {                                                 
134         struct alg_sock *ask = alg_sk(sk);        
135         unsigned int nokey = atomic_read(&ask-    
136                                                   
137         sk = ask->parent;                         
138         ask = alg_sk(sk);                         
139                                                   
140         if (nokey)                                
141                 atomic_dec(&ask->nokey_refcnt)    
142                                                   
143         if (atomic_dec_and_test(&ask->refcnt))    
144                 sock_put(sk);                     
145 }                                                 
146 EXPORT_SYMBOL_GPL(af_alg_release_parent);         
147                                                   
148 static int alg_bind(struct socket *sock, struc    
149 {                                                 
150         const u32 allowed = CRYPTO_ALG_KERN_DR    
151         struct sock *sk = sock->sk;               
152         struct alg_sock *ask = alg_sk(sk);        
153         struct sockaddr_alg_new *sa = (void *)    
154         const struct af_alg_type *type;           
155         void *private;                            
156         int err;                                  
157                                                   
158         if (sock->state == SS_CONNECTED)          
159                 return -EINVAL;                   
160                                                   
161         BUILD_BUG_ON(offsetof(struct sockaddr_    
162                      offsetof(struct sockaddr_    
163         BUILD_BUG_ON(offsetof(struct sockaddr_    
164                                                   
165         if (addr_len < sizeof(*sa) + 1)           
166                 return -EINVAL;                   
167                                                   
168         /* If caller uses non-allowed flag, re    
169         if ((sa->salg_feat & ~allowed) || (sa-    
170                 return -EINVAL;                   
171                                                   
172         sa->salg_type[sizeof(sa->salg_type) -     
173         sa->salg_name[addr_len - sizeof(*sa) -    
174                                                   
175         type = alg_get_type(sa->salg_type);       
176         if (PTR_ERR(type) == -ENOENT) {           
177                 request_module("algif-%s", sa-    
178                 type = alg_get_type(sa->salg_t    
179         }                                         
180                                                   
181         if (IS_ERR(type))                         
182                 return PTR_ERR(type);             
183                                                   
184         private = type->bind(sa->salg_name, sa    
185         if (IS_ERR(private)) {                    
186                 module_put(type->owner);          
187                 return PTR_ERR(private);          
188         }                                         
189                                                   
190         err = -EBUSY;                             
191         lock_sock(sk);                            
192         if (atomic_read(&ask->refcnt))            
193                 goto unlock;                      
194                                                   
195         swap(ask->type, type);                    
196         swap(ask->private, private);              
197                                                   
198         err = 0;                                  
199                                                   
200 unlock:                                           
201         release_sock(sk);                         
202                                                   
203         alg_do_release(type, private);            
204                                                   
205         return err;                               
206 }                                                 
207                                                   
208 static int alg_setkey(struct sock *sk, sockptr    
209 {                                                 
210         struct alg_sock *ask = alg_sk(sk);        
211         const struct af_alg_type *type = ask->    
212         u8 *key;                                  
213         int err;                                  
214                                                   
215         key = sock_kmalloc(sk, keylen, GFP_KER    
216         if (!key)                                 
217                 return -ENOMEM;                   
218                                                   
219         err = -EFAULT;                            
220         if (copy_from_sockptr(key, ukey, keyle    
221                 goto out;                         
222                                                   
223         err = type->setkey(ask->private, key,     
224                                                   
225 out:                                              
226         sock_kzfree_s(sk, key, keylen);           
227                                                   
228         return err;                               
229 }                                                 
230                                                   
231 #ifdef CONFIG_KEYS                                
232                                                   
233 static const u8 *key_data_ptr_user(const struc    
234                                    unsigned in    
235 {                                                 
236         const struct user_key_payload *ukp;       
237                                                   
238         ukp = user_key_payload_locked(key);       
239         if (IS_ERR_OR_NULL(ukp))                  
240                 return ERR_PTR(-EKEYREVOKED);     
241                                                   
242         *datalen = key->datalen;                  
243                                                   
244         return ukp->data;                         
245 }                                                 
246                                                   
247 static const u8 *key_data_ptr_encrypted(const     
248                                         unsign    
249 {                                                 
250         const struct encrypted_key_payload *ek    
251                                                   
252         ekp = dereference_key_locked(key);        
253         if (IS_ERR_OR_NULL(ekp))                  
254                 return ERR_PTR(-EKEYREVOKED);     
255                                                   
256         *datalen = ekp->decrypted_datalen;        
257                                                   
258         return ekp->decrypted_data;               
259 }                                                 
260                                                   
261 static const u8 *key_data_ptr_trusted(const st    
262                                       unsigned    
263 {                                                 
264         const struct trusted_key_payload *tkp;    
265                                                   
266         tkp = dereference_key_locked(key);        
267         if (IS_ERR_OR_NULL(tkp))                  
268                 return ERR_PTR(-EKEYREVOKED);     
269                                                   
270         *datalen = tkp->key_len;                  
271                                                   
272         return tkp->key;                          
273 }                                                 
274                                                   
275 static struct key *lookup_key(key_serial_t ser    
276 {                                                 
277         key_ref_t key_ref;                        
278                                                   
279         key_ref = lookup_user_key(serial, 0, K    
280         if (IS_ERR(key_ref))                      
281                 return ERR_CAST(key_ref);         
282                                                   
283         return key_ref_to_ptr(key_ref);           
284 }                                                 
285                                                   
286 static int alg_setkey_by_key_serial(struct alg    
287                                     unsigned i    
288 {                                                 
289         const struct af_alg_type *type = ask->    
290         u8 *key_data = NULL;                      
291         unsigned int key_datalen;                 
292         key_serial_t serial;                      
293         struct key *key;                          
294         const u8 *ret;                            
295         int err;                                  
296                                                   
297         if (optlen != sizeof(serial))             
298                 return -EINVAL;                   
299                                                   
300         if (copy_from_sockptr(&serial, optval,    
301                 return -EFAULT;                   
302                                                   
303         key = lookup_key(serial);                 
304         if (IS_ERR(key))                          
305                 return PTR_ERR(key);              
306                                                   
307         down_read(&key->sem);                     
308                                                   
309         ret = ERR_PTR(-ENOPROTOOPT);              
310         if (!strcmp(key->type->name, "user") |    
311             !strcmp(key->type->name, "logon"))    
312                 ret = key_data_ptr_user(key, &    
313         } else if (IS_REACHABLE(CONFIG_ENCRYPT    
314                            !strcmp(key->type->    
315                 ret = key_data_ptr_encrypted(k    
316         } else if (IS_REACHABLE(CONFIG_TRUSTED    
317                            !strcmp(key->type->    
318                 ret = key_data_ptr_trusted(key    
319         }                                         
320                                                   
321         if (IS_ERR(ret)) {                        
322                 up_read(&key->sem);               
323                 key_put(key);                     
324                 return PTR_ERR(ret);              
325         }                                         
326                                                   
327         key_data = sock_kmalloc(&ask->sk, key_    
328         if (!key_data) {                          
329                 up_read(&key->sem);               
330                 key_put(key);                     
331                 return -ENOMEM;                   
332         }                                         
333                                                   
334         memcpy(key_data, ret, key_datalen);       
335                                                   
336         up_read(&key->sem);                       
337         key_put(key);                             
338                                                   
339         err = type->setkey(ask->private, key_d    
340                                                   
341         sock_kzfree_s(&ask->sk, key_data, key_    
342                                                   
343         return err;                               
344 }                                                 
345                                                   
346 #else                                             
347                                                   
348 static inline int alg_setkey_by_key_serial(str    
349                                            soc    
350                                            uns    
351 {                                                 
352         return -ENOPROTOOPT;                      
353 }                                                 
354                                                   
355 #endif                                            
356                                                   
357 static int alg_setsockopt(struct socket *sock,    
358                           sockptr_t optval, un    
359 {                                                 
360         struct sock *sk = sock->sk;               
361         struct alg_sock *ask = alg_sk(sk);        
362         const struct af_alg_type *type;           
363         int err = -EBUSY;                         
364                                                   
365         lock_sock(sk);                            
366         if (atomic_read(&ask->refcnt) != atomi    
367                 goto unlock;                      
368                                                   
369         type = ask->type;                         
370                                                   
371         err = -ENOPROTOOPT;                       
372         if (level != SOL_ALG || !type)            
373                 goto unlock;                      
374                                                   
375         switch (optname) {                        
376         case ALG_SET_KEY:                         
377         case ALG_SET_KEY_BY_KEY_SERIAL:           
378                 if (sock->state == SS_CONNECTE    
379                         goto unlock;              
380                 if (!type->setkey)                
381                         goto unlock;              
382                                                   
383                 if (optname == ALG_SET_KEY_BY_    
384                         err = alg_setkey_by_ke    
385                 else                              
386                         err = alg_setkey(sk, o    
387                 break;                            
388         case ALG_SET_AEAD_AUTHSIZE:               
389                 if (sock->state == SS_CONNECTE    
390                         goto unlock;              
391                 if (!type->setauthsize)           
392                         goto unlock;              
393                 err = type->setauthsize(ask->p    
394                 break;                            
395         case ALG_SET_DRBG_ENTROPY:                
396                 if (sock->state == SS_CONNECTE    
397                         goto unlock;              
398                 if (!type->setentropy)            
399                         goto unlock;              
400                                                   
401                 err = type->setentropy(ask->pr    
402         }                                         
403                                                   
404 unlock:                                           
405         release_sock(sk);                         
406                                                   
407         return err;                               
408 }                                                 
409                                                   
410 int af_alg_accept(struct sock *sk, struct sock    
411                   struct proto_accept_arg *arg    
412 {                                                 
413         struct alg_sock *ask = alg_sk(sk);        
414         const struct af_alg_type *type;           
415         struct sock *sk2;                         
416         unsigned int nokey;                       
417         int err;                                  
418                                                   
419         lock_sock(sk);                            
420         type = ask->type;                         
421                                                   
422         err = -EINVAL;                            
423         if (!type)                                
424                 goto unlock;                      
425                                                   
426         sk2 = sk_alloc(sock_net(sk), PF_ALG, G    
427         err = -ENOMEM;                            
428         if (!sk2)                                 
429                 goto unlock;                      
430                                                   
431         sock_init_data(newsock, sk2);             
432         security_sock_graft(sk2, newsock);        
433         security_sk_clone(sk, sk2);               
434                                                   
435         /*                                        
436          * newsock->ops assigned here to allow    
437          * them when required.                    
438          */                                       
439         newsock->ops = type->ops;                 
440         err = type->accept(ask->private, sk2);    
441                                                   
442         nokey = err == -ENOKEY;                   
443         if (nokey && type->accept_nokey)          
444                 err = type->accept_nokey(ask->    
445                                                   
446         if (err)                                  
447                 goto unlock;                      
448                                                   
449         if (atomic_inc_return_relaxed(&ask->re    
450                 sock_hold(sk);                    
451         if (nokey) {                              
452                 atomic_inc(&ask->nokey_refcnt)    
453                 atomic_set(&alg_sk(sk2)->nokey    
454         }                                         
455         alg_sk(sk2)->parent = sk;                 
456         alg_sk(sk2)->type = type;                 
457                                                   
458         newsock->state = SS_CONNECTED;            
459                                                   
460         if (nokey)                                
461                 newsock->ops = type->ops_nokey    
462                                                   
463         err = 0;                                  
464                                                   
465 unlock:                                           
466         release_sock(sk);                         
467                                                   
468         return err;                               
469 }                                                 
470 EXPORT_SYMBOL_GPL(af_alg_accept);                 
471                                                   
472 static int alg_accept(struct socket *sock, str    
473                       struct proto_accept_arg     
474 {                                                 
475         return af_alg_accept(sock->sk, newsock    
476 }                                                 
477                                                   
478 static const struct proto_ops alg_proto_ops =     
479         .family         =       PF_ALG,           
480         .owner          =       THIS_MODULE,      
481                                                   
482         .connect        =       sock_no_connec    
483         .socketpair     =       sock_no_socket    
484         .getname        =       sock_no_getnam    
485         .ioctl          =       sock_no_ioctl,    
486         .listen         =       sock_no_listen    
487         .shutdown       =       sock_no_shutdo    
488         .mmap           =       sock_no_mmap,     
489         .sendmsg        =       sock_no_sendms    
490         .recvmsg        =       sock_no_recvms    
491                                                   
492         .bind           =       alg_bind,         
493         .release        =       af_alg_release    
494         .setsockopt     =       alg_setsockopt    
495         .accept         =       alg_accept,       
496 };                                                
497                                                   
498 static void alg_sock_destruct(struct sock *sk)    
499 {                                                 
500         struct alg_sock *ask = alg_sk(sk);        
501                                                   
502         alg_do_release(ask->type, ask->private    
503 }                                                 
504                                                   
505 static int alg_create(struct net *net, struct     
506                       int kern)                   
507 {                                                 
508         struct sock *sk;                          
509         int err;                                  
510                                                   
511         if (sock->type != SOCK_SEQPACKET)         
512                 return -ESOCKTNOSUPPORT;          
513         if (protocol != 0)                        
514                 return -EPROTONOSUPPORT;          
515                                                   
516         err = -ENOMEM;                            
517         sk = sk_alloc(net, PF_ALG, GFP_KERNEL,    
518         if (!sk)                                  
519                 goto out;                         
520                                                   
521         sock->ops = &alg_proto_ops;               
522         sock_init_data(sock, sk);                 
523                                                   
524         sk->sk_destruct = alg_sock_destruct;      
525                                                   
526         return 0;                                 
527 out:                                              
528         return err;                               
529 }                                                 
530                                                   
531 static const struct net_proto_family alg_famil    
532         .family =       PF_ALG,                   
533         .create =       alg_create,               
534         .owner  =       THIS_MODULE,              
535 };                                                
536                                                   
537 static void af_alg_link_sg(struct af_alg_sgl *    
538                            struct af_alg_sgl *    
539 {                                                 
540         sg_unmark_end(sgl_prev->sgt.sgl + sgl_    
541         sg_chain(sgl_prev->sgt.sgl, sgl_prev->    
542 }                                                 
543                                                   
544 void af_alg_free_sg(struct af_alg_sgl *sgl)       
545 {                                                 
546         int i;                                    
547                                                   
548         if (sgl->sgt.sgl) {                       
549                 if (sgl->need_unpin)              
550                         for (i = 0; i < sgl->s    
551                                 unpin_user_pag    
552                 if (sgl->sgt.sgl != sgl->sgl)     
553                         kvfree(sgl->sgt.sgl);     
554                 sgl->sgt.sgl = NULL;              
555         }                                         
556 }                                                 
557 EXPORT_SYMBOL_GPL(af_alg_free_sg);                
558                                                   
559 static int af_alg_cmsg_send(struct msghdr *msg    
560 {                                                 
561         struct cmsghdr *cmsg;                     
562                                                   
563         for_each_cmsghdr(cmsg, msg) {             
564                 if (!CMSG_OK(msg, cmsg))          
565                         return -EINVAL;           
566                 if (cmsg->cmsg_level != SOL_AL    
567                         continue;                 
568                                                   
569                 switch (cmsg->cmsg_type) {        
570                 case ALG_SET_IV:                  
571                         if (cmsg->cmsg_len < C    
572                                 return -EINVAL    
573                         con->iv = (void *)CMSG    
574                         if (cmsg->cmsg_len < C    
575                                                   
576                                 return -EINVAL    
577                         break;                    
578                                                   
579                 case ALG_SET_OP:                  
580                         if (cmsg->cmsg_len < C    
581                                 return -EINVAL    
582                         con->op = *(u32 *)CMSG    
583                         break;                    
584                                                   
585                 case ALG_SET_AEAD_ASSOCLEN:       
586                         if (cmsg->cmsg_len < C    
587                                 return -EINVAL    
588                         con->aead_assoclen = *    
589                         break;                    
590                                                   
591                 default:                          
592                         return -EINVAL;           
593                 }                                 
594         }                                         
595                                                   
596         return 0;                                 
597 }                                                 
598                                                   
599 /**                                               
600  * af_alg_alloc_tsgl - allocate the TX SGL        
601  *                                                
602  * @sk: socket of connection to user space        
603  * Return: 0 upon success, < 0 upon error         
604  */                                               
605 static int af_alg_alloc_tsgl(struct sock *sk)     
606 {                                                 
607         struct alg_sock *ask = alg_sk(sk);        
608         struct af_alg_ctx *ctx = ask->private;    
609         struct af_alg_tsgl *sgl;                  
610         struct scatterlist *sg = NULL;            
611                                                   
612         sgl = list_entry(ctx->tsgl_list.prev,     
613         if (!list_empty(&ctx->tsgl_list))         
614                 sg = sgl->sg;                     
615                                                   
616         if (!sg || sgl->cur >= MAX_SGL_ENTS) {    
617                 sgl = sock_kmalloc(sk,            
618                                    struct_size    
619                                    GFP_KERNEL)    
620                 if (!sgl)                         
621                         return -ENOMEM;           
622                                                   
623                 sg_init_table(sgl->sg, MAX_SGL    
624                 sgl->cur = 0;                     
625                                                   
626                 if (sg)                           
627                         sg_chain(sg, MAX_SGL_E    
628                                                   
629                 list_add_tail(&sgl->list, &ctx    
630         }                                         
631                                                   
632         return 0;                                 
633 }                                                 
634                                                   
635 /**                                               
636  * af_alg_count_tsgl - Count number of TX SG e    
637  *                                                
638  * The counting starts from the beginning of t    
639  * an @offset is provided, the counting of the    
640  *                                                
641  * @sk: socket of connection to user space        
642  * @bytes: Count the number of SG entries hold    
643  * @offset: Start the counting of SG entries f    
644  * Return: Number of TX SG entries found given    
645  */                                               
646 unsigned int af_alg_count_tsgl(struct sock *sk    
647 {                                                 
648         const struct alg_sock *ask = alg_sk(sk    
649         const struct af_alg_ctx *ctx = ask->pr    
650         const struct af_alg_tsgl *sgl;            
651         unsigned int i;                           
652         unsigned int sgl_count = 0;               
653                                                   
654         if (!bytes)                               
655                 return 0;                         
656                                                   
657         list_for_each_entry(sgl, &ctx->tsgl_li    
658                 const struct scatterlist *sg =    
659                                                   
660                 for (i = 0; i < sgl->cur; i++)    
661                         size_t bytes_count;       
662                                                   
663                         /* Skip offset */         
664                         if (offset >= sg[i].le    
665                                 offset -= sg[i    
666                                 bytes -= sg[i]    
667                                 continue;         
668                         }                         
669                                                   
670                         bytes_count = sg[i].le    
671                                                   
672                         offset = 0;               
673                         sgl_count++;              
674                                                   
675                         /* If we have seen req    
676                         if (bytes_count >= byt    
677                                 return sgl_cou    
678                                                   
679                         bytes -= bytes_count;     
680                 }                                 
681         }                                         
682                                                   
683         return sgl_count;                         
684 }                                                 
685 EXPORT_SYMBOL_GPL(af_alg_count_tsgl);             
686                                                   
687 /**                                               
688  * af_alg_pull_tsgl - Release the specified bu    
689  *                                                
690  * If @dst is non-null, reassign the pages to     
691  * the pages. If @dst_offset is given only rea    
692  * at the @dst_offset (byte). The caller must     
693  * enough (e.g. by using af_alg_count_tsgl wit    
694  *                                                
695  * @sk: socket of connection to user space        
696  * @used: Number of bytes to pull from TX SGL     
697  * @dst: If non-NULL, buffer is reassigned to     
698  *       caller must release the buffers in ds    
699  * @dst_offset: Reassign the TX SGL from given    
700  *              reaching the offset is release    
701  */                                               
702 void af_alg_pull_tsgl(struct sock *sk, size_t     
703                       size_t dst_offset)          
704 {                                                 
705         struct alg_sock *ask = alg_sk(sk);        
706         struct af_alg_ctx *ctx = ask->private;    
707         struct af_alg_tsgl *sgl;                  
708         struct scatterlist *sg;                   
709         unsigned int i, j = 0;                    
710                                                   
711         while (!list_empty(&ctx->tsgl_list)) {    
712                 sgl = list_first_entry(&ctx->t    
713                                        list);     
714                 sg = sgl->sg;                     
715                                                   
716                 for (i = 0; i < sgl->cur; i++)    
717                         size_t plen = min_t(si    
718                         struct page *page = sg    
719                                                   
720                         if (!page)                
721                                 continue;         
722                                                   
723                         /*                        
724                          * Assumption: caller     
725                          * SG entries in dst.     
726                          */                       
727                         if (dst) {                
728                                 if (dst_offset    
729                                         /* dis    
730                                         dst_of    
731                                 } else {          
732                                         /* rea    
733                                         get_pa    
734                                         sg_set    
735                                                   
736                                                   
737                                         dst_of    
738                                         j++;      
739                                 }                 
740                         }                         
741                                                   
742                         sg[i].length -= plen;     
743                         sg[i].offset += plen;     
744                                                   
745                         used -= plen;             
746                         ctx->used -= plen;        
747                                                   
748                         if (sg[i].length)         
749                                 return;           
750                                                   
751                         put_page(page);           
752                         sg_assign_page(sg + i,    
753                 }                                 
754                                                   
755                 list_del(&sgl->list);             
756                 sock_kfree_s(sk, sgl, struct_s    
757         }                                         
758                                                   
759         if (!ctx->used)                           
760                 ctx->merge = 0;                   
761         ctx->init = ctx->more;                    
762 }                                                 
763 EXPORT_SYMBOL_GPL(af_alg_pull_tsgl);              
764                                                   
765 /**                                               
766  * af_alg_free_areq_sgls - Release TX and RX S    
767  *                                                
768  * @areq: Request holding the TX and RX SGL       
769  */                                               
770 static void af_alg_free_areq_sgls(struct af_al    
771 {                                                 
772         struct sock *sk = areq->sk;               
773         struct alg_sock *ask = alg_sk(sk);        
774         struct af_alg_ctx *ctx = ask->private;    
775         struct af_alg_rsgl *rsgl, *tmp;           
776         struct scatterlist *tsgl;                 
777         struct scatterlist *sg;                   
778         unsigned int i;                           
779                                                   
780         list_for_each_entry_safe(rsgl, tmp, &a    
781                 atomic_sub(rsgl->sg_num_bytes,    
782                 af_alg_free_sg(&rsgl->sgl);       
783                 list_del(&rsgl->list);            
784                 if (rsgl != &areq->first_rsgl)    
785                         sock_kfree_s(sk, rsgl,    
786         }                                         
787                                                   
788         tsgl = areq->tsgl;                        
789         if (tsgl) {                               
790                 for_each_sg(tsgl, sg, areq->ts    
791                         if (!sg_page(sg))         
792                                 continue;         
793                         put_page(sg_page(sg));    
794                 }                                 
795                                                   
796                 sock_kfree_s(sk, tsgl, areq->t    
797         }                                         
798 }                                                 
799                                                   
800 /**                                               
801  * af_alg_wait_for_wmem - wait for availabilit    
802  *                                                
803  * @sk: socket of connection to user space        
804  * @flags: If MSG_DONTWAIT is set, then only r    
805  * Return: 0 when writable memory is available    
806  */                                               
807 static int af_alg_wait_for_wmem(struct sock *s    
808 {                                                 
809         DEFINE_WAIT_FUNC(wait, woken_wake_func    
810         int err = -ERESTARTSYS;                   
811         long timeout;                             
812                                                   
813         if (flags & MSG_DONTWAIT)                 
814                 return -EAGAIN;                   
815                                                   
816         sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);     
817                                                   
818         add_wait_queue(sk_sleep(sk), &wait);      
819         for (;;) {                                
820                 if (signal_pending(current))      
821                         break;                    
822                 timeout = MAX_SCHEDULE_TIMEOUT    
823                 if (sk_wait_event(sk, &timeout    
824                         err = 0;                  
825                         break;                    
826                 }                                 
827         }                                         
828         remove_wait_queue(sk_sleep(sk), &wait)    
829                                                   
830         return err;                               
831 }                                                 
832                                                   
833 /**                                               
834  * af_alg_wmem_wakeup - wakeup caller when wri    
835  *                                                
836  * @sk: socket of connection to user space        
837  */                                               
838 void af_alg_wmem_wakeup(struct sock *sk)          
839 {                                                 
840         struct socket_wq *wq;                     
841                                                   
842         if (!af_alg_writable(sk))                 
843                 return;                           
844                                                   
845         rcu_read_lock();                          
846         wq = rcu_dereference(sk->sk_wq);          
847         if (skwq_has_sleeper(wq))                 
848                 wake_up_interruptible_sync_pol    
849                                                   
850                                                   
851         sk_wake_async_rcu(sk, SOCK_WAKE_WAITD,    
852         rcu_read_unlock();                        
853 }                                                 
854 EXPORT_SYMBOL_GPL(af_alg_wmem_wakeup);            
855                                                   
856 /**                                               
857  * af_alg_wait_for_data - wait for availabilit    
858  *                                                
859  * @sk: socket of connection to user space        
860  * @flags: If MSG_DONTWAIT is set, then only r    
861  * @min: Set to minimum request size if partia    
862  * Return: 0 when writable memory is available    
863  */                                               
864 int af_alg_wait_for_data(struct sock *sk, unsi    
865 {                                                 
866         DEFINE_WAIT_FUNC(wait, woken_wake_func    
867         struct alg_sock *ask = alg_sk(sk);        
868         struct af_alg_ctx *ctx = ask->private;    
869         long timeout;                             
870         int err = -ERESTARTSYS;                   
871                                                   
872         if (flags & MSG_DONTWAIT)                 
873                 return -EAGAIN;                   
874                                                   
875         sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);    
876                                                   
877         add_wait_queue(sk_sleep(sk), &wait);      
878         for (;;) {                                
879                 if (signal_pending(current))      
880                         break;                    
881                 timeout = MAX_SCHEDULE_TIMEOUT    
882                 if (sk_wait_event(sk, &timeout    
883                                   ctx->init &&    
884                                                   
885                                   &wait)) {       
886                         err = 0;                  
887                         break;                    
888                 }                                 
889         }                                         
890         remove_wait_queue(sk_sleep(sk), &wait)    
891                                                   
892         sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk    
893                                                   
894         return err;                               
895 }                                                 
896 EXPORT_SYMBOL_GPL(af_alg_wait_for_data);          
897                                                   
898 /**                                               
899  * af_alg_data_wakeup - wakeup caller when new    
900  *                                                
901  * @sk: socket of connection to user space        
902  */                                               
903 static void af_alg_data_wakeup(struct sock *sk    
904 {                                                 
905         struct alg_sock *ask = alg_sk(sk);        
906         struct af_alg_ctx *ctx = ask->private;    
907         struct socket_wq *wq;                     
908                                                   
909         if (!ctx->used)                           
910                 return;                           
911                                                   
912         rcu_read_lock();                          
913         wq = rcu_dereference(sk->sk_wq);          
914         if (skwq_has_sleeper(wq))                 
915                 wake_up_interruptible_sync_pol    
916                                                   
917                                                   
918         sk_wake_async_rcu(sk, SOCK_WAKE_SPACE,    
919         rcu_read_unlock();                        
920 }                                                 
921                                                   
922 /**                                               
923  * af_alg_sendmsg - implementation of sendmsg     
924  *                                                
925  * The sendmsg system call handler obtains the    
926  * in ctx->tsgl_list. This implies allocation     
927  * struct af_alg_tsgl.                            
928  *                                                
929  * In addition, the ctx is filled with the inf    
930  *                                                
931  * @sock: socket of connection to user space      
932  * @msg: message from user space                  
933  * @size: size of message from user space         
934  * @ivsize: the size of the IV for the cipher     
935  *         user-space-provided IV has the righ    
936  * Return: the number of copied data upon succ    
937  */                                               
938 int af_alg_sendmsg(struct socket *sock, struct    
939                    unsigned int ivsize)           
940 {                                                 
941         struct sock *sk = sock->sk;               
942         struct alg_sock *ask = alg_sk(sk);        
943         struct af_alg_ctx *ctx = ask->private;    
944         struct af_alg_tsgl *sgl;                  
945         struct af_alg_control con = {};           
946         long copied = 0;                          
947         bool enc = false;                         
948         bool init = false;                        
949         int err = 0;                              
950                                                   
951         if (msg->msg_controllen) {                
952                 err = af_alg_cmsg_send(msg, &c    
953                 if (err)                          
954                         return err;               
955                                                   
956                 init = true;                      
957                 switch (con.op) {                 
958                 case ALG_OP_ENCRYPT:              
959                         enc = true;               
960                         break;                    
961                 case ALG_OP_DECRYPT:              
962                         enc = false;              
963                         break;                    
964                 default:                          
965                         return -EINVAL;           
966                 }                                 
967                                                   
968                 if (con.iv && con.iv->ivlen !=    
969                         return -EINVAL;           
970         }                                         
971                                                   
972         lock_sock(sk);                            
973         if (ctx->init && !ctx->more) {            
974                 if (ctx->used) {                  
975                         err = -EINVAL;            
976                         goto unlock;              
977                 }                                 
978                                                   
979                 pr_info_once(                     
980                         "%s sent an empty cont    
981                         current->comm);           
982         }                                         
983         ctx->init = true;                         
984                                                   
985         if (init) {                               
986                 ctx->enc = enc;                   
987                 if (con.iv)                       
988                         memcpy(ctx->iv, con.iv    
989                                                   
990                 ctx->aead_assoclen = con.aead_    
991         }                                         
992                                                   
993         while (size) {                            
994                 struct scatterlist *sg;           
995                 size_t len = size;                
996                 ssize_t plen;                     
997                                                   
998                 /* use the existing memory in     
999                 if (ctx->merge && !(msg->msg_f    
1000                         sgl = list_entry(ctx-    
1001                                          stru    
1002                         sg = sgl->sg + sgl->c    
1003                         len = min_t(size_t, l    
1004                                     PAGE_SIZE    
1005                                                  
1006                         err = memcpy_from_msg    
1007                                                  
1008                                                  
1009                         if (err)                 
1010                                 goto unlock;     
1011                                                  
1012                         sg->length += len;       
1013                         ctx->merge = (sg->off    
1014                                      (PAGE_SI    
1015                                                  
1016                         ctx->used += len;        
1017                         copied += len;           
1018                         size -= len;             
1019                         continue;                
1020                 }                                
1021                                                  
1022                 if (!af_alg_writable(sk)) {      
1023                         err = af_alg_wait_for    
1024                         if (err)                 
1025                                 goto unlock;     
1026                 }                                
1027                                                  
1028                 /* allocate a new page */        
1029                 len = min_t(unsigned long, le    
1030                                                  
1031                 err = af_alg_alloc_tsgl(sk);     
1032                 if (err)                         
1033                         goto unlock;             
1034                                                  
1035                 sgl = list_entry(ctx->tsgl_li    
1036                                  list);          
1037                 sg = sgl->sg;                    
1038                 if (sgl->cur)                    
1039                         sg_unmark_end(sg + sg    
1040                                                  
1041                 if (msg->msg_flags & MSG_SPLI    
1042                         struct sg_table sgtab    
1043                                 .sgl             
1044                                 .nents           
1045                                 .orig_nents      
1046                         };                       
1047                                                  
1048                         plen = extract_iter_t    
1049                                                  
1050                         if (plen < 0) {          
1051                                 err = plen;      
1052                                 goto unlock;     
1053                         }                        
1054                                                  
1055                         for (; sgl->cur < sgt    
1056                                 get_page(sg_p    
1057                         len -= plen;             
1058                         ctx->used += plen;       
1059                         copied += plen;          
1060                         size -= plen;            
1061                         ctx->merge = 0;          
1062                 } else {                         
1063                         do {                     
1064                                 struct page *    
1065                                 unsigned int     
1066                                                  
1067                                 plen = min_t(    
1068                                                  
1069                                 pg = alloc_pa    
1070                                 if (!pg) {       
1071                                         err =    
1072                                         goto     
1073                                 }                
1074                                                  
1075                                 sg_assign_pag    
1076                                                  
1077                                 err = memcpy_    
1078                                         page_    
1079                                         msg,     
1080                                 if (err) {       
1081                                         __fre    
1082                                         sg_as    
1083                                         goto     
1084                                 }                
1085                                                  
1086                                 sg[i].length     
1087                                 len -= plen;     
1088                                 ctx->used +=     
1089                                 copied += ple    
1090                                 size -= plen;    
1091                                 sgl->cur++;      
1092                         } while (len && sgl->    
1093                                                  
1094                         ctx->merge = plen & (    
1095                 }                                
1096                                                  
1097                 if (!size)                       
1098                         sg_mark_end(sg + sgl-    
1099         }                                        
1100                                                  
1101         err = 0;                                 
1102                                                  
1103         ctx->more = msg->msg_flags & MSG_MORE    
1104                                                  
1105 unlock:                                          
1106         af_alg_data_wakeup(sk);                  
1107         release_sock(sk);                        
1108                                                  
1109         return copied ?: err;                    
1110 }                                                
1111 EXPORT_SYMBOL_GPL(af_alg_sendmsg);               
1112                                                  
1113 /**                                              
1114  * af_alg_free_resources - release resources     
1115  * @areq: Request holding the TX and RX SGL      
1116  */                                              
1117 void af_alg_free_resources(struct af_alg_asyn    
1118 {                                                
1119         struct sock *sk = areq->sk;              
1120         struct af_alg_ctx *ctx;                  
1121                                                  
1122         af_alg_free_areq_sgls(areq);             
1123         sock_kfree_s(sk, areq, areq->areqlen)    
1124                                                  
1125         ctx = alg_sk(sk)->private;               
1126         ctx->inflight = false;                   
1127 }                                                
1128 EXPORT_SYMBOL_GPL(af_alg_free_resources);        
1129                                                  
1130 /**                                              
1131  * af_alg_async_cb - AIO callback handler        
1132  * @data: async request completion data          
1133  * @err: if non-zero, error result to be retu    
1134  *       otherwise return the AIO output leng    
1135  *                                               
1136  * This handler cleans up the struct af_alg_a    
1137  * AIO operation.                                
1138  *                                               
1139  * The number of bytes to be generated with t    
1140  * in areq->outlen before the AIO callback ha    
1141  */                                              
1142 void af_alg_async_cb(void *data, int err)        
1143 {                                                
1144         struct af_alg_async_req *areq = data;    
1145         struct sock *sk = areq->sk;              
1146         struct kiocb *iocb = areq->iocb;         
1147         unsigned int resultlen;                  
1148                                                  
1149         /* Buffer size written by crypto oper    
1150         resultlen = areq->outlen;                
1151                                                  
1152         af_alg_free_resources(areq);             
1153         sock_put(sk);                            
1154                                                  
1155         iocb->ki_complete(iocb, err ? err : (    
1156 }                                                
1157 EXPORT_SYMBOL_GPL(af_alg_async_cb);              
1158                                                  
1159 /**                                              
1160  * af_alg_poll - poll system call handler        
1161  * @file: file pointer                           
1162  * @sock: socket to poll                         
1163  * @wait: poll_table                             
1164  */                                              
1165 __poll_t af_alg_poll(struct file *file, struc    
1166                          poll_table *wait)       
1167 {                                                
1168         struct sock *sk = sock->sk;              
1169         struct alg_sock *ask = alg_sk(sk);       
1170         struct af_alg_ctx *ctx = ask->private    
1171         __poll_t mask;                           
1172                                                  
1173         sock_poll_wait(file, sock, wait);        
1174         mask = 0;                                
1175                                                  
1176         if (!ctx->more || ctx->used)             
1177                 mask |= EPOLLIN | EPOLLRDNORM    
1178                                                  
1179         if (af_alg_writable(sk))                 
1180                 mask |= EPOLLOUT | EPOLLWRNOR    
1181                                                  
1182         return mask;                             
1183 }                                                
1184 EXPORT_SYMBOL_GPL(af_alg_poll);                  
1185                                                  
1186 /**                                              
1187  * af_alg_alloc_areq - allocate struct af_alg    
1188  *                                               
1189  * @sk: socket of connection to user space       
1190  * @areqlen: size of struct af_alg_async_req     
1191  * Return: allocated data structure or ERR_PT    
1192  */                                              
1193 struct af_alg_async_req *af_alg_alloc_areq(st    
1194                                            un    
1195 {                                                
1196         struct af_alg_ctx *ctx = alg_sk(sk)->    
1197         struct af_alg_async_req *areq;           
1198                                                  
1199         /* Only one AIO request can be in fli    
1200         if (ctx->inflight)                       
1201                 return ERR_PTR(-EBUSY);          
1202                                                  
1203         areq = sock_kmalloc(sk, areqlen, GFP_    
1204         if (unlikely(!areq))                     
1205                 return ERR_PTR(-ENOMEM);         
1206                                                  
1207         ctx->inflight = true;                    
1208                                                  
1209         areq->areqlen = areqlen;                 
1210         areq->sk = sk;                           
1211         areq->first_rsgl.sgl.sgt.sgl = areq->    
1212         areq->last_rsgl = NULL;                  
1213         INIT_LIST_HEAD(&areq->rsgl_list);        
1214         areq->tsgl = NULL;                       
1215         areq->tsgl_entries = 0;                  
1216                                                  
1217         return areq;                             
1218 }                                                
1219 EXPORT_SYMBOL_GPL(af_alg_alloc_areq);            
1220                                                  
1221 /**                                              
1222  * af_alg_get_rsgl - create the RX SGL for th    
1223  *                   operation                   
1224  *                                               
1225  * @sk: socket of connection to user space       
1226  * @msg: user space message                      
1227  * @flags: flags used to invoke recvmsg with     
1228  * @areq: instance of the cryptographic reque    
1229  * @maxsize: maximum number of bytes to be pu    
1230  * @outlen: number of bytes in the RX SGL        
1231  * Return: 0 on success, < 0 upon error          
1232  */                                              
1233 int af_alg_get_rsgl(struct sock *sk, struct m    
1234                     struct af_alg_async_req *    
1235                     size_t *outlen)              
1236 {                                                
1237         struct alg_sock *ask = alg_sk(sk);       
1238         struct af_alg_ctx *ctx = ask->private    
1239         size_t len = 0;                          
1240                                                  
1241         while (maxsize > len && msg_data_left    
1242                 struct af_alg_rsgl *rsgl;        
1243                 ssize_t err;                     
1244                 size_t seglen;                   
1245                                                  
1246                 /* limit the amount of readab    
1247                 if (!af_alg_readable(sk))        
1248                         break;                   
1249                                                  
1250                 seglen = min_t(size_t, (maxsi    
1251                                msg_data_left(    
1252                                                  
1253                 if (list_empty(&areq->rsgl_li    
1254                         rsgl = &areq->first_r    
1255                 } else {                         
1256                         rsgl = sock_kmalloc(s    
1257                         if (unlikely(!rsgl))     
1258                                 return -ENOME    
1259                 }                                
1260                                                  
1261                 rsgl->sgl.need_unpin =           
1262                         iov_iter_extract_will    
1263                 rsgl->sgl.sgt.sgl = rsgl->sgl    
1264                 rsgl->sgl.sgt.nents = 0;         
1265                 rsgl->sgl.sgt.orig_nents = 0;    
1266                 list_add_tail(&rsgl->list, &a    
1267                                                  
1268                 sg_init_table(rsgl->sgl.sgt.s    
1269                 err = extract_iter_to_sg(&msg    
1270                                          ALG_    
1271                 if (err < 0) {                   
1272                         rsgl->sg_num_bytes =     
1273                         return err;              
1274                 }                                
1275                                                  
1276                 sg_mark_end(rsgl->sgl.sgt.sgl    
1277                                                  
1278                 /* chain the new scatterlist     
1279                 if (areq->last_rsgl)             
1280                         af_alg_link_sg(&areq-    
1281                                                  
1282                 areq->last_rsgl = rsgl;          
1283                 len += err;                      
1284                 atomic_add(err, &ctx->rcvused    
1285                 rsgl->sg_num_bytes = err;        
1286         }                                        
1287                                                  
1288         *outlen = len;                           
1289         return 0;                                
1290 }                                                
1291 EXPORT_SYMBOL_GPL(af_alg_get_rsgl);              
1292                                                  
1293 static int __init af_alg_init(void)              
1294 {                                                
1295         int err = proto_register(&alg_proto,     
1296                                                  
1297         if (err)                                 
1298                 goto out;                        
1299                                                  
1300         err = sock_register(&alg_family);        
1301         if (err != 0)                            
1302                 goto out_unregister_proto;       
1303                                                  
1304 out:                                             
1305         return err;                              
1306                                                  
1307 out_unregister_proto:                            
1308         proto_unregister(&alg_proto);            
1309         goto out;                                
1310 }                                                
1311                                                  
1312 static void __exit af_alg_exit(void)             
1313 {                                                
1314         sock_unregister(PF_ALG);                 
1315         proto_unregister(&alg_proto);            
1316 }                                                
1317                                                  
1318 module_init(af_alg_init);                        
1319 module_exit(af_alg_exit);                        
1320 MODULE_DESCRIPTION("Crypto userspace interfac    
1321 MODULE_LICENSE("GPL");                           
1322 MODULE_ALIAS_NETPROTO(AF_ALG);                   
1323                                                  

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php