10
10
*
11
11
*/
12
12
13
+ #include <linux/err.h>
13
14
#include <linux/errno.h>
14
15
#include <linux/init.h>
15
16
#include <linux/kernel.h>
@@ -73,27 +74,96 @@ static int crypto_check_alg(struct crypto_alg *alg)
73
74
return crypto_set_driver_name (alg );
74
75
}
75
76
76
- static int __crypto_register_alg (struct crypto_alg * alg )
77
+ static void crypto_destroy_instance (struct crypto_alg * alg )
78
+ {
79
+ struct crypto_instance * inst = (void * )alg ;
80
+ struct crypto_template * tmpl = inst -> tmpl ;
81
+
82
+ tmpl -> free (inst );
83
+ crypto_tmpl_put (tmpl );
84
+ }
85
+
86
+ static void crypto_remove_spawns (struct list_head * spawns ,
87
+ struct list_head * list )
88
+ {
89
+ struct crypto_spawn * spawn , * n ;
90
+
91
+ list_for_each_entry_safe (spawn , n , spawns , list ) {
92
+ struct crypto_instance * inst = spawn -> inst ;
93
+ struct crypto_template * tmpl = inst -> tmpl ;
94
+
95
+ list_del_init (& spawn -> list );
96
+ spawn -> alg = NULL ;
97
+
98
+ if (crypto_is_dead (& inst -> alg ))
99
+ continue ;
100
+
101
+ inst -> alg .cra_flags |= CRYPTO_ALG_DEAD ;
102
+ if (!tmpl || !crypto_tmpl_get (tmpl ))
103
+ continue ;
104
+
105
+ crypto_notify (CRYPTO_MSG_ALG_UNREGISTER , & inst -> alg );
106
+ list_move (& inst -> alg .cra_list , list );
107
+ hlist_del (& inst -> list );
108
+ inst -> alg .cra_destroy = crypto_destroy_instance ;
109
+
110
+ if (!list_empty (& inst -> alg .cra_users )) {
111
+ if (& n -> list == spawns )
112
+ n = list_entry (inst -> alg .cra_users .next ,
113
+ typeof (* n ), list );
114
+ __list_splice (& inst -> alg .cra_users , spawns -> prev );
115
+ }
116
+ }
117
+ }
118
+
119
+ static int __crypto_register_alg (struct crypto_alg * alg ,
120
+ struct list_head * list )
77
121
{
78
122
struct crypto_alg * q ;
79
- int ret = - EEXIST ;
123
+ int ret = - EAGAIN ;
124
+
125
+ if (crypto_is_dead (alg ))
126
+ goto out ;
127
+
128
+ INIT_LIST_HEAD (& alg -> cra_users );
129
+
130
+ ret = - EEXIST ;
80
131
81
132
atomic_set (& alg -> cra_refcnt , 1 );
82
133
list_for_each_entry (q , & crypto_alg_list , cra_list ) {
83
134
if (q == alg )
84
135
goto out ;
85
- if (crypto_is_larval (q ) &&
86
- (!strcmp (alg -> cra_name , q -> cra_name ) ||
87
- !strcmp (alg -> cra_driver_name , q -> cra_name ))) {
136
+
137
+ if (crypto_is_moribund (q ))
138
+ continue ;
139
+
140
+ if (crypto_is_larval (q )) {
88
141
struct crypto_larval * larval = (void * )q ;
89
142
143
+ if (strcmp (alg -> cra_name , q -> cra_name ) &&
144
+ strcmp (alg -> cra_driver_name , q -> cra_name ))
145
+ continue ;
146
+
147
+ if (larval -> adult )
148
+ continue ;
90
149
if ((q -> cra_flags ^ alg -> cra_flags ) & larval -> mask )
91
150
continue ;
92
151
if (!crypto_mod_get (alg ))
93
152
continue ;
153
+
94
154
larval -> adult = alg ;
95
155
complete (& larval -> completion );
156
+ continue ;
96
157
}
158
+
159
+ if (strcmp (alg -> cra_name , q -> cra_name ))
160
+ continue ;
161
+
162
+ if (strcmp (alg -> cra_driver_name , q -> cra_driver_name ) &&
163
+ q -> cra_priority > alg -> cra_priority )
164
+ continue ;
165
+
166
+ crypto_remove_spawns (& q -> cra_users , list );
97
167
}
98
168
99
169
list_add (& alg -> cra_list , & crypto_alg_list );
@@ -105,32 +175,56 @@ static int __crypto_register_alg(struct crypto_alg *alg)
105
175
return ret ;
106
176
}
107
177
178
+ static void crypto_remove_final (struct list_head * list )
179
+ {
180
+ struct crypto_alg * alg ;
181
+ struct crypto_alg * n ;
182
+
183
+ list_for_each_entry_safe (alg , n , list , cra_list ) {
184
+ list_del_init (& alg -> cra_list );
185
+ crypto_alg_put (alg );
186
+ }
187
+ }
188
+
108
189
int crypto_register_alg (struct crypto_alg * alg )
109
190
{
191
+ LIST_HEAD (list );
110
192
int err ;
111
193
112
194
err = crypto_check_alg (alg );
113
195
if (err )
114
196
return err ;
115
197
116
198
down_write (& crypto_alg_sem );
117
- err = __crypto_register_alg (alg );
199
+ err = __crypto_register_alg (alg , & list );
118
200
up_write (& crypto_alg_sem );
119
201
202
+ crypto_remove_final (& list );
120
203
return err ;
121
204
}
122
205
EXPORT_SYMBOL_GPL (crypto_register_alg );
123
206
207
+ static int crypto_remove_alg (struct crypto_alg * alg , struct list_head * list )
208
+ {
209
+ if (unlikely (list_empty (& alg -> cra_list )))
210
+ return - ENOENT ;
211
+
212
+ alg -> cra_flags |= CRYPTO_ALG_DEAD ;
213
+
214
+ crypto_notify (CRYPTO_MSG_ALG_UNREGISTER , alg );
215
+ list_del_init (& alg -> cra_list );
216
+ crypto_remove_spawns (& alg -> cra_users , list );
217
+
218
+ return 0 ;
219
+ }
220
+
124
221
int crypto_unregister_alg (struct crypto_alg * alg )
125
222
{
126
- int ret = - ENOENT ;
223
+ int ret ;
224
+ LIST_HEAD (list );
127
225
128
226
down_write (& crypto_alg_sem );
129
- if (likely (!list_empty (& alg -> cra_list ))) {
130
- list_del_init (& alg -> cra_list );
131
- ret = 0 ;
132
- }
133
- crypto_notify (CRYPTO_MSG_ALG_UNREGISTER , alg );
227
+ ret = crypto_remove_alg (alg , & list );
134
228
up_write (& crypto_alg_sem );
135
229
136
230
if (ret )
@@ -140,6 +234,7 @@ int crypto_unregister_alg(struct crypto_alg *alg)
140
234
if (alg -> cra_destroy )
141
235
alg -> cra_destroy (alg );
142
236
237
+ crypto_remove_final (& list );
143
238
return 0 ;
144
239
}
145
240
EXPORT_SYMBOL_GPL (crypto_unregister_alg );
@@ -170,6 +265,7 @@ void crypto_unregister_template(struct crypto_template *tmpl)
170
265
struct crypto_instance * inst ;
171
266
struct hlist_node * p , * n ;
172
267
struct hlist_head * list ;
268
+ LIST_HEAD (users );
173
269
174
270
down_write (& crypto_alg_sem );
175
271
@@ -178,9 +274,8 @@ void crypto_unregister_template(struct crypto_template *tmpl)
178
274
179
275
list = & tmpl -> instances ;
180
276
hlist_for_each_entry (inst , p , list , list ) {
181
- BUG_ON (list_empty (& inst -> alg .cra_list ));
182
- list_del_init (& inst -> alg .cra_list );
183
- crypto_notify (CRYPTO_MSG_ALG_UNREGISTER , & inst -> alg );
277
+ int err = crypto_remove_alg (& inst -> alg , & users );
278
+ BUG_ON (err );
184
279
}
185
280
186
281
crypto_notify (CRYPTO_MSG_TMPL_UNREGISTER , tmpl );
@@ -191,6 +286,7 @@ void crypto_unregister_template(struct crypto_template *tmpl)
191
286
BUG_ON (atomic_read (& inst -> alg .cra_refcnt ) != 1 );
192
287
tmpl -> free (inst );
193
288
}
289
+ crypto_remove_final (& users );
194
290
}
195
291
EXPORT_SYMBOL_GPL (crypto_unregister_template );
196
292
@@ -222,6 +318,7 @@ EXPORT_SYMBOL_GPL(crypto_lookup_template);
222
318
int crypto_register_instance (struct crypto_template * tmpl ,
223
319
struct crypto_instance * inst )
224
320
{
321
+ LIST_HEAD (list );
225
322
int err = - EINVAL ;
226
323
227
324
if (inst -> alg .cra_destroy )
@@ -235,7 +332,7 @@ int crypto_register_instance(struct crypto_template *tmpl,
235
332
236
333
down_write (& crypto_alg_sem );
237
334
238
- err = __crypto_register_alg (& inst -> alg );
335
+ err = __crypto_register_alg (& inst -> alg , & list );
239
336
if (err )
240
337
goto unlock ;
241
338
@@ -245,11 +342,67 @@ int crypto_register_instance(struct crypto_template *tmpl,
245
342
unlock :
246
343
up_write (& crypto_alg_sem );
247
344
345
+ crypto_remove_final (& list );
346
+
248
347
err :
249
348
return err ;
250
349
}
251
350
EXPORT_SYMBOL_GPL (crypto_register_instance );
252
351
352
+ int crypto_init_spawn (struct crypto_spawn * spawn , struct crypto_alg * alg ,
353
+ struct crypto_instance * inst )
354
+ {
355
+ int err = - EAGAIN ;
356
+
357
+ spawn -> inst = inst ;
358
+
359
+ down_write (& crypto_alg_sem );
360
+ if (!crypto_is_moribund (alg )) {
361
+ list_add (& spawn -> list , & alg -> cra_users );
362
+ spawn -> alg = alg ;
363
+ err = 0 ;
364
+ }
365
+ up_write (& crypto_alg_sem );
366
+
367
+ return err ;
368
+ }
369
+ EXPORT_SYMBOL_GPL (crypto_init_spawn );
370
+
371
+ void crypto_drop_spawn (struct crypto_spawn * spawn )
372
+ {
373
+ down_write (& crypto_alg_sem );
374
+ list_del (& spawn -> list );
375
+ up_write (& crypto_alg_sem );
376
+ }
377
+ EXPORT_SYMBOL_GPL (crypto_drop_spawn );
378
+
379
+ struct crypto_tfm * crypto_spawn_tfm (struct crypto_spawn * spawn )
380
+ {
381
+ struct crypto_alg * alg ;
382
+ struct crypto_alg * alg2 ;
383
+ struct crypto_tfm * tfm ;
384
+
385
+ down_read (& crypto_alg_sem );
386
+ alg = spawn -> alg ;
387
+ alg2 = alg ;
388
+ if (alg2 )
389
+ alg2 = crypto_mod_get (alg2 );
390
+ up_read (& crypto_alg_sem );
391
+
392
+ if (!alg2 ) {
393
+ if (alg )
394
+ crypto_shoot_alg (alg );
395
+ return ERR_PTR (- EAGAIN );
396
+ }
397
+
398
+ tfm = __crypto_alloc_tfm (alg , 0 );
399
+ if (IS_ERR (tfm ))
400
+ crypto_mod_put (alg );
401
+
402
+ return tfm ;
403
+ }
404
+ EXPORT_SYMBOL_GPL (crypto_spawn_tfm );
405
+
253
406
int crypto_register_notifier (struct notifier_block * nb )
254
407
{
255
408
return blocking_notifier_chain_register (& crypto_chain , nb );
0 commit comments