diff options
-rw-r--r-- | arch/x86/crypto/aesni-intel_glue.c | 37 | ||||
-rw-r--r-- | crypto/ctr.c | 173 | ||||
-rw-r--r-- | crypto/tcrypt.c | 4 | ||||
-rw-r--r-- | crypto/tcrypt.h | 1 | ||||
-rw-r--r-- | include/net/xfrm.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/snmp.h | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_algo.c | 3 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_proc.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 131 |
10 files changed, 185 insertions, 176 deletions
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 1b9c22bea8a7..a0795da22c02 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c | |||
@@ -40,10 +40,6 @@ | |||
40 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
41 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
42 | 42 | ||
43 | #if defined(CONFIG_CRYPTO_CTR) || defined(CONFIG_CRYPTO_CTR_MODULE) | ||
44 | #define HAS_CTR | ||
45 | #endif | ||
46 | |||
47 | #if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE) | 43 | #if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE) |
48 | #define HAS_PCBC | 44 | #define HAS_PCBC |
49 | #endif | 45 | #endif |
@@ -395,12 +391,6 @@ static int ablk_ctr_init(struct crypto_tfm *tfm) | |||
395 | return ablk_init_common(tfm, "__driver-ctr-aes-aesni"); | 391 | return ablk_init_common(tfm, "__driver-ctr-aes-aesni"); |
396 | } | 392 | } |
397 | 393 | ||
398 | #ifdef HAS_CTR | ||
399 | static int ablk_rfc3686_ctr_init(struct crypto_tfm *tfm) | ||
400 | { | ||
401 | return ablk_init_common(tfm, "rfc3686(__driver-ctr-aes-aesni)"); | ||
402 | } | ||
403 | #endif | ||
404 | #endif | 394 | #endif |
405 | 395 | ||
406 | #ifdef HAS_PCBC | 396 | #ifdef HAS_PCBC |
@@ -1158,33 +1148,6 @@ static struct crypto_alg aesni_algs[] = { { | |||
1158 | .maxauthsize = 16, | 1148 | .maxauthsize = 16, |
1159 | }, | 1149 | }, |
1160 | }, | 1150 | }, |
1161 | #ifdef HAS_CTR | ||
1162 | }, { | ||
1163 | .cra_name = "rfc3686(ctr(aes))", | ||
1164 | .cra_driver_name = "rfc3686-ctr-aes-aesni", | ||
1165 | .cra_priority = 400, | ||
1166 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | ||
1167 | .cra_blocksize = 1, | ||
1168 | .cra_ctxsize = sizeof(struct async_helper_ctx), | ||
1169 | .cra_alignmask = 0, | ||
1170 | .cra_type = &crypto_ablkcipher_type, | ||
1171 | .cra_module = THIS_MODULE, | ||
1172 | .cra_init = ablk_rfc3686_ctr_init, | ||
1173 | .cra_exit = ablk_exit, | ||
1174 | .cra_u = { | ||
1175 | .ablkcipher = { | ||
1176 | .min_keysize = AES_MIN_KEY_SIZE + | ||
1177 | CTR_RFC3686_NONCE_SIZE, | ||
1178 | .max_keysize = AES_MAX_KEY_SIZE + | ||
1179 | CTR_RFC3686_NONCE_SIZE, | ||
1180 | .ivsize = CTR_RFC3686_IV_SIZE, | ||
1181 | .setkey = ablk_set_key, | ||
1182 | .encrypt = ablk_encrypt, | ||
1183 | .decrypt = ablk_decrypt, | ||
1184 | .geniv = "seqiv", | ||
1185 | }, | ||
1186 | }, | ||
1187 | #endif | ||
1188 | #endif | 1151 | #endif |
1189 | #ifdef HAS_PCBC | 1152 | #ifdef HAS_PCBC |
1190 | }, { | 1153 | }, { |
diff --git a/crypto/ctr.c b/crypto/ctr.c index 4ca7222cfeb6..1f2997cbfdd4 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <crypto/algapi.h> | 13 | #include <crypto/algapi.h> |
14 | #include <crypto/ctr.h> | 14 | #include <crypto/ctr.h> |
15 | #include <crypto/internal/skcipher.h> | ||
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -25,10 +26,15 @@ struct crypto_ctr_ctx { | |||
25 | }; | 26 | }; |
26 | 27 | ||
27 | struct crypto_rfc3686_ctx { | 28 | struct crypto_rfc3686_ctx { |
28 | struct crypto_blkcipher *child; | 29 | struct crypto_ablkcipher *child; |
29 | u8 nonce[CTR_RFC3686_NONCE_SIZE]; | 30 | u8 nonce[CTR_RFC3686_NONCE_SIZE]; |
30 | }; | 31 | }; |
31 | 32 | ||
33 | struct crypto_rfc3686_req_ctx { | ||
34 | u8 iv[CTR_RFC3686_BLOCK_SIZE]; | ||
35 | struct ablkcipher_request subreq CRYPTO_MINALIGN_ATTR; | ||
36 | }; | ||
37 | |||
32 | static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, | 38 | static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key, |
33 | unsigned int keylen) | 39 | unsigned int keylen) |
34 | { | 40 | { |
@@ -243,11 +249,11 @@ static struct crypto_template crypto_ctr_tmpl = { | |||
243 | .module = THIS_MODULE, | 249 | .module = THIS_MODULE, |
244 | }; | 250 | }; |
245 | 251 | ||
246 | static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key, | 252 | static int crypto_rfc3686_setkey(struct crypto_ablkcipher *parent, |
247 | unsigned int keylen) | 253 | const u8 *key, unsigned int keylen) |
248 | { | 254 | { |
249 | struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent); | 255 | struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(parent); |
250 | struct crypto_blkcipher *child = ctx->child; | 256 | struct crypto_ablkcipher *child = ctx->child; |
251 | int err; | 257 | int err; |
252 | 258 | ||
253 | /* the nonce is stored in bytes at end of key */ | 259 | /* the nonce is stored in bytes at end of key */ |
@@ -259,59 +265,64 @@ static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key, | |||
259 | 265 | ||
260 | keylen -= CTR_RFC3686_NONCE_SIZE; | 266 | keylen -= CTR_RFC3686_NONCE_SIZE; |
261 | 267 | ||
262 | crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); | 268 | crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); |
263 | crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) & | 269 | crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(parent) & |
264 | CRYPTO_TFM_REQ_MASK); | 270 | CRYPTO_TFM_REQ_MASK); |
265 | err = crypto_blkcipher_setkey(child, key, keylen); | 271 | err = crypto_ablkcipher_setkey(child, key, keylen); |
266 | crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) & | 272 | crypto_ablkcipher_set_flags(parent, crypto_ablkcipher_get_flags(child) & |
267 | CRYPTO_TFM_RES_MASK); | 273 | CRYPTO_TFM_RES_MASK); |
268 | 274 | ||
269 | return err; | 275 | return err; |
270 | } | 276 | } |
271 | 277 | ||
272 | static int crypto_rfc3686_crypt(struct blkcipher_desc *desc, | 278 | static int crypto_rfc3686_crypt(struct ablkcipher_request *req) |
273 | struct scatterlist *dst, | ||
274 | struct scatterlist *src, unsigned int nbytes) | ||
275 | { | 279 | { |
276 | struct crypto_blkcipher *tfm = desc->tfm; | 280 | struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); |
277 | struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm); | 281 | struct crypto_rfc3686_ctx *ctx = crypto_ablkcipher_ctx(tfm); |
278 | struct crypto_blkcipher *child = ctx->child; | 282 | struct crypto_ablkcipher *child = ctx->child; |
279 | unsigned long alignmask = crypto_blkcipher_alignmask(tfm); | 283 | unsigned long align = crypto_ablkcipher_alignmask(tfm); |
280 | u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask]; | 284 | struct crypto_rfc3686_req_ctx *rctx = |
281 | u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1); | 285 | (void *)PTR_ALIGN((u8 *)ablkcipher_request_ctx(req), align + 1); |
282 | u8 *info = desc->info; | 286 | struct ablkcipher_request *subreq = &rctx->subreq; |
283 | int err; | 287 | u8 *iv = rctx->iv; |
284 | 288 | ||
285 | /* set up counter block */ | 289 | /* set up counter block */ |
286 | memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE); | 290 | memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE); |
287 | memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE); | 291 | memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->info, CTR_RFC3686_IV_SIZE); |
288 | 292 | ||
289 | /* initialize counter portion of counter block */ | 293 | /* initialize counter portion of counter block */ |
290 | *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = | 294 | *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) = |
291 | cpu_to_be32(1); | 295 | cpu_to_be32(1); |
292 | 296 | ||
293 | desc->tfm = child; | 297 | ablkcipher_request_set_tfm(subreq, child); |
294 | desc->info = iv; | 298 | ablkcipher_request_set_callback(subreq, req->base.flags, |
295 | err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes); | 299 | req->base.complete, req->base.data); |
296 | desc->tfm = tfm; | 300 | ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes, |
297 | desc->info = info; | 301 | iv); |
298 | 302 | ||
299 | return err; | 303 | return crypto_ablkcipher_encrypt(subreq); |
300 | } | 304 | } |
301 | 305 | ||
302 | static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm) | 306 | static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm) |
303 | { | 307 | { |
304 | struct crypto_instance *inst = (void *)tfm->__crt_alg; | 308 | struct crypto_instance *inst = (void *)tfm->__crt_alg; |
305 | struct crypto_spawn *spawn = crypto_instance_ctx(inst); | 309 | struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst); |
306 | struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); | 310 | struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); |
307 | struct crypto_blkcipher *cipher; | 311 | struct crypto_ablkcipher *cipher; |
312 | unsigned long align; | ||
308 | 313 | ||
309 | cipher = crypto_spawn_blkcipher(spawn); | 314 | cipher = crypto_spawn_skcipher(spawn); |
310 | if (IS_ERR(cipher)) | 315 | if (IS_ERR(cipher)) |
311 | return PTR_ERR(cipher); | 316 | return PTR_ERR(cipher); |
312 | 317 | ||
313 | ctx->child = cipher; | 318 | ctx->child = cipher; |
314 | 319 | ||
320 | align = crypto_tfm_alg_alignmask(tfm); | ||
321 | align &= ~(crypto_tfm_ctx_alignment() - 1); | ||
322 | tfm->crt_ablkcipher.reqsize = align + | ||
323 | sizeof(struct crypto_rfc3686_req_ctx) + | ||
324 | crypto_ablkcipher_reqsize(cipher); | ||
325 | |||
315 | return 0; | 326 | return 0; |
316 | } | 327 | } |
317 | 328 | ||
@@ -319,74 +330,110 @@ static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm) | |||
319 | { | 330 | { |
320 | struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); | 331 | struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm); |
321 | 332 | ||
322 | crypto_free_blkcipher(ctx->child); | 333 | crypto_free_ablkcipher(ctx->child); |
323 | } | 334 | } |
324 | 335 | ||
325 | static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb) | 336 | static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb) |
326 | { | 337 | { |
338 | struct crypto_attr_type *algt; | ||
327 | struct crypto_instance *inst; | 339 | struct crypto_instance *inst; |
328 | struct crypto_alg *alg; | 340 | struct crypto_alg *alg; |
341 | struct crypto_skcipher_spawn *spawn; | ||
342 | const char *cipher_name; | ||
329 | int err; | 343 | int err; |
330 | 344 | ||
331 | err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER); | 345 | algt = crypto_get_attr_type(tb); |
332 | if (err) | 346 | err = PTR_ERR(algt); |
347 | if (IS_ERR(algt)) | ||
333 | return ERR_PTR(err); | 348 | return ERR_PTR(err); |
334 | 349 | ||
335 | alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER, | 350 | if ((algt->type ^ CRYPTO_ALG_TYPE_BLKCIPHER) & algt->mask) |
336 | CRYPTO_ALG_TYPE_MASK); | 351 | return ERR_PTR(-EINVAL); |
337 | err = PTR_ERR(alg); | 352 | |
338 | if (IS_ERR(alg)) | 353 | cipher_name = crypto_attr_alg_name(tb[1]); |
354 | err = PTR_ERR(cipher_name); | ||
355 | if (IS_ERR(cipher_name)) | ||
339 | return ERR_PTR(err); | 356 | return ERR_PTR(err); |
340 | 357 | ||
358 | inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); | ||
359 | if (!inst) | ||
360 | return ERR_PTR(-ENOMEM); | ||
361 | |||
362 | spawn = crypto_instance_ctx(inst); | ||
363 | |||
364 | crypto_set_skcipher_spawn(spawn, inst); | ||
365 | err = crypto_grab_skcipher(spawn, cipher_name, 0, | ||
366 | crypto_requires_sync(algt->type, | ||
367 | algt->mask)); | ||
368 | if (err) | ||
369 | goto err_free_inst; | ||
370 | |||
371 | alg = crypto_skcipher_spawn_alg(spawn); | ||
372 | |||
341 | /* We only support 16-byte blocks. */ | 373 | /* We only support 16-byte blocks. */ |
342 | err = -EINVAL; | 374 | err = -EINVAL; |
343 | if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE) | 375 | if (alg->cra_ablkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE) |
344 | goto out_put_alg; | 376 | goto err_drop_spawn; |
345 | 377 | ||
346 | /* Not a stream cipher? */ | 378 | /* Not a stream cipher? */ |
347 | if (alg->cra_blocksize != 1) | 379 | if (alg->cra_blocksize != 1) |
348 | goto out_put_alg; | 380 | goto err_drop_spawn; |
349 | 381 | ||
350 | inst = crypto_alloc_instance("rfc3686", alg); | 382 | err = -ENAMETOOLONG; |
351 | if (IS_ERR(inst)) | 383 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "rfc3686(%s)", |
352 | goto out; | 384 | alg->cra_name) >= CRYPTO_MAX_ALG_NAME) |
385 | goto err_drop_spawn; | ||
386 | if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, | ||
387 | "rfc3686(%s)", alg->cra_driver_name) >= | ||
388 | CRYPTO_MAX_ALG_NAME) | ||
389 | goto err_drop_spawn; | ||
353 | 390 | ||
354 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; | ||
355 | inst->alg.cra_priority = alg->cra_priority; | 391 | inst->alg.cra_priority = alg->cra_priority; |
356 | inst->alg.cra_blocksize = 1; | 392 | inst->alg.cra_blocksize = 1; |
357 | inst->alg.cra_alignmask = alg->cra_alignmask; | 393 | inst->alg.cra_alignmask = alg->cra_alignmask; |
358 | inst->alg.cra_type = &crypto_blkcipher_type; | ||
359 | 394 | ||
360 | inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE; | 395 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | |
361 | inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize | 396 | (alg->cra_flags & CRYPTO_ALG_ASYNC); |
362 | + CTR_RFC3686_NONCE_SIZE; | 397 | inst->alg.cra_type = &crypto_ablkcipher_type; |
363 | inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize | 398 | |
364 | + CTR_RFC3686_NONCE_SIZE; | 399 | inst->alg.cra_ablkcipher.ivsize = CTR_RFC3686_IV_SIZE; |
400 | inst->alg.cra_ablkcipher.min_keysize = | ||
401 | alg->cra_ablkcipher.min_keysize + CTR_RFC3686_NONCE_SIZE; | ||
402 | inst->alg.cra_ablkcipher.max_keysize = | ||
403 | alg->cra_ablkcipher.max_keysize + CTR_RFC3686_NONCE_SIZE; | ||
365 | 404 | ||
366 | inst->alg.cra_blkcipher.geniv = "seqiv"; | 405 | inst->alg.cra_ablkcipher.geniv = "seqiv"; |
406 | |||
407 | inst->alg.cra_ablkcipher.setkey = crypto_rfc3686_setkey; | ||
408 | inst->alg.cra_ablkcipher.encrypt = crypto_rfc3686_crypt; | ||
409 | inst->alg.cra_ablkcipher.decrypt = crypto_rfc3686_crypt; | ||
367 | 410 | ||
368 | inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx); | 411 | inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx); |
369 | 412 | ||
370 | inst->alg.cra_init = crypto_rfc3686_init_tfm; | 413 | inst->alg.cra_init = crypto_rfc3686_init_tfm; |
371 | inst->alg.cra_exit = crypto_rfc3686_exit_tfm; | 414 | inst->alg.cra_exit = crypto_rfc3686_exit_tfm; |
372 | 415 | ||
373 | inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey; | ||
374 | inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt; | ||
375 | inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt; | ||
376 | |||
377 | out: | ||
378 | crypto_mod_put(alg); | ||
379 | return inst; | 416 | return inst; |
380 | 417 | ||
381 | out_put_alg: | 418 | err_drop_spawn: |
382 | inst = ERR_PTR(err); | 419 | crypto_drop_skcipher(spawn); |
383 | goto out; | 420 | err_free_inst: |
421 | kfree(inst); | ||
422 | return ERR_PTR(err); | ||
423 | } | ||
424 | |||
425 | static void crypto_rfc3686_free(struct crypto_instance *inst) | ||
426 | { | ||
427 | struct crypto_skcipher_spawn *spawn = crypto_instance_ctx(inst); | ||
428 | |||
429 | crypto_drop_skcipher(spawn); | ||
430 | kfree(inst); | ||
384 | } | 431 | } |
385 | 432 | ||
386 | static struct crypto_template crypto_rfc3686_tmpl = { | 433 | static struct crypto_template crypto_rfc3686_tmpl = { |
387 | .name = "rfc3686", | 434 | .name = "rfc3686", |
388 | .alloc = crypto_rfc3686_alloc, | 435 | .alloc = crypto_rfc3686_alloc, |
389 | .free = crypto_ctr_free, | 436 | .free = crypto_rfc3686_free, |
390 | .module = THIS_MODULE, | 437 | .module = THIS_MODULE, |
391 | }; | 438 | }; |
392 | 439 | ||
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 7ae2130e1b00..87ef7d66bc20 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c | |||
@@ -1591,6 +1591,10 @@ static int do_test(int m) | |||
1591 | speed_template_16_24_32); | 1591 | speed_template_16_24_32); |
1592 | test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0, | 1592 | test_acipher_speed("ofb(aes)", DECRYPT, sec, NULL, 0, |
1593 | speed_template_16_24_32); | 1593 | speed_template_16_24_32); |
1594 | test_acipher_speed("rfc3686(ctr(aes))", ENCRYPT, sec, NULL, 0, | ||
1595 | speed_template_20_28_36); | ||
1596 | test_acipher_speed("rfc3686(ctr(aes))", DECRYPT, sec, NULL, 0, | ||
1597 | speed_template_20_28_36); | ||
1594 | break; | 1598 | break; |
1595 | 1599 | ||
1596 | case 501: | 1600 | case 501: |
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index cd2068524f3f..ecdeeb1a7b05 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h | |||
@@ -51,6 +51,7 @@ static u8 speed_template_8_16[] = {8, 16, 0}; | |||
51 | static u8 speed_template_8_32[] = {8, 32, 0}; | 51 | static u8 speed_template_8_32[] = {8, 32, 0}; |
52 | static u8 speed_template_16_32[] = {16, 32, 0}; | 52 | static u8 speed_template_16_32[] = {16, 32, 0}; |
53 | static u8 speed_template_16_24_32[] = {16, 24, 32, 0}; | 53 | static u8 speed_template_16_24_32[] = {16, 24, 32, 0}; |
54 | static u8 speed_template_20_28_36[] = {20, 28, 36, 0}; | ||
54 | static u8 speed_template_32_40_48[] = {32, 40, 48, 0}; | 55 | static u8 speed_template_32_40_48[] = {32, 40, 48, 0}; |
55 | static u8 speed_template_32_48[] = {32, 48, 0}; | 56 | static u8 speed_template_32_48[] = {32, 48, 0}; |
56 | static u8 speed_template_32_48_64[] = {32, 48, 64, 0}; | 57 | static u8 speed_template_32_48_64[] = {32, 48, 64, 0}; |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 63445ede48bb..421f764794d5 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -557,10 +557,6 @@ struct xfrm_migrate { | |||
557 | }; | 557 | }; |
558 | 558 | ||
559 | #define XFRM_KM_TIMEOUT 30 | 559 | #define XFRM_KM_TIMEOUT 30 |
560 | /* which seqno */ | ||
561 | #define XFRM_REPLAY_SEQ 1 | ||
562 | #define XFRM_REPLAY_OSEQ 2 | ||
563 | #define XFRM_REPLAY_SEQ_MASK 3 | ||
564 | /* what happened */ | 560 | /* what happened */ |
565 | #define XFRM_REPLAY_UPDATE XFRM_AE_CR | 561 | #define XFRM_REPLAY_UPDATE XFRM_AE_CR |
566 | #define XFRM_REPLAY_TIMEOUT XFRM_AE_CE | 562 | #define XFRM_REPLAY_TIMEOUT XFRM_AE_CE |
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index fdfba235f9f1..b49eab89c9fd 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h | |||
@@ -278,6 +278,7 @@ enum | |||
278 | LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ | 278 | LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ |
279 | LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ | 279 | LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ |
280 | LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ | 280 | LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ |
281 | LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */ | ||
281 | __LINUX_MIB_XFRMMAX | 282 | __LINUX_MIB_XFRMMAX |
282 | }; | 283 | }; |
283 | 284 | ||
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 4ce2d93162c1..f9a549554740 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c | |||
@@ -700,8 +700,7 @@ void xfrm_probe_algs(void) | |||
700 | } | 700 | } |
701 | 701 | ||
702 | for (i = 0; i < ealg_entries(); i++) { | 702 | for (i = 0; i < ealg_entries(); i++) { |
703 | status = crypto_has_blkcipher(ealg_list[i].name, 0, | 703 | status = crypto_has_ablkcipher(ealg_list[i].name, 0, 0); |
704 | CRYPTO_ALG_ASYNC); | ||
705 | if (ealg_list[i].available != status) | 704 | if (ealg_list[i].available != status) |
706 | ealg_list[i].available = status; | 705 | ealg_list[i].available = status; |
707 | } | 706 | } |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 95a338c89f99..3670526e70b9 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -61,6 +61,12 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | spin_lock_bh(&x->lock); | 63 | spin_lock_bh(&x->lock); |
64 | |||
65 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | ||
66 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID); | ||
67 | goto error_nolock; | ||
68 | } | ||
69 | |||
64 | err = xfrm_state_check_expire(x); | 70 | err = xfrm_state_check_expire(x); |
65 | if (err) { | 71 | if (err) { |
66 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED); | 72 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED); |
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index d0a1af8ed584..603903853e89 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c | |||
@@ -43,6 +43,7 @@ static const struct snmp_mib xfrm_mib_list[] = { | |||
43 | SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD), | 43 | SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD), |
44 | SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR), | 44 | SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR), |
45 | SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR), | 45 | SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR), |
46 | SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID), | ||
46 | SNMP_MIB_SENTINEL | 47 | SNMP_MIB_SENTINEL |
47 | }; | 48 | }; |
48 | 49 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3459692092ec..0adae918a7a2 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -158,8 +158,8 @@ out_unlock: | |||
158 | mutex_unlock(&hash_resize_mutex); | 158 | mutex_unlock(&hash_resize_mutex); |
159 | } | 159 | } |
160 | 160 | ||
161 | static DEFINE_RWLOCK(xfrm_state_afinfo_lock); | 161 | static DEFINE_SPINLOCK(xfrm_state_afinfo_lock); |
162 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; | 162 | static struct xfrm_state_afinfo __rcu *xfrm_state_afinfo[NPROTO]; |
163 | 163 | ||
164 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); | 164 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); |
165 | 165 | ||
@@ -168,58 +168,45 @@ int __xfrm_state_delete(struct xfrm_state *x); | |||
168 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); | 168 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); |
169 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); | 169 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); |
170 | 170 | ||
171 | static struct xfrm_state_afinfo *xfrm_state_lock_afinfo(unsigned int family) | 171 | static DEFINE_SPINLOCK(xfrm_type_lock); |
172 | { | ||
173 | struct xfrm_state_afinfo *afinfo; | ||
174 | if (unlikely(family >= NPROTO)) | ||
175 | return NULL; | ||
176 | write_lock_bh(&xfrm_state_afinfo_lock); | ||
177 | afinfo = xfrm_state_afinfo[family]; | ||
178 | if (unlikely(!afinfo)) | ||
179 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
180 | return afinfo; | ||
181 | } | ||
182 | |||
183 | static void xfrm_state_unlock_afinfo(struct xfrm_state_afinfo *afinfo) | ||
184 | __releases(xfrm_state_afinfo_lock) | ||
185 | { | ||
186 | write_unlock_bh(&xfrm_state_afinfo_lock); | ||
187 | } | ||
188 | |||
189 | int xfrm_register_type(const struct xfrm_type *type, unsigned short family) | 172 | int xfrm_register_type(const struct xfrm_type *type, unsigned short family) |
190 | { | 173 | { |
191 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | 174 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
192 | const struct xfrm_type **typemap; | 175 | const struct xfrm_type **typemap; |
193 | int err = 0; | 176 | int err = 0; |
194 | 177 | ||
195 | if (unlikely(afinfo == NULL)) | 178 | if (unlikely(afinfo == NULL)) |
196 | return -EAFNOSUPPORT; | 179 | return -EAFNOSUPPORT; |
197 | typemap = afinfo->type_map; | 180 | typemap = afinfo->type_map; |
181 | spin_lock_bh(&xfrm_type_lock); | ||
198 | 182 | ||
199 | if (likely(typemap[type->proto] == NULL)) | 183 | if (likely(typemap[type->proto] == NULL)) |
200 | typemap[type->proto] = type; | 184 | typemap[type->proto] = type; |
201 | else | 185 | else |
202 | err = -EEXIST; | 186 | err = -EEXIST; |
203 | xfrm_state_unlock_afinfo(afinfo); | 187 | spin_unlock_bh(&xfrm_type_lock); |
188 | xfrm_state_put_afinfo(afinfo); | ||
204 | return err; | 189 | return err; |
205 | } | 190 | } |
206 | EXPORT_SYMBOL(xfrm_register_type); | 191 | EXPORT_SYMBOL(xfrm_register_type); |
207 | 192 | ||
208 | int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) | 193 | int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family) |
209 | { | 194 | { |
210 | struct xfrm_state_afinfo *afinfo = xfrm_state_lock_afinfo(family); | 195 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); |
211 | const struct xfrm_type **typemap; | 196 | const struct xfrm_type **typemap; |
212 | int err = 0; | 197 | int err = 0; |
213 | 198 | ||
214 | if (unlikely(afinfo == NULL)) | 199 | if (unlikely(afinfo == NULL)) |
215 | return -EAFNOSUPPORT; | 200 | return -EAFNOSUPPORT; |
216 | typemap = afinfo->type_map; | 201 | typemap = afinfo->type_map; |
202 | spin_lock_bh(&xfrm_type_lock); | ||
217 | 203 | ||
218 | if (unlikely(typemap[type->proto] != type)) | 204 | if (unlikely(typemap[type->proto] != type)) |
219 | err = -ENOENT; | 205 | err = -ENOENT; |
220 | else | 206 | else |
221 | typemap[type->proto] = NULL; | 207 | typemap[type->proto] = NULL; |
222 | xfrm_state_unlock_afinfo(afinfo); | 208 | spin_unlock_bh(&xfrm_type_lock); |
209 | xfrm_state_put_afinfo(afinfo); | ||
223 | return err; | 210 | return err; |
224 | } | 211 | } |
225 | EXPORT_SYMBOL(xfrm_unregister_type); | 212 | EXPORT_SYMBOL(xfrm_unregister_type); |
@@ -256,6 +243,7 @@ static void xfrm_put_type(const struct xfrm_type *type) | |||
256 | module_put(type->owner); | 243 | module_put(type->owner); |
257 | } | 244 | } |
258 | 245 | ||
246 | static DEFINE_SPINLOCK(xfrm_mode_lock); | ||
259 | int xfrm_register_mode(struct xfrm_mode *mode, int family) | 247 | int xfrm_register_mode(struct xfrm_mode *mode, int family) |
260 | { | 248 | { |
261 | struct xfrm_state_afinfo *afinfo; | 249 | struct xfrm_state_afinfo *afinfo; |
@@ -265,12 +253,13 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family) | |||
265 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | 253 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) |
266 | return -EINVAL; | 254 | return -EINVAL; |
267 | 255 | ||
268 | afinfo = xfrm_state_lock_afinfo(family); | 256 | afinfo = xfrm_state_get_afinfo(family); |
269 | if (unlikely(afinfo == NULL)) | 257 | if (unlikely(afinfo == NULL)) |
270 | return -EAFNOSUPPORT; | 258 | return -EAFNOSUPPORT; |
271 | 259 | ||
272 | err = -EEXIST; | 260 | err = -EEXIST; |
273 | modemap = afinfo->mode_map; | 261 | modemap = afinfo->mode_map; |
262 | spin_lock_bh(&xfrm_mode_lock); | ||
274 | if (modemap[mode->encap]) | 263 | if (modemap[mode->encap]) |
275 | goto out; | 264 | goto out; |
276 | 265 | ||
@@ -283,7 +272,8 @@ int xfrm_register_mode(struct xfrm_mode *mode, int family) | |||
283 | err = 0; | 272 | err = 0; |
284 | 273 | ||
285 | out: | 274 | out: |
286 | xfrm_state_unlock_afinfo(afinfo); | 275 | spin_unlock_bh(&xfrm_mode_lock); |
276 | xfrm_state_put_afinfo(afinfo); | ||
287 | return err; | 277 | return err; |
288 | } | 278 | } |
289 | EXPORT_SYMBOL(xfrm_register_mode); | 279 | EXPORT_SYMBOL(xfrm_register_mode); |
@@ -297,19 +287,21 @@ int xfrm_unregister_mode(struct xfrm_mode *mode, int family) | |||
297 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) | 287 | if (unlikely(mode->encap >= XFRM_MODE_MAX)) |
298 | return -EINVAL; | 288 | return -EINVAL; |
299 | 289 | ||
300 | afinfo = xfrm_state_lock_afinfo(family); | 290 | afinfo = xfrm_state_get_afinfo(family); |
301 | if (unlikely(afinfo == NULL)) | 291 | if (unlikely(afinfo == NULL)) |
302 | return -EAFNOSUPPORT; | 292 | return -EAFNOSUPPORT; |
303 | 293 | ||
304 | err = -ENOENT; | 294 | err = -ENOENT; |
305 | modemap = afinfo->mode_map; | 295 | modemap = afinfo->mode_map; |
296 | spin_lock_bh(&xfrm_mode_lock); | ||
306 | if (likely(modemap[mode->encap] == mode)) { | 297 | if (likely(modemap[mode->encap] == mode)) { |
307 | modemap[mode->encap] = NULL; | 298 | modemap[mode->encap] = NULL; |
308 | module_put(mode->afinfo->owner); | 299 | module_put(mode->afinfo->owner); |
309 | err = 0; | 300 | err = 0; |
310 | } | 301 | } |
311 | 302 | ||
312 | xfrm_state_unlock_afinfo(afinfo); | 303 | spin_unlock_bh(&xfrm_mode_lock); |
304 | xfrm_state_put_afinfo(afinfo); | ||
313 | return err; | 305 | return err; |
314 | } | 306 | } |
315 | EXPORT_SYMBOL(xfrm_unregister_mode); | 307 | EXPORT_SYMBOL(xfrm_unregister_mode); |
@@ -1370,9 +1362,6 @@ int xfrm_state_check_expire(struct xfrm_state *x) | |||
1370 | if (!x->curlft.use_time) | 1362 | if (!x->curlft.use_time) |
1371 | x->curlft.use_time = get_seconds(); | 1363 | x->curlft.use_time = get_seconds(); |
1372 | 1364 | ||
1373 | if (x->km.state != XFRM_STATE_VALID) | ||
1374 | return -EINVAL; | ||
1375 | |||
1376 | if (x->curlft.bytes >= x->lft.hard_byte_limit || | 1365 | if (x->curlft.bytes >= x->lft.hard_byte_limit || |
1377 | x->curlft.packets >= x->lft.hard_packet_limit) { | 1366 | x->curlft.packets >= x->lft.hard_packet_limit) { |
1378 | x->km.state = XFRM_STATE_EXPIRED; | 1367 | x->km.state = XFRM_STATE_EXPIRED; |
@@ -1648,27 +1637,26 @@ static void xfrm_replay_timer_handler(unsigned long data) | |||
1648 | } | 1637 | } |
1649 | 1638 | ||
1650 | static LIST_HEAD(xfrm_km_list); | 1639 | static LIST_HEAD(xfrm_km_list); |
1651 | static DEFINE_RWLOCK(xfrm_km_lock); | ||
1652 | 1640 | ||
1653 | void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) | 1641 | void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
1654 | { | 1642 | { |
1655 | struct xfrm_mgr *km; | 1643 | struct xfrm_mgr *km; |
1656 | 1644 | ||
1657 | read_lock(&xfrm_km_lock); | 1645 | rcu_read_lock(); |
1658 | list_for_each_entry(km, &xfrm_km_list, list) | 1646 | list_for_each_entry_rcu(km, &xfrm_km_list, list) |
1659 | if (km->notify_policy) | 1647 | if (km->notify_policy) |
1660 | km->notify_policy(xp, dir, c); | 1648 | km->notify_policy(xp, dir, c); |
1661 | read_unlock(&xfrm_km_lock); | 1649 | rcu_read_unlock(); |
1662 | } | 1650 | } |
1663 | 1651 | ||
1664 | void km_state_notify(struct xfrm_state *x, const struct km_event *c) | 1652 | void km_state_notify(struct xfrm_state *x, const struct km_event *c) |
1665 | { | 1653 | { |
1666 | struct xfrm_mgr *km; | 1654 | struct xfrm_mgr *km; |
1667 | read_lock(&xfrm_km_lock); | 1655 | rcu_read_lock(); |
1668 | list_for_each_entry(km, &xfrm_km_list, list) | 1656 | list_for_each_entry_rcu(km, &xfrm_km_list, list) |
1669 | if (km->notify) | 1657 | if (km->notify) |
1670 | km->notify(x, c); | 1658 | km->notify(x, c); |
1671 | read_unlock(&xfrm_km_lock); | 1659 | rcu_read_unlock(); |
1672 | } | 1660 | } |
1673 | 1661 | ||
1674 | EXPORT_SYMBOL(km_policy_notify); | 1662 | EXPORT_SYMBOL(km_policy_notify); |
@@ -1698,13 +1686,13 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) | |||
1698 | int err = -EINVAL, acqret; | 1686 | int err = -EINVAL, acqret; |
1699 | struct xfrm_mgr *km; | 1687 | struct xfrm_mgr *km; |
1700 | 1688 | ||
1701 | read_lock(&xfrm_km_lock); | 1689 | rcu_read_lock(); |
1702 | list_for_each_entry(km, &xfrm_km_list, list) { | 1690 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1703 | acqret = km->acquire(x, t, pol); | 1691 | acqret = km->acquire(x, t, pol); |
1704 | if (!acqret) | 1692 | if (!acqret) |
1705 | err = acqret; | 1693 | err = acqret; |
1706 | } | 1694 | } |
1707 | read_unlock(&xfrm_km_lock); | 1695 | rcu_read_unlock(); |
1708 | return err; | 1696 | return err; |
1709 | } | 1697 | } |
1710 | EXPORT_SYMBOL(km_query); | 1698 | EXPORT_SYMBOL(km_query); |
@@ -1714,14 +1702,14 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) | |||
1714 | int err = -EINVAL; | 1702 | int err = -EINVAL; |
1715 | struct xfrm_mgr *km; | 1703 | struct xfrm_mgr *km; |
1716 | 1704 | ||
1717 | read_lock(&xfrm_km_lock); | 1705 | rcu_read_lock(); |
1718 | list_for_each_entry(km, &xfrm_km_list, list) { | 1706 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1719 | if (km->new_mapping) | 1707 | if (km->new_mapping) |
1720 | err = km->new_mapping(x, ipaddr, sport); | 1708 | err = km->new_mapping(x, ipaddr, sport); |
1721 | if (!err) | 1709 | if (!err) |
1722 | break; | 1710 | break; |
1723 | } | 1711 | } |
1724 | read_unlock(&xfrm_km_lock); | 1712 | rcu_read_unlock(); |
1725 | return err; | 1713 | return err; |
1726 | } | 1714 | } |
1727 | EXPORT_SYMBOL(km_new_mapping); | 1715 | EXPORT_SYMBOL(km_new_mapping); |
@@ -1750,15 +1738,15 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
1750 | int ret; | 1738 | int ret; |
1751 | struct xfrm_mgr *km; | 1739 | struct xfrm_mgr *km; |
1752 | 1740 | ||
1753 | read_lock(&xfrm_km_lock); | 1741 | rcu_read_lock(); |
1754 | list_for_each_entry(km, &xfrm_km_list, list) { | 1742 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1755 | if (km->migrate) { | 1743 | if (km->migrate) { |
1756 | ret = km->migrate(sel, dir, type, m, num_migrate, k); | 1744 | ret = km->migrate(sel, dir, type, m, num_migrate, k); |
1757 | if (!ret) | 1745 | if (!ret) |
1758 | err = ret; | 1746 | err = ret; |
1759 | } | 1747 | } |
1760 | } | 1748 | } |
1761 | read_unlock(&xfrm_km_lock); | 1749 | rcu_read_unlock(); |
1762 | return err; | 1750 | return err; |
1763 | } | 1751 | } |
1764 | EXPORT_SYMBOL(km_migrate); | 1752 | EXPORT_SYMBOL(km_migrate); |
@@ -1770,15 +1758,15 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address | |||
1770 | int ret; | 1758 | int ret; |
1771 | struct xfrm_mgr *km; | 1759 | struct xfrm_mgr *km; |
1772 | 1760 | ||
1773 | read_lock(&xfrm_km_lock); | 1761 | rcu_read_lock(); |
1774 | list_for_each_entry(km, &xfrm_km_list, list) { | 1762 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1775 | if (km->report) { | 1763 | if (km->report) { |
1776 | ret = km->report(net, proto, sel, addr); | 1764 | ret = km->report(net, proto, sel, addr); |
1777 | if (!ret) | 1765 | if (!ret) |
1778 | err = ret; | 1766 | err = ret; |
1779 | } | 1767 | } |
1780 | } | 1768 | } |
1781 | read_unlock(&xfrm_km_lock); | 1769 | rcu_read_unlock(); |
1782 | return err; | 1770 | return err; |
1783 | } | 1771 | } |
1784 | EXPORT_SYMBOL(km_report); | 1772 | EXPORT_SYMBOL(km_report); |
@@ -1802,14 +1790,14 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen | |||
1802 | goto out; | 1790 | goto out; |
1803 | 1791 | ||
1804 | err = -EINVAL; | 1792 | err = -EINVAL; |
1805 | read_lock(&xfrm_km_lock); | 1793 | rcu_read_lock(); |
1806 | list_for_each_entry(km, &xfrm_km_list, list) { | 1794 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1807 | pol = km->compile_policy(sk, optname, data, | 1795 | pol = km->compile_policy(sk, optname, data, |
1808 | optlen, &err); | 1796 | optlen, &err); |
1809 | if (err >= 0) | 1797 | if (err >= 0) |
1810 | break; | 1798 | break; |
1811 | } | 1799 | } |
1812 | read_unlock(&xfrm_km_lock); | 1800 | rcu_read_unlock(); |
1813 | 1801 | ||
1814 | if (err >= 0) { | 1802 | if (err >= 0) { |
1815 | xfrm_sk_policy_insert(sk, err, pol); | 1803 | xfrm_sk_policy_insert(sk, err, pol); |
@@ -1823,20 +1811,23 @@ out: | |||
1823 | } | 1811 | } |
1824 | EXPORT_SYMBOL(xfrm_user_policy); | 1812 | EXPORT_SYMBOL(xfrm_user_policy); |
1825 | 1813 | ||
1814 | static DEFINE_SPINLOCK(xfrm_km_lock); | ||
1815 | |||
1826 | int xfrm_register_km(struct xfrm_mgr *km) | 1816 | int xfrm_register_km(struct xfrm_mgr *km) |
1827 | { | 1817 | { |
1828 | write_lock_bh(&xfrm_km_lock); | 1818 | spin_lock_bh(&xfrm_km_lock); |
1829 | list_add_tail(&km->list, &xfrm_km_list); | 1819 | list_add_tail_rcu(&km->list, &xfrm_km_list); |
1830 | write_unlock_bh(&xfrm_km_lock); | 1820 | spin_unlock_bh(&xfrm_km_lock); |
1831 | return 0; | 1821 | return 0; |
1832 | } | 1822 | } |
1833 | EXPORT_SYMBOL(xfrm_register_km); | 1823 | EXPORT_SYMBOL(xfrm_register_km); |
1834 | 1824 | ||
1835 | int xfrm_unregister_km(struct xfrm_mgr *km) | 1825 | int xfrm_unregister_km(struct xfrm_mgr *km) |
1836 | { | 1826 | { |
1837 | write_lock_bh(&xfrm_km_lock); | 1827 | spin_lock_bh(&xfrm_km_lock); |
1838 | list_del(&km->list); | 1828 | list_del_rcu(&km->list); |
1839 | write_unlock_bh(&xfrm_km_lock); | 1829 | spin_unlock_bh(&xfrm_km_lock); |
1830 | synchronize_rcu(); | ||
1840 | return 0; | 1831 | return 0; |
1841 | } | 1832 | } |
1842 | EXPORT_SYMBOL(xfrm_unregister_km); | 1833 | EXPORT_SYMBOL(xfrm_unregister_km); |
@@ -1848,12 +1839,12 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1848 | return -EINVAL; | 1839 | return -EINVAL; |
1849 | if (unlikely(afinfo->family >= NPROTO)) | 1840 | if (unlikely(afinfo->family >= NPROTO)) |
1850 | return -EAFNOSUPPORT; | 1841 | return -EAFNOSUPPORT; |
1851 | write_lock_bh(&xfrm_state_afinfo_lock); | 1842 | spin_lock_bh(&xfrm_state_afinfo_lock); |
1852 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) | 1843 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) |
1853 | err = -ENOBUFS; | 1844 | err = -ENOBUFS; |
1854 | else | 1845 | else |
1855 | xfrm_state_afinfo[afinfo->family] = afinfo; | 1846 | rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo); |
1856 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1847 | spin_unlock_bh(&xfrm_state_afinfo_lock); |
1857 | return err; | 1848 | return err; |
1858 | } | 1849 | } |
1859 | EXPORT_SYMBOL(xfrm_state_register_afinfo); | 1850 | EXPORT_SYMBOL(xfrm_state_register_afinfo); |
@@ -1865,14 +1856,15 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1865 | return -EINVAL; | 1856 | return -EINVAL; |
1866 | if (unlikely(afinfo->family >= NPROTO)) | 1857 | if (unlikely(afinfo->family >= NPROTO)) |
1867 | return -EAFNOSUPPORT; | 1858 | return -EAFNOSUPPORT; |
1868 | write_lock_bh(&xfrm_state_afinfo_lock); | 1859 | spin_lock_bh(&xfrm_state_afinfo_lock); |
1869 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { | 1860 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { |
1870 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) | 1861 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) |
1871 | err = -EINVAL; | 1862 | err = -EINVAL; |
1872 | else | 1863 | else |
1873 | xfrm_state_afinfo[afinfo->family] = NULL; | 1864 | RCU_INIT_POINTER(xfrm_state_afinfo[afinfo->family], NULL); |
1874 | } | 1865 | } |
1875 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1866 | spin_unlock_bh(&xfrm_state_afinfo_lock); |
1867 | synchronize_rcu(); | ||
1876 | return err; | 1868 | return err; |
1877 | } | 1869 | } |
1878 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); | 1870 | EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
@@ -1882,17 +1874,16 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) | |||
1882 | struct xfrm_state_afinfo *afinfo; | 1874 | struct xfrm_state_afinfo *afinfo; |
1883 | if (unlikely(family >= NPROTO)) | 1875 | if (unlikely(family >= NPROTO)) |
1884 | return NULL; | 1876 | return NULL; |
1885 | read_lock(&xfrm_state_afinfo_lock); | 1877 | rcu_read_lock(); |
1886 | afinfo = xfrm_state_afinfo[family]; | 1878 | afinfo = rcu_dereference(xfrm_state_afinfo[family]); |
1887 | if (unlikely(!afinfo)) | 1879 | if (unlikely(!afinfo)) |
1888 | read_unlock(&xfrm_state_afinfo_lock); | 1880 | rcu_read_unlock(); |
1889 | return afinfo; | 1881 | return afinfo; |
1890 | } | 1882 | } |
1891 | 1883 | ||
1892 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) | 1884 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo) |
1893 | __releases(xfrm_state_afinfo_lock) | ||
1894 | { | 1885 | { |
1895 | read_unlock(&xfrm_state_afinfo_lock); | 1886 | rcu_read_unlock(); |
1896 | } | 1887 | } |
1897 | 1888 | ||
1898 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ | 1889 | /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ |