aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2018-12-02 19:30:30 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-12-19 13:52:45 -0500
commit5e16923b432bfe79fdfb7cd95ed8e63f6438b663 (patch)
tree92c842d96a8cacdead34c4f260bd371077f06793
parentecd5f97e1c7cd6124e3c3053beb5f2239aeacf8e (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.c11
-rw-r--r--fs/nfs/nfs4_fs.h9
-rw-r--r--fs/nfs/nfs4state.c21
-rw-r--r--fs/nfsd/nfs4callback.c12
-rw-r--r--include/linux/nfs_fs_sb.h3
-rw-r--r--include/linux/sunrpc/auth.h3
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--net/sunrpc/auth.c42
-rw-r--r--net/sunrpc/auth_generic.c21
-rw-r--r--net/sunrpc/clnt.c1
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);
151struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) 151struct 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
167struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp) 167struct 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
178static void nfs4_root_machine_cred(struct nfs_client *clp) 172static 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
193static struct rpc_cred * 180static 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)
847static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses) 847static 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
78struct 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);
170struct rpc_cred * rpc_lookup_cred(void); 172struct rpc_cred * rpc_lookup_cred(void);
171struct rpc_cred * rpc_lookup_cred_nonblock(void); 173struct rpc_cred * rpc_lookup_cred_nonblock(void);
172struct rpc_cred * rpc_lookup_generic_cred(struct auth_cred *, int, gfp_t); 174struct rpc_cred * rpc_lookup_generic_cred(struct auth_cred *, int, gfp_t);
173struct rpc_cred * rpc_lookup_machine_cred(const char *service_name);
174int rpcauth_register(const struct rpc_authops *); 175int rpcauth_register(const struct rpc_authops *);
175int rpcauth_unregister(const struct rpc_authops *); 176int rpcauth_unregister(const struct rpc_authops *);
176struct rpc_auth * rpcauth_create(const struct rpc_auth_create_args *, 177struct 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] = {
39static LIST_HEAD(cred_unused); 39static LIST_HEAD(cred_unused);
40static unsigned long number_cred_unused; 40static unsigned long number_cred_unused;
41 41
42static 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 */
50struct rpc_cred *rpc_machine_cred(void)
51{
52 return &machine_cred;
53}
54EXPORT_SYMBOL_GPL(rpc_machine_cred);
55
42#define MAX_HASHTABLE_BITS (14) 56#define MAX_HASHTABLE_BITS (14)
43static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) 57static 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
705static struct rpc_cred * 719static struct rpc_cred *
720rpcauth_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
735static struct rpc_cred *
706rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) 736rpcauth_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
716rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) 746rpcauth_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}
49EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock); 49EXPORT_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 */
56struct 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}
70EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);
71
72static struct rpc_cred *generic_bind_cred(struct rpc_task *task, 51static 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
632out_err: 633out_err: