diff options
| -rw-r--r-- | fs/nfsd/Kconfig | 2 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 24 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 26 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 132 | ||||
| -rw-r--r-- | fs/nfsd/nfsfh.c | 8 | ||||
| -rw-r--r-- | include/linux/nfs4.h | 3 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_unseal.c | 8 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 10 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_upcall.c | 3 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 29 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 4 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 2 |
12 files changed, 146 insertions, 105 deletions
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index dc8f1ef665ce..f994e750e0d1 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
| @@ -95,7 +95,7 @@ config NFSD_V4_SECURITY_LABEL | |||
| 95 | Smack policies on NFSv4 files, say N. | 95 | Smack policies on NFSv4 files, say N. |
| 96 | 96 | ||
| 97 | WARNING: there is still a chance of backwards-incompatible protocol changes. | 97 | WARNING: there is still a chance of backwards-incompatible protocol changes. |
| 98 | For now we recommend "Y" only for developers and testers." | 98 | For now we recommend "Y" only for developers and testers. |
| 99 | 99 | ||
| 100 | config NFSD_FAULT_INJECTION | 100 | config NFSD_FAULT_INJECTION |
| 101 | bool "NFS server manual fault injection" | 101 | bool "NFS server manual fault injection" |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 5f38ea36e266..8513c598fabf 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
| @@ -536,16 +536,12 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
| 536 | if (err) | 536 | if (err) |
| 537 | goto out3; | 537 | goto out3; |
| 538 | exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); | 538 | exp.ex_anon_uid= make_kuid(&init_user_ns, an_int); |
| 539 | if (!uid_valid(exp.ex_anon_uid)) | ||
| 540 | goto out3; | ||
| 541 | 539 | ||
| 542 | /* anon gid */ | 540 | /* anon gid */ |
| 543 | err = get_int(&mesg, &an_int); | 541 | err = get_int(&mesg, &an_int); |
| 544 | if (err) | 542 | if (err) |
| 545 | goto out3; | 543 | goto out3; |
| 546 | exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); | 544 | exp.ex_anon_gid= make_kgid(&init_user_ns, an_int); |
| 547 | if (!gid_valid(exp.ex_anon_gid)) | ||
| 548 | goto out3; | ||
| 549 | 545 | ||
| 550 | /* fsid */ | 546 | /* fsid */ |
| 551 | err = get_int(&mesg, &an_int); | 547 | err = get_int(&mesg, &an_int); |
| @@ -583,6 +579,26 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
| 583 | exp.ex_uuid); | 579 | exp.ex_uuid); |
| 584 | if (err) | 580 | if (err) |
| 585 | goto out4; | 581 | goto out4; |
| 582 | /* | ||
| 583 | * No point caching this if it would immediately expire. | ||
| 584 | * Also, this protects exportfs's dummy export from the | ||
| 585 | * anon_uid/anon_gid checks: | ||
| 586 | */ | ||
| 587 | if (exp.h.expiry_time < seconds_since_boot()) | ||
| 588 | goto out4; | ||
| 589 | /* | ||
| 590 | * For some reason exportfs has been passing down an | ||
| 591 | * invalid (-1) uid & gid on the "dummy" export which it | ||
| 592 | * uses to test export support. To make sure exportfs | ||
| 593 | * sees errors from check_export we therefore need to | ||
| 594 | * delay these checks till after check_export: | ||
| 595 | */ | ||
| 596 | err = -EINVAL; | ||
| 597 | if (!uid_valid(exp.ex_anon_uid)) | ||
| 598 | goto out4; | ||
| 599 | if (!gid_valid(exp.ex_anon_gid)) | ||
| 600 | goto out4; | ||
| 601 | err = 0; | ||
| 586 | } | 602 | } |
| 587 | 603 | ||
| 588 | expp = svc_export_lookup(&exp); | 604 | expp = svc_export_lookup(&exp); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f36a30a9f2d1..105d6fa7c514 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -402,11 +402,16 @@ static void remove_stid(struct nfs4_stid *s) | |||
| 402 | idr_remove(stateids, s->sc_stateid.si_opaque.so_id); | 402 | idr_remove(stateids, s->sc_stateid.si_opaque.so_id); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | static void nfs4_free_stid(struct kmem_cache *slab, struct nfs4_stid *s) | ||
| 406 | { | ||
| 407 | kmem_cache_free(slab, s); | ||
| 408 | } | ||
| 409 | |||
| 405 | void | 410 | void |
| 406 | nfs4_put_delegation(struct nfs4_delegation *dp) | 411 | nfs4_put_delegation(struct nfs4_delegation *dp) |
| 407 | { | 412 | { |
| 408 | if (atomic_dec_and_test(&dp->dl_count)) { | 413 | if (atomic_dec_and_test(&dp->dl_count)) { |
| 409 | kmem_cache_free(deleg_slab, dp); | 414 | nfs4_free_stid(deleg_slab, &dp->dl_stid); |
| 410 | num_delegations--; | 415 | num_delegations--; |
| 411 | } | 416 | } |
| 412 | } | 417 | } |
| @@ -610,7 +615,7 @@ static void close_generic_stateid(struct nfs4_ol_stateid *stp) | |||
| 610 | static void free_generic_stateid(struct nfs4_ol_stateid *stp) | 615 | static void free_generic_stateid(struct nfs4_ol_stateid *stp) |
| 611 | { | 616 | { |
| 612 | remove_stid(&stp->st_stid); | 617 | remove_stid(&stp->st_stid); |
| 613 | kmem_cache_free(stateid_slab, stp); | 618 | nfs4_free_stid(stateid_slab, &stp->st_stid); |
| 614 | } | 619 | } |
| 615 | 620 | ||
| 616 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 621 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
| @@ -668,7 +673,6 @@ static void unhash_open_stateid(struct nfs4_ol_stateid *stp) | |||
| 668 | static void release_open_stateid(struct nfs4_ol_stateid *stp) | 673 | static void release_open_stateid(struct nfs4_ol_stateid *stp) |
| 669 | { | 674 | { |
| 670 | unhash_open_stateid(stp); | 675 | unhash_open_stateid(stp); |
| 671 | unhash_stid(&stp->st_stid); | ||
| 672 | free_generic_stateid(stp); | 676 | free_generic_stateid(stp); |
| 673 | } | 677 | } |
| 674 | 678 | ||
| @@ -690,7 +694,6 @@ static void release_last_closed_stateid(struct nfs4_openowner *oo) | |||
| 690 | struct nfs4_ol_stateid *s = oo->oo_last_closed_stid; | 694 | struct nfs4_ol_stateid *s = oo->oo_last_closed_stid; |
| 691 | 695 | ||
| 692 | if (s) { | 696 | if (s) { |
| 693 | unhash_stid(&s->st_stid); | ||
| 694 | free_generic_stateid(s); | 697 | free_generic_stateid(s); |
| 695 | oo->oo_last_closed_stid = NULL; | 698 | oo->oo_last_closed_stid = NULL; |
| 696 | } | 699 | } |
| @@ -1127,6 +1130,11 @@ destroy_client(struct nfs4_client *clp) | |||
| 1127 | dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); | 1130 | dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); |
| 1128 | destroy_delegation(dp); | 1131 | destroy_delegation(dp); |
| 1129 | } | 1132 | } |
| 1133 | list_splice_init(&clp->cl_revoked, &reaplist); | ||
| 1134 | while (!list_empty(&reaplist)) { | ||
| 1135 | dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); | ||
| 1136 | destroy_revoked_delegation(dp); | ||
| 1137 | } | ||
| 1130 | while (!list_empty(&clp->cl_openowners)) { | 1138 | while (!list_empty(&clp->cl_openowners)) { |
| 1131 | oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); | 1139 | oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); |
| 1132 | release_openowner(oo); | 1140 | release_openowner(oo); |
| @@ -3154,7 +3162,7 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, | |||
| 3154 | open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; | 3162 | open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; |
| 3155 | return; | 3163 | return; |
| 3156 | out_free: | 3164 | out_free: |
| 3157 | unhash_stid(&dp->dl_stid); | 3165 | remove_stid(&dp->dl_stid); |
| 3158 | nfs4_put_delegation(dp); | 3166 | nfs4_put_delegation(dp); |
| 3159 | out_no_deleg: | 3167 | out_no_deleg: |
| 3160 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; | 3168 | open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; |
| @@ -3995,10 +4003,9 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3995 | 4003 | ||
| 3996 | nfsd4_close_open_stateid(stp); | 4004 | nfsd4_close_open_stateid(stp); |
| 3997 | 4005 | ||
| 3998 | if (cstate->minorversion) { | 4006 | if (cstate->minorversion) |
| 3999 | unhash_stid(&stp->st_stid); | ||
| 4000 | free_generic_stateid(stp); | 4007 | free_generic_stateid(stp); |
| 4001 | } else | 4008 | else |
| 4002 | oo->oo_last_closed_stid = stp; | 4009 | oo->oo_last_closed_stid = stp; |
| 4003 | 4010 | ||
| 4004 | if (list_empty(&oo->oo_owner.so_stateids)) { | 4011 | if (list_empty(&oo->oo_owner.so_stateids)) { |
| @@ -5119,7 +5126,6 @@ out_recovery: | |||
| 5119 | return ret; | 5126 | return ret; |
| 5120 | } | 5127 | } |
| 5121 | 5128 | ||
| 5122 | /* should be called with the state lock held */ | ||
| 5123 | void | 5129 | void |
| 5124 | nfs4_state_shutdown_net(struct net *net) | 5130 | nfs4_state_shutdown_net(struct net *net) |
| 5125 | { | 5131 | { |
| @@ -5130,6 +5136,7 @@ nfs4_state_shutdown_net(struct net *net) | |||
| 5130 | cancel_delayed_work_sync(&nn->laundromat_work); | 5136 | cancel_delayed_work_sync(&nn->laundromat_work); |
| 5131 | locks_end_grace(&nn->nfsd4_manager); | 5137 | locks_end_grace(&nn->nfsd4_manager); |
| 5132 | 5138 | ||
| 5139 | nfs4_lock_state(); | ||
| 5133 | INIT_LIST_HEAD(&reaplist); | 5140 | INIT_LIST_HEAD(&reaplist); |
| 5134 | spin_lock(&recall_lock); | 5141 | spin_lock(&recall_lock); |
| 5135 | list_for_each_safe(pos, next, &nn->del_recall_lru) { | 5142 | list_for_each_safe(pos, next, &nn->del_recall_lru) { |
| @@ -5144,6 +5151,7 @@ nfs4_state_shutdown_net(struct net *net) | |||
