diff options
author | NeilBrown <neilb@suse.com> | 2018-12-02 19:30:30 -0500 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2018-12-19 13:52:45 -0500 |
commit | 5e16923b432bfe79fdfb7cd95ed8e63f6438b663 (patch) | |
tree | 92c842d96a8cacdead34c4f260bd371077f06793 | |
parent | ecd5f97e1c7cd6124e3c3053beb5f2239aeacf8e (diff) |
NFS/SUNRPC: don't lookup machine credential until rpcauth_bindcred().
When NFS creates a machine credential, it is a "generic" credential,
not tied to any auth protocol, and is really just a container for
the princpal name.
This doesn't get linked to a genuine credential until rpcauth_bindcred()
is called.
The lookup always succeeds, so various places that test if the machine
credential is NULL, are pointless.
As a step towards getting rid of generic credentials, this patch gets
rid of generic machine credentials. The nfs_client and rpc_client
just hold a pointer to a constant principal name.
When a machine credential is wanted, a special static 'struct rpc_cred'
pointer is used. rpcauth_bindcred() recognizes this, finds the
principal from the client, and binds the correct credential.
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | fs/nfs/client.c | 11 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 9 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 21 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 12 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 3 | ||||
-rw-r--r-- | include/linux/sunrpc/auth.h | 3 | ||||
-rw-r--r-- | include/linux/sunrpc/clnt.h | 1 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 42 | ||||
-rw-r--r-- | net/sunrpc/auth_generic.c | 21 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 1 |
10 files changed, 55 insertions, 69 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index cce151776709..fb1cf1a4bda2 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -151,7 +151,6 @@ EXPORT_SYMBOL_GPL(unregister_nfs_version); | |||
151 | struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) | 151 | struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
152 | { | 152 | { |
153 | struct nfs_client *clp; | 153 | struct nfs_client *clp; |
154 | struct rpc_cred *cred; | ||
155 | int err = -ENOMEM; | 154 | int err = -ENOMEM; |
156 | 155 | ||
157 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) | 156 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
@@ -182,9 +181,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) | |||
182 | clp->cl_proto = cl_init->proto; | 181 | clp->cl_proto = cl_init->proto; |
183 | clp->cl_net = get_net(cl_init->net); | 182 | clp->cl_net = get_net(cl_init->net); |
184 | 183 | ||
185 | cred = rpc_lookup_machine_cred("*"); | 184 | clp->cl_principal = "*"; |
186 | if (!IS_ERR(cred)) | ||
187 | clp->cl_machine_cred = cred; | ||
188 | nfs_fscache_get_client_cookie(clp); | 185 | nfs_fscache_get_client_cookie(clp); |
189 | 186 | ||
190 | return clp; | 187 | return clp; |
@@ -246,11 +243,6 @@ void nfs_free_client(struct nfs_client *clp) | |||
246 | if (!IS_ERR(clp->cl_rpcclient)) | 243 | if (!IS_ERR(clp->cl_rpcclient)) |
247 | rpc_shutdown_client(clp->cl_rpcclient); | 244 | rpc_shutdown_client(clp->cl_rpcclient); |
248 | 245 | ||
249 | if (clp->cl_machine_cred != NULL) | ||
250 | put_rpccred(clp->cl_machine_cred); | ||
251 | if (clp->cl_root_cred != NULL) | ||
252 | put_rpccred(clp->cl_root_cred); | ||
253 | |||
254 | put_net(clp->cl_net); | 246 | put_net(clp->cl_net); |
255 | put_nfs_version(clp->cl_nfs_mod); | 247 | put_nfs_version(clp->cl_nfs_mod); |
256 | kfree(clp->cl_hostname); | 248 | kfree(clp->cl_hostname); |
@@ -529,6 +521,7 @@ int nfs_create_rpc_client(struct nfs_client *clp, | |||
529 | return PTR_ERR(clnt); | 521 | return PTR_ERR(clnt); |
530 | } | 522 | } |
531 | 523 | ||
524 | clnt->cl_principal = clp->cl_principal; | ||
532 | clp->cl_rpcclient = clnt; | 525 | clp->cl_rpcclient = clnt; |
533 | return 0; | 526 | return 0; |
534 | } | 527 | } |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ad649a49822f..eab41490ce58 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -338,7 +338,6 @@ static inline bool | |||
338 | _nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, | 338 | _nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, |
339 | struct rpc_clnt **clntp, struct rpc_message *msg) | 339 | struct rpc_clnt **clntp, struct rpc_message *msg) |
340 | { | 340 | { |
341 | struct rpc_cred *newcred = NULL; | ||
342 | rpc_authflavor_t flavor; | 341 | rpc_authflavor_t flavor; |
343 | 342 | ||
344 | if (sp4_mode == NFS_SP4_MACH_CRED_CLEANUP || | 343 | if (sp4_mode == NFS_SP4_MACH_CRED_CLEANUP || |
@@ -353,13 +352,7 @@ _nfs4_state_protect(struct nfs_client *clp, unsigned long sp4_mode, | |||
353 | return false; | 352 | return false; |
354 | } | 353 | } |
355 | if (test_bit(sp4_mode, &clp->cl_sp4_flags)) { | 354 | if (test_bit(sp4_mode, &clp->cl_sp4_flags)) { |
356 | spin_lock(&clp->cl_lock); | 355 | msg->rpc_cred = rpc_machine_cred(); |
357 | if (clp->cl_machine_cred != NULL) | ||
358 | /* don't call get_rpccred on the machine cred - | ||
359 | * a reference will be held for life of clp */ | ||
360 | newcred = clp->cl_machine_cred; | ||
361 | spin_unlock(&clp->cl_lock); | ||
362 | msg->rpc_cred = newcred; | ||
363 | 356 | ||
364 | flavor = clp->cl_rpcclient->cl_auth->au_flavor; | 357 | flavor = clp->cl_rpcclient->cl_auth->au_flavor; |
365 | WARN_ON_ONCE(flavor != RPC_AUTH_GSS_KRB5I && | 358 | WARN_ON_ONCE(flavor != RPC_AUTH_GSS_KRB5I && |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f142fca6995b..6304c79dbcd1 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -166,28 +166,15 @@ out: | |||
166 | 166 | ||
167 | struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp) | 167 | struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp) |
168 | { | 168 | { |
169 | struct rpc_cred *cred = clp->cl_root_cred; | 169 | return get_rpccred(rpc_machine_cred()); |
170 | |||
171 | if (!cred) | ||
172 | cred = clp->cl_machine_cred; | ||
173 | if (cred) | ||
174 | return get_rpccred(cred); | ||
175 | return cred; | ||
176 | } | 170 | } |
177 | 171 | ||
178 | static void nfs4_root_machine_cred(struct nfs_client *clp) | 172 | static void nfs4_root_machine_cred(struct nfs_client *clp) |
179 | { | 173 | { |
180 | struct rpc_cred *new; | ||
181 | 174 | ||
182 | new = rpc_lookup_machine_cred(NULL); | 175 | /* Force root creds instead of machine */ |
183 | spin_lock(&clp->cl_lock); | 176 | clp->cl_principal = NULL; |
184 | if (clp->cl_root_cred == NULL) { | 177 | clp->cl_rpcclient->cl_principal = NULL; |
185 | clp->cl_root_cred = new; | ||
186 | new = NULL; | ||
187 | } | ||
188 | spin_unlock(&clp->cl_lock); | ||
189 | if (new != NULL) | ||
190 | put_rpccred(new); | ||
191 | } | 178 | } |
192 | 179 | ||
193 | static struct rpc_cred * | 180 | static struct rpc_cred * |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index c032e4c24a8d..1dcee1fd32d9 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -847,14 +847,10 @@ static int max_cb_time(struct net *net) | |||
847 | static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) | 847 | static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) |
848 | { | 848 | { |
849 | if (clp->cl_minorversion == 0) { | 849 | if (clp->cl_minorversion == 0) { |
850 | char *principal = clp->cl_cred.cr_targ_princ ? | 850 | client->cl_principal = clp->cl_cred.cr_targ_princ ? |
851 | clp->cl_cred.cr_targ_princ : "nfs"; | 851 | clp->cl_cred.cr_targ_princ : "nfs"; |
852 | struct rpc_cred *cred; | 852 | |
853 | 853 | return get_rpccred(rpc_machine_cred()); | |
854 | cred = rpc_lookup_machine_cred(principal); | ||
855 | if (!IS_ERR(cred)) | ||
856 | get_rpccred(cred); | ||
857 | return cred; | ||
858 | } else { | 854 | } else { |
859 | struct rpc_auth *auth = client->cl_auth; | 855 | struct rpc_auth *auth = client->cl_auth; |
860 | struct auth_cred acred = {}; | 856 | struct auth_cred acred = {}; |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index fea51b44fe50..6aa8cc83c3b6 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -58,8 +58,7 @@ struct nfs_client { | |||
58 | struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */ | 58 | struct nfs_subversion * cl_nfs_mod; /* pointer to nfs version module */ |
59 | 59 | ||
60 | u32 cl_minorversion;/* NFSv4 minorversion */ | 60 | u32 cl_minorversion;/* NFSv4 minorversion */ |
61 | struct rpc_cred *cl_machine_cred; | 61 | const char * cl_principal; /* used for machine cred */ |
62 | struct rpc_cred *cl_root_cred; /* Use when machine_cred is ineffective */ | ||
63 | 62 | ||
64 | #if IS_ENABLED(CONFIG_NFS_V4) | 63 | #if IS_ENABLED(CONFIG_NFS_V4) |
65 | struct list_head cl_ds_clients; /* auth flavor data servers */ | 64 | struct list_head cl_ds_clients; /* auth flavor data servers */ |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 1c0468f39479..28b34c740c43 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -75,6 +75,8 @@ struct rpc_cred { | |||
75 | #define RPCAUTH_CRED_HASHED 2 | 75 | #define RPCAUTH_CRED_HASHED 2 |
76 | #define RPCAUTH_CRED_NEGATIVE 3 | 76 | #define RPCAUTH_CRED_NEGATIVE 3 |
77 | 77 | ||
78 | struct rpc_cred *rpc_machine_cred(void); | ||
79 | |||
78 | /* rpc_auth au_flags */ | 80 | /* rpc_auth au_flags */ |
79 | #define RPCAUTH_AUTH_NO_CRKEY_TIMEOUT 0x0001 /* underlying cred has no key timeout */ | 81 | #define RPCAUTH_AUTH_NO_CRKEY_TIMEOUT 0x0001 /* underlying cred has no key timeout */ |
80 | 82 | ||
@@ -170,7 +172,6 @@ void rpc_destroy_authunix(void); | |||
170 | struct rpc_cred * rpc_lookup_cred(void); | 172 | struct rpc_cred * rpc_lookup_cred(void); |
171 | struct rpc_cred * rpc_lookup_cred_nonblock(void); | 173 | struct rpc_cred * rpc_lookup_cred_nonblock(void); |
172 | struct rpc_cred * rpc_lookup_generic_cred(struct auth_cred *, int, gfp_t); | 174 | struct rpc_cred * rpc_lookup_generic_cred(struct auth_cred *, int, gfp_t); |
173 | struct rpc_cred * rpc_lookup_machine_cred(const char *service_name); | ||
174 | int rpcauth_register(const struct rpc_authops *); | 175 | int rpcauth_register(const struct rpc_authops *); |
175 | int rpcauth_unregister(const struct rpc_authops *); | 176 | int rpcauth_unregister(const struct rpc_authops *); |
176 | struct rpc_auth * rpcauth_create(const struct rpc_auth_create_args *, | 177 | struct rpc_auth * rpcauth_create(const struct rpc_auth_create_args *, |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 73d5c4a870fa..fc6dfbf77a9d 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
@@ -66,6 +66,7 @@ struct rpc_clnt { | |||
66 | struct rpc_rtt cl_rtt_default; | 66 | struct rpc_rtt cl_rtt_default; |
67 | struct rpc_timeout cl_timeout_default; | 67 | struct rpc_timeout cl_timeout_default; |
68 | const struct rpc_program *cl_program; | 68 | const struct rpc_program *cl_program; |
69 | const char * cl_principal; /* use for machine cred */ | ||
69 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 70 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
70 | struct dentry *cl_debugfs; /* debugfs directory */ | 71 | struct dentry *cl_debugfs; /* debugfs directory */ |
71 | #endif | 72 | #endif |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 63e2d35c10d5..9e709dcc8c39 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -39,6 +39,20 @@ static const struct rpc_authops __rcu *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
39 | static LIST_HEAD(cred_unused); | 39 | static LIST_HEAD(cred_unused); |
40 | static unsigned long number_cred_unused; | 40 | static unsigned long number_cred_unused; |
41 | 41 | ||
42 | static struct rpc_cred machine_cred = { | ||
43 | .cr_count = REFCOUNT_INIT(1), | ||
44 | }; | ||
45 | |||
46 | /* | ||
47 | * Return the machine_cred pointer to be used whenever | ||
48 | * the a generic machine credential is needed. | ||
49 | */ | ||
50 | struct rpc_cred *rpc_machine_cred(void) | ||
51 | { | ||
52 | return &machine_cred; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(rpc_machine_cred); | ||
55 | |||
42 | #define MAX_HASHTABLE_BITS (14) | 56 | #define MAX_HASHTABLE_BITS (14) |
43 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 57 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
44 | { | 58 | { |
@@ -703,6 +717,22 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | |||
703 | } | 717 | } |
704 | 718 | ||
705 | static struct rpc_cred * | 719 | static struct rpc_cred * |
720 | rpcauth_bind_machine_cred(struct rpc_task *task, int lookupflags) | ||
721 | { | ||
722 | struct rpc_auth *auth = task->tk_client->cl_auth; | ||
723 | struct auth_cred acred = { | ||
724 | .principal = task->tk_client->cl_principal, | ||
725 | .cred = init_task.cred, | ||
726 | }; | ||
727 | |||
728 | if (!acred.principal) | ||
729 | return NULL; | ||
730 | dprintk("RPC: %5u looking up %s machine cred\n", | ||
731 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); | ||
732 | return auth->au_ops->lookup_cred(auth, &acred, lookupflags); | ||
733 | } | ||
734 | |||
735 | static struct rpc_cred * | ||
706 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) | 736 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) |
707 | { | 737 | { |
708 | struct rpc_auth *auth = task->tk_client->cl_auth; | 738 | struct rpc_auth *auth = task->tk_client->cl_auth; |
@@ -716,14 +746,20 @@ static int | |||
716 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) | 746 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) |
717 | { | 747 | { |
718 | struct rpc_rqst *req = task->tk_rqstp; | 748 | struct rpc_rqst *req = task->tk_rqstp; |
719 | struct rpc_cred *new; | 749 | struct rpc_cred *new = NULL; |
720 | int lookupflags = 0; | 750 | int lookupflags = 0; |
721 | 751 | ||
722 | if (flags & RPC_TASK_ASYNC) | 752 | if (flags & RPC_TASK_ASYNC) |
723 | lookupflags |= RPCAUTH_LOOKUP_NEW; | 753 | lookupflags |= RPCAUTH_LOOKUP_NEW; |
724 | if (cred != NULL) | 754 | if (cred != NULL && cred != &machine_cred) |
725 | new = cred->cr_ops->crbind(task, cred, lookupflags); | 755 | new = cred->cr_ops->crbind(task, cred, lookupflags); |
726 | else if (flags & RPC_TASK_ROOTCREDS) | 756 | else if (cred == &machine_cred) |
757 | new = rpcauth_bind_machine_cred(task, lookupflags); | ||
758 | |||
759 | /* If machine cred couldn't be bound, try a root cred */ | ||
760 | if (new) | ||
761 | ; | ||
762 | else if (cred == &machine_cred || (flags & RPC_TASK_ROOTCREDS)) | ||
727 | new = rpcauth_bind_root_cred(task, lookupflags); | 763 | new = rpcauth_bind_root_cred(task, lookupflags); |
728 | else | 764 | else |
729 | new = rpcauth_bind_new_cred(task, lookupflags); | 765 | new = rpcauth_bind_new_cred(task, lookupflags); |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 7d1a8f45726c..5f7aa6324b78 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -48,27 +48,6 @@ struct rpc_cred *rpc_lookup_cred_nonblock(void) | |||
48 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock); | 49 | EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock); |
50 | 50 | ||
51 | /* | ||
52 | * Public call interface for looking up machine creds. | ||
53 | * Note that if service_name is NULL, we actually look up | ||
54 | * "root" credential. | ||
55 | */ | ||
56 | struct rpc_cred *rpc_lookup_machine_cred(const char *service_name) | ||
57 | { | ||
58 | struct auth_cred acred = { | ||
59 | .principal = service_name, | ||
60 | .cred = get_task_cred(&init_task), | ||
61 | }; | ||
62 | struct rpc_cred *ret; | ||
63 | |||
64 | dprintk("RPC: looking up machine cred for service %s\n", | ||
65 | service_name); | ||
66 | ret = generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); | ||
67 | put_cred(acred.cred); | ||
68 | return ret; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); | ||
71 | |||
72 | static struct rpc_cred *generic_bind_cred(struct rpc_task *task, | 51 | static struct rpc_cred *generic_bind_cred(struct rpc_task *task, |
73 | struct rpc_cred *cred, int lookupflags) | 52 | struct rpc_cred *cred, int lookupflags) |
74 | { | 53 | { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 24cbddc44c88..c5bf56abf266 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -627,6 +627,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
627 | new->cl_noretranstimeo = clnt->cl_noretranstimeo; | 627 | new->cl_noretranstimeo = clnt->cl_noretranstimeo; |
628 | new->cl_discrtry = clnt->cl_discrtry; | 628 | new->cl_discrtry = clnt->cl_discrtry; |
629 | new->cl_chatty = clnt->cl_chatty; | 629 | new->cl_chatty = clnt->cl_chatty; |
630 | new->cl_principal = clnt->cl_principal; | ||
630 | return new; | 631 | return new; |
631 | 632 | ||
632 | out_err: | 633 | out_err: |