diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-07 20:50:11 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-19 16:54:56 -0400 |
| commit | 7c67db3a8a98045744f06fcd6d8f476d9df0ba5c (patch) | |
| tree | 4d0041249b48f9ac66560550e0e96c9c86c37891 | |
| parent | 78ea323be6380a9313e87fe241809e912e8ae401 (diff) | |
NFSv4: Reintroduce machine creds
We need to try to ensure that we always use the same credentials whenever
we re-establish the clientid on the server. If not, the server won't
recognise that we're the same client, and so may not allow us to recover
state.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | fs/nfs/client.c | 7 | ||||
| -rw-r--r-- | include/linux/nfs_fs_sb.h | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/auth.h | 2 | ||||
| -rw-r--r-- | include/linux/sunrpc/auth_gss.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth_generic.c | 26 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 12 |
6 files changed, 47 insertions, 3 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 93dfd75aba7c..f2f3b284e6dd 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -112,6 +112,7 @@ struct nfs_client_initdata { | |||
| 112 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) | 112 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
| 113 | { | 113 | { |
| 114 | struct nfs_client *clp; | 114 | struct nfs_client *clp; |
| 115 | struct rpc_cred *cred; | ||
| 115 | 116 | ||
| 116 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | 117 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
| 117 | goto error_0; | 118 | goto error_0; |
| @@ -150,6 +151,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
| 150 | clp->cl_boot_time = CURRENT_TIME; | 151 | clp->cl_boot_time = CURRENT_TIME; |
| 151 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 152 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
| 152 | #endif | 153 | #endif |
| 154 | cred = rpc_lookup_machine_cred(); | ||
| 155 | if (!IS_ERR(cred)) | ||
| 156 | clp->cl_machine_cred = cred; | ||
| 153 | 157 | ||
| 154 | return clp; | 158 | return clp; |
| 155 | 159 | ||
| @@ -191,6 +195,9 @@ static void nfs_free_client(struct nfs_client *clp) | |||
| 191 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | 195 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) |
| 192 | nfs_callback_down(); | 196 | nfs_callback_down(); |
| 193 | 197 | ||
| 198 | if (clp->cl_machine_cred != NULL) | ||
| 199 | put_rpccred(clp->cl_machine_cred); | ||
| 200 | |||
| 194 | kfree(clp->cl_hostname); | 201 | kfree(clp->cl_hostname); |
| 195 | kfree(clp); | 202 | kfree(clp); |
| 196 | 203 | ||
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index ac7e4fb943ea..c9beacd16c00 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
| @@ -32,6 +32,8 @@ struct nfs_client { | |||
| 32 | const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ | 32 | const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ |
| 33 | int cl_proto; /* Network transport protocol */ | 33 | int cl_proto; /* Network transport protocol */ |
| 34 | 34 | ||
| 35 | struct rpc_cred *cl_machine_cred; | ||
| 36 | |||
| 35 | #ifdef CONFIG_NFS_V4 | 37 | #ifdef CONFIG_NFS_V4 |
| 36 | u64 cl_clientid; /* constant */ | 38 | u64 cl_clientid; /* constant */ |
| 37 | nfs4_verifier cl_confirm; | 39 | nfs4_verifier cl_confirm; |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index a19c3af933ca..3f632182d8eb 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
| @@ -26,6 +26,7 @@ struct auth_cred { | |||
| 26 | uid_t uid; | 26 | uid_t uid; |
| 27 | gid_t gid; | 27 | gid_t gid; |
| 28 | struct group_info *group_info; | 28 | struct group_info *group_info; |
| 29 | unsigned char machine_cred : 1; | ||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | /* | 32 | /* |
| @@ -130,6 +131,7 @@ void __exit rpcauth_remove_module(void); | |||
| 130 | void __exit rpc_destroy_generic_auth(void); | 131 | void __exit rpc_destroy_generic_auth(void); |
| 131 | 132 | ||
| 132 | struct rpc_cred * rpc_lookup_cred(void); | 133 | struct rpc_cred * rpc_lookup_cred(void); |
| 134 | struct rpc_cred * rpc_lookup_machine_cred(void); | ||
| 133 | int rpcauth_register(const struct rpc_authops *); | 135 | int rpcauth_register(const struct rpc_authops *); |
| 134 | int rpcauth_unregister(const struct rpc_authops *); | 136 | int rpcauth_unregister(const struct rpc_authops *); |
| 135 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); | 137 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); |
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h index 67658e17a375..fec6899bf355 100644 --- a/include/linux/sunrpc/auth_gss.h +++ b/include/linux/sunrpc/auth_gss.h | |||
| @@ -84,6 +84,7 @@ struct gss_cred { | |||
| 84 | enum rpc_gss_svc gc_service; | 84 | enum rpc_gss_svc gc_service; |
| 85 | struct gss_cl_ctx *gc_ctx; | 85 | struct gss_cl_ctx *gc_ctx; |
| 86 | struct gss_upcall_msg *gc_upcall; | 86 | struct gss_upcall_msg *gc_upcall; |
| 87 | unsigned char gc_machine_cred : 1; | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | #endif /* __KERNEL__ */ | 90 | #endif /* __KERNEL__ */ |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index b6f124c85072..d927d9f57412 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
| @@ -17,6 +17,9 @@ | |||
| 17 | # define RPCDBG_FACILITY RPCDBG_AUTH | 17 | # define RPCDBG_FACILITY RPCDBG_AUTH |
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | #define RPC_ANONYMOUS_USERID ((uid_t)-2) | ||
| 21 | #define RPC_ANONYMOUS_GROUPID ((gid_t)-2) | ||
| 22 | |||
| 20 | struct generic_cred { | 23 | struct generic_cred { |
| 21 | struct rpc_cred gc_base; | 24 | struct rpc_cred gc_base; |
| 22 | struct auth_cred acred; | 25 | struct auth_cred acred; |
| @@ -35,6 +38,22 @@ struct rpc_cred *rpc_lookup_cred(void) | |||
| 35 | } | 38 | } |
| 36 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); | 39 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); |
| 37 | 40 | ||
| 41 | /* | ||
| 42 | * Public call interface for looking up machine creds. | ||
| 43 | */ | ||
| 44 | struct rpc_cred *rpc_lookup_machine_cred(void) | ||
| 45 | { | ||
| 46 | struct auth_cred acred = { | ||
| 47 | .uid = RPC_ANONYMOUS_USERID, | ||
| 48 | .gid = RPC_ANONYMOUS_GROUPID, | ||
| 49 | .machine_cred = 1, | ||
| 50 | }; | ||
| 51 | |||
| 52 | dprintk("RPC: looking up machine cred\n"); | ||
| 53 | return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); | ||
| 56 | |||
| 38 | static void | 57 | static void |
| 39 | generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred) | 58 | generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred) |
| 40 | { | 59 | { |
| @@ -75,8 +94,10 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
| 75 | gcred->acred.group_info = acred->group_info; | 94 | gcred->acred.group_info = acred->group_info; |
| 76 | if (gcred->acred.group_info != NULL) | 95 | if (gcred->acred.group_info != NULL) |
| 77 | get_group_info(gcred->acred.group_info); | 96 | get_group_info(gcred->acred.group_info); |
| 97 | gcred->acred.machine_cred = acred->machine_cred; | ||
| 78 | 98 | ||
| 79 | dprintk("RPC: allocated generic cred %p for uid %d gid %d\n", | 99 | dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", |
| 100 | gcred->acred.machine_cred ? "machine" : "generic", | ||
| 80 | gcred, acred->uid, acred->gid); | 101 | gcred, acred->uid, acred->gid); |
| 81 | return &gcred->gc_base; | 102 | return &gcred->gc_base; |
| 82 | } | 103 | } |
| @@ -115,7 +136,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | |||
| 115 | 136 | ||
| 116 | if (gcred->acred.uid != acred->uid || | 137 | if (gcred->acred.uid != acred->uid || |
| 117 | gcred->acred.gid != acred->gid || | 138 | gcred->acred.gid != acred->gid || |
| 118 | gcred->acred.group_info != acred->group_info) | 139 | gcred->acred.group_info != acred->group_info || |
| 140 | gcred->acred.machine_cred != acred->machine_cred) | ||
| 119 | return 0; | 141 | return 0; |
| 120 | return 1; | 142 | return 1; |
| 121 | } | 143 | } |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 7567eb95823b..46f7ec800af9 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -371,9 +371,16 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid) | |||
| 371 | static struct gss_upcall_msg * | 371 | static struct gss_upcall_msg * |
| 372 | gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred) | 372 | gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred) |
| 373 | { | 373 | { |
| 374 | struct gss_cred *gss_cred = container_of(cred, | ||
| 375 | struct gss_cred, gc_base); | ||
| 374 | struct gss_upcall_msg *gss_new, *gss_msg; | 376 | struct gss_upcall_msg *gss_new, *gss_msg; |
| 377 | uid_t uid = cred->cr_uid; | ||
| 375 | 378 | ||
| 376 | gss_new = gss_alloc_msg(gss_auth, cred->cr_uid); | 379 | /* Special case: rpc.gssd assumes that uid == 0 implies machine creds */ |
| 380 | if (gss_cred->gc_machine_cred != 0) | ||
| 381 | uid = 0; | ||
| 382 | |||
| 383 | gss_new = gss_alloc_msg(gss_auth, uid); | ||
| 377 | if (gss_new == NULL) | 384 | if (gss_new == NULL) |
| 378 | return ERR_PTR(-ENOMEM); | 385 | return ERR_PTR(-ENOMEM); |
| 379 | gss_msg = gss_add_msg(gss_auth, gss_new); | 386 | gss_msg = gss_add_msg(gss_auth, gss_new); |
| @@ -818,6 +825,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
| 818 | */ | 825 | */ |
| 819 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; | 826 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; |
| 820 | cred->gc_service = gss_auth->service; | 827 | cred->gc_service = gss_auth->service; |
| 828 | cred->gc_machine_cred = acred->machine_cred; | ||
| 821 | kref_get(&gss_auth->kref); | 829 | kref_get(&gss_auth->kref); |
| 822 | return &cred->gc_base; | 830 | return &cred->gc_base; |
| 823 | 831 | ||
| @@ -855,6 +863,8 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | |||
| 855 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 863 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) |
| 856 | return 0; | 864 | return 0; |
| 857 | out: | 865 | out: |
| 866 | if (acred->machine_cred != gss_cred->gc_machine_cred) | ||
| 867 | return 0; | ||
| 858 | return (rc->cr_uid == acred->uid); | 868 | return (rc->cr_uid == acred->uid); |
| 859 | } | 869 | } |
| 860 | 870 | ||
