diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-13 12:51:02 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:33 -0400 |
commit | 1f4c86c0be9064ab4eebd9e67c84606c1cfeec4b (patch) | |
tree | 6ae9e8e6550f644335bbf6812edd7e6cfcde7e53 /net/sunrpc | |
parent | 8535b2be5181fc3019e4150567ef53210fe3b04f (diff) |
NFS: Don't use GFP_KERNEL in rpcsec_gss downcalls
Again, we can deadlock if the memory reclaim triggers a writeback that
requires a rpcsec_gss credential lookup.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_keys.c | 9 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 34 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 7 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_mech.c | 5 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 2 |
6 files changed, 32 insertions, 27 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6654c8534d32..48a7939dc9e2 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -229,7 +229,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
229 | p = ERR_PTR(-EFAULT); | 229 | p = ERR_PTR(-EFAULT); |
230 | goto err; | 230 | goto err; |
231 | } | 231 | } |
232 | ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx); | 232 | ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx, GFP_NOFS); |
233 | if (ret < 0) { | 233 | if (ret < 0) { |
234 | p = ERR_PTR(ret); | 234 | p = ERR_PTR(ret); |
235 | goto err; | 235 | goto err; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index 33b87f04b30b..76e42e6be755 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c | |||
@@ -150,7 +150,8 @@ static void krb5_nfold(u32 inbits, const u8 *in, | |||
150 | u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, | 150 | u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, |
151 | const struct xdr_netobj *inkey, | 151 | const struct xdr_netobj *inkey, |
152 | struct xdr_netobj *outkey, | 152 | struct xdr_netobj *outkey, |
153 | const struct xdr_netobj *in_constant) | 153 | const struct xdr_netobj *in_constant, |
154 | gfp_t gfp_mask) | ||
154 | { | 155 | { |
155 | size_t blocksize, keybytes, keylength, n; | 156 | size_t blocksize, keybytes, keylength, n; |
156 | unsigned char *inblockdata, *outblockdata, *rawkey; | 157 | unsigned char *inblockdata, *outblockdata, *rawkey; |
@@ -175,15 +176,15 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, | |||
175 | /* allocate and set up buffers */ | 176 | /* allocate and set up buffers */ |
176 | 177 | ||
177 | ret = ENOMEM; | 178 | ret = ENOMEM; |
178 | inblockdata = kmalloc(blocksize, GFP_KERNEL); | 179 | inblockdata = kmalloc(blocksize, gfp_mask); |
179 | if (inblockdata == NULL) | 180 | if (inblockdata == NULL) |
180 | goto err_free_cipher; | 181 | goto err_free_cipher; |
181 | 182 | ||
182 | outblockdata = kmalloc(blocksize, GFP_KERNEL); | 183 | outblockdata = kmalloc(blocksize, gfp_mask); |
183 | if (outblockdata == NULL) | 184 | if (outblockdata == NULL) |
184 | goto err_free_in; | 185 | goto err_free_in; |
185 | 186 | ||
186 | rawkey = kmalloc(keybytes, GFP_KERNEL); | 187 | rawkey = kmalloc(keybytes, gfp_mask); |
187 | if (rawkey == NULL) | 188 | if (rawkey == NULL) |
188 | goto err_free_out; | 189 | goto err_free_out; |
189 | 190 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 7c249a3f9a03..032644610524 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -369,7 +369,7 @@ set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | static int | 371 | static int |
372 | context_derive_keys_des3(struct krb5_ctx *ctx) | 372 | context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) |
373 | { | 373 | { |
374 | struct xdr_netobj c, keyin, keyout; | 374 | struct xdr_netobj c, keyin, keyout; |
375 | u8 cdata[GSS_KRB5_K5CLENGTH]; | 375 | u8 cdata[GSS_KRB5_K5CLENGTH]; |
@@ -396,7 +396,7 @@ context_derive_keys_des3(struct krb5_ctx *ctx) | |||
396 | /* derive cksum */ | 396 | /* derive cksum */ |
397 | set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM); | 397 | set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM); |
398 | keyout.data = ctx->cksum; | 398 | keyout.data = ctx->cksum; |
399 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 399 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
400 | if (err) { | 400 | if (err) { |
401 | dprintk("%s: Error %d deriving cksum key\n", | 401 | dprintk("%s: Error %d deriving cksum key\n", |
402 | __func__, err); | 402 | __func__, err); |
@@ -487,7 +487,7 @@ out_err: | |||
487 | } | 487 | } |
488 | 488 | ||
489 | static int | 489 | static int |
490 | context_derive_keys_new(struct krb5_ctx *ctx) | 490 | context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) |
491 | { | 491 | { |
492 | struct xdr_netobj c, keyin, keyout; | 492 | struct xdr_netobj c, keyin, keyout; |
493 | u8 cdata[GSS_KRB5_K5CLENGTH]; | 493 | u8 cdata[GSS_KRB5_K5CLENGTH]; |
@@ -503,7 +503,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
503 | /* initiator seal encryption */ | 503 | /* initiator seal encryption */ |
504 | set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); | 504 | set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); |
505 | keyout.data = ctx->initiator_seal; | 505 | keyout.data = ctx->initiator_seal; |
506 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 506 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
507 | if (err) { | 507 | if (err) { |
508 | dprintk("%s: Error %d deriving initiator_seal key\n", | 508 | dprintk("%s: Error %d deriving initiator_seal key\n", |
509 | __func__, err); | 509 | __func__, err); |
@@ -518,7 +518,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
518 | /* acceptor seal encryption */ | 518 | /* acceptor seal encryption */ |
519 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); | 519 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); |
520 | keyout.data = ctx->acceptor_seal; | 520 | keyout.data = ctx->acceptor_seal; |
521 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 521 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
522 | if (err) { | 522 | if (err) { |
523 | dprintk("%s: Error %d deriving acceptor_seal key\n", | 523 | dprintk("%s: Error %d deriving acceptor_seal key\n", |
524 | __func__, err); | 524 | __func__, err); |
@@ -533,7 +533,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
533 | /* initiator sign checksum */ | 533 | /* initiator sign checksum */ |
534 | set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM); | 534 | set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM); |
535 | keyout.data = ctx->initiator_sign; | 535 | keyout.data = ctx->initiator_sign; |
536 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 536 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
537 | if (err) { | 537 | if (err) { |
538 | dprintk("%s: Error %d deriving initiator_sign key\n", | 538 | dprintk("%s: Error %d deriving initiator_sign key\n", |
539 | __func__, err); | 539 | __func__, err); |
@@ -543,7 +543,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
543 | /* acceptor sign checksum */ | 543 | /* acceptor sign checksum */ |
544 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM); | 544 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM); |
545 | keyout.data = ctx->acceptor_sign; | 545 | keyout.data = ctx->acceptor_sign; |
546 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 546 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
547 | if (err) { | 547 | if (err) { |
548 | dprintk("%s: Error %d deriving acceptor_sign key\n", | 548 | dprintk("%s: Error %d deriving acceptor_sign key\n", |
549 | __func__, err); | 549 | __func__, err); |
@@ -553,7 +553,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
553 | /* initiator seal integrity */ | 553 | /* initiator seal integrity */ |
554 | set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY); | 554 | set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY); |
555 | keyout.data = ctx->initiator_integ; | 555 | keyout.data = ctx->initiator_integ; |
556 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 556 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
557 | if (err) { | 557 | if (err) { |
558 | dprintk("%s: Error %d deriving initiator_integ key\n", | 558 | dprintk("%s: Error %d deriving initiator_integ key\n", |
559 | __func__, err); | 559 | __func__, err); |
@@ -563,7 +563,7 @@ context_derive_keys_new(struct krb5_ctx *ctx) | |||
563 | /* acceptor seal integrity */ | 563 | /* acceptor seal integrity */ |
564 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY); | 564 | set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY); |
565 | keyout.data = ctx->acceptor_integ; | 565 | keyout.data = ctx->acceptor_integ; |
566 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c); | 566 | err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); |
567 | if (err) { | 567 | if (err) { |
568 | dprintk("%s: Error %d deriving acceptor_integ key\n", | 568 | dprintk("%s: Error %d deriving acceptor_integ key\n", |
569 | __func__, err); | 569 | __func__, err); |
@@ -598,7 +598,8 @@ out_err: | |||
598 | } | 598 | } |
599 | 599 | ||
600 | static int | 600 | static int |
601 | gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx) | 601 | gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, |
602 | gfp_t gfp_mask) | ||
602 | { | 603 | { |
603 | int keylen; | 604 | int keylen; |
604 | 605 | ||
@@ -645,7 +646,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
645 | } | 646 | } |
646 | 647 | ||
647 | ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data, | 648 | ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data, |
648 | gss_kerberos_mech.gm_oid.len, GFP_KERNEL); | 649 | gss_kerberos_mech.gm_oid.len, gfp_mask); |
649 | if (unlikely(ctx->mech_used.data == NULL)) { | 650 | if (unlikely(ctx->mech_used.data == NULL)) { |
650 | p = ERR_PTR(-ENOMEM); | 651 | p = ERR_PTR(-ENOMEM); |
651 | goto out_err; | 652 | goto out_err; |
@@ -654,12 +655,12 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
654 | 655 | ||
655 | switch (ctx->enctype) { | 656 | switch (ctx->enctype) { |
656 | case ENCTYPE_DES3_CBC_RAW: | 657 | case ENCTYPE_DES3_CBC_RAW: |
657 | return context_derive_keys_des3(ctx); | 658 | return context_derive_keys_des3(ctx, gfp_mask); |
658 | case ENCTYPE_ARCFOUR_HMAC: | 659 | case ENCTYPE_ARCFOUR_HMAC: |
659 | return context_derive_keys_rc4(ctx); | 660 | return context_derive_keys_rc4(ctx); |
660 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: | 661 | case ENCTYPE_AES128_CTS_HMAC_SHA1_96: |
661 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: | 662 | case ENCTYPE_AES256_CTS_HMAC_SHA1_96: |
662 | return context_derive_keys_new(ctx); | 663 | return context_derive_keys_new(ctx, gfp_mask); |
663 | default: | 664 | default: |
664 | return -EINVAL; | 665 | return -EINVAL; |
665 | } | 666 | } |
@@ -670,20 +671,21 @@ out_err: | |||
670 | 671 | ||
671 | static int | 672 | static int |
672 | gss_import_sec_context_kerberos(const void *p, size_t len, | 673 | gss_import_sec_context_kerberos(const void *p, size_t len, |
673 | struct gss_ctx *ctx_id) | 674 | struct gss_ctx *ctx_id, |
675 | gfp_t gfp_mask) | ||
674 | { | 676 | { |
675 | const void *end = (const void *)((const char *)p + len); | 677 | const void *end = (const void *)((const char *)p + len); |
676 | struct krb5_ctx *ctx; | 678 | struct krb5_ctx *ctx; |
677 | int ret; | 679 | int ret; |
678 | 680 | ||
679 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | 681 | ctx = kzalloc(sizeof(*ctx), gfp_mask); |
680 | if (ctx == NULL) | 682 | if (ctx == NULL) |
681 | return -ENOMEM; | 683 | return -ENOMEM; |
682 | 684 | ||
683 | if (len == 85) | 685 | if (len == 85) |
684 | ret = gss_import_v1_context(p, end, ctx); | 686 | ret = gss_import_v1_context(p, end, ctx); |
685 | else | 687 | else |
686 | ret = gss_import_v2_context(p, end, ctx); | 688 | ret = gss_import_v2_context(p, end, ctx, gfp_mask); |
687 | 689 | ||
688 | if (ret == 0) | 690 | if (ret == 0) |
689 | ctx_id->internal_ctx_id = ctx; | 691 | ctx_id->internal_ctx_id = ctx; |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 28a84ef41d13..2689de39dc78 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -249,14 +249,15 @@ EXPORT_SYMBOL_GPL(gss_mech_put); | |||
249 | int | 249 | int |
250 | gss_import_sec_context(const void *input_token, size_t bufsize, | 250 | gss_import_sec_context(const void *input_token, size_t bufsize, |
251 | struct gss_api_mech *mech, | 251 | struct gss_api_mech *mech, |
252 | struct gss_ctx **ctx_id) | 252 | struct gss_ctx **ctx_id, |
253 | gfp_t gfp_mask) | ||
253 | { | 254 | { |
254 | if (!(*ctx_id = kzalloc(sizeof(**ctx_id), GFP_KERNEL))) | 255 | if (!(*ctx_id = kzalloc(sizeof(**ctx_id), gfp_mask))) |
255 | return -ENOMEM; | 256 | return -ENOMEM; |
256 | (*ctx_id)->mech_type = gss_mech_get(mech); | 257 | (*ctx_id)->mech_type = gss_mech_get(mech); |
257 | 258 | ||
258 | return mech->gm_ops | 259 | return mech->gm_ops |
259 | ->gss_import_sec_context(input_token, bufsize, *ctx_id); | 260 | ->gss_import_sec_context(input_token, bufsize, *ctx_id, gfp_mask); |
260 | } | 261 | } |
261 | 262 | ||
262 | /* gss_get_mic: compute a mic over message and return mic_token. */ | 263 | /* gss_get_mic: compute a mic over message and return mic_token. */ |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index 035e1dd6af1b..dc3f1f5ed865 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
@@ -84,13 +84,14 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) | |||
84 | 84 | ||
85 | static int | 85 | static int |
86 | gss_import_sec_context_spkm3(const void *p, size_t len, | 86 | gss_import_sec_context_spkm3(const void *p, size_t len, |
87 | struct gss_ctx *ctx_id) | 87 | struct gss_ctx *ctx_id, |
88 | gfp_t gfp_mask) | ||
88 | { | 89 | { |
89 | const void *end = (const void *)((const char *)p + len); | 90 | const void *end = (const void *)((const char *)p + len); |
90 | struct spkm3_ctx *ctx; | 91 | struct spkm3_ctx *ctx; |
91 | int version; | 92 | int version; |
92 | 93 | ||
93 | if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS))) | 94 | if (!(ctx = kzalloc(sizeof(*ctx), gfp_mask))) |
94 | goto out_err; | 95 | goto out_err; |
95 | 96 | ||
96 | p = simple_get_bytes(p, end, &version, sizeof(version)); | 97 | p = simple_get_bytes(p, end, &version, sizeof(version)); |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 1d9ac4ac818a..cc385b3a59c2 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -494,7 +494,7 @@ static int rsc_parse(struct cache_detail *cd, | |||
494 | len = qword_get(&mesg, buf, mlen); | 494 | len = qword_get(&mesg, buf, mlen); |
495 | if (len < 0) | 495 | if (len < 0) |
496 | goto out; | 496 | goto out; |
497 | status = gss_import_sec_context(buf, len, gm, &rsci.mechctx); | 497 | status = gss_import_sec_context(buf, len, gm, &rsci.mechctx, GFP_KERNEL); |
498 | if (status) | 498 | if (status) |
499 | goto out; | 499 | goto out; |
500 | 500 | ||