aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfs/callback.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r--fs/nfs/callback.c97
1 files changed, 51 insertions, 46 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index e17b49e2eabd..e3d294269058 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -9,7 +9,6 @@
9#include <linux/completion.h> 9#include <linux/completion.h>
10#include <linux/ip.h> 10#include <linux/ip.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/smp_lock.h>
13#include <linux/sunrpc/svc.h> 12#include <linux/sunrpc/svc.h>
14#include <linux/sunrpc/svcsock.h> 13#include <linux/sunrpc/svcsock.h>
15#include <linux/nfs_fs.h> 14#include <linux/nfs_fs.h>
@@ -17,9 +16,7 @@
17#include <linux/freezer.h> 16#include <linux/freezer.h>
18#include <linux/kthread.h> 17#include <linux/kthread.h>
19#include <linux/sunrpc/svcauth_gss.h> 18#include <linux/sunrpc/svcauth_gss.h>
20#if defined(CONFIG_NFS_V4_1)
21#include <linux/sunrpc/bc_xprt.h> 19#include <linux/sunrpc/bc_xprt.h>
22#endif
23 20
24#include <net/inet_sock.h> 21#include <net/inet_sock.h>
25 22
@@ -109,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv)
109{ 106{
110 int ret; 107 int ret;
111 108
112 ret = svc_create_xprt(serv, "tcp", PF_INET, 109 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
113 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 110 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
114 if (ret <= 0) 111 if (ret <= 0)
115 goto out_err; 112 goto out_err;
@@ -117,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv)
117 dprintk("NFS: Callback listener port = %u (af %u)\n", 114 dprintk("NFS: Callback listener port = %u (af %u)\n",
118 nfs_callback_tcpport, PF_INET); 115 nfs_callback_tcpport, PF_INET);
119 116
120 ret = svc_create_xprt(serv, "tcp", PF_INET6, 117 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
121 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 118 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
122 if (ret > 0) { 119 if (ret > 0) {
123 nfs_callback_tcpport6 = ret; 120 nfs_callback_tcpport6 = ret;
@@ -178,30 +175,38 @@ nfs41_callback_svc(void *vrqstp)
178struct svc_rqst * 175struct svc_rqst *
179nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 176nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
180{ 177{
181 struct svc_xprt *bc_xprt; 178 struct svc_rqst *rqstp;
182 struct svc_rqst *rqstp = ERR_PTR(-ENOMEM); 179 int ret;
183 180
184 dprintk("--> %s\n", __func__); 181 /*
185 /* Create a svc_sock for the service */ 182 * Create an svc_sock for the back channel service that shares the
186 bc_xprt = svc_sock_create(serv, xprt->prot); 183 * fore channel connection.
187 if (!bc_xprt) 184 * Returns the input port (0) and sets the svc_serv bc_xprt on success
185 */
186 ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0,
187 SVC_SOCK_ANONYMOUS);
188 if (ret < 0) {
189 rqstp = ERR_PTR(ret);
188 goto out; 190 goto out;
191 }
189 192
190 /* 193 /*
191 * Save the svc_serv in the transport so that it can 194 * Save the svc_serv in the transport so that it can
192 * be referenced when the session backchannel is initialized 195 * be referenced when the session backchannel is initialized
193 */ 196 */
194 serv->bc_xprt = bc_xprt;
195 xprt->bc_serv = serv; 197 xprt->bc_serv = serv;
196 198
197 INIT_LIST_HEAD(&serv->sv_cb_list); 199 INIT_LIST_HEAD(&serv->sv_cb_list);
198 spin_lock_init(&serv->sv_cb_lock); 200 spin_lock_init(&serv->sv_cb_lock);
199 init_waitqueue_head(&serv->sv_cb_waitq); 201 init_waitqueue_head(&serv->sv_cb_waitq);
200 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); 202 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
201 if (IS_ERR(rqstp)) 203 if (IS_ERR(rqstp)) {
202 svc_sock_destroy(bc_xprt); 204 svc_xprt_put(serv->sv_bc_xprt);
205 serv->sv_bc_xprt = NULL;
206 }
203out: 207out:
204 dprintk("--> %s return %p\n", __func__, rqstp); 208 dprintk("--> %s return %ld\n", __func__,
209 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
205 return rqstp; 210 return rqstp;
206} 211}
207 212
@@ -323,58 +328,58 @@ void nfs_callback_down(int minorversion)
323 mutex_unlock(&nfs_callback_mutex); 328 mutex_unlock(&nfs_callback_mutex);
324} 329}
325 330
326static int check_gss_callback_principal(struct nfs_client *clp, 331/* Boolean check of RPC_AUTH_GSS principal */
327 struct svc_rqst *rqstp) 332int
333check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
328{ 334{
329 struct rpc_clnt *r = clp->cl_rpcclient; 335 struct rpc_clnt *r = clp->cl_rpcclient;
330 char *p = svc_gss_principal(rqstp); 336 char *p = svc_gss_principal(rqstp);
331 337
338 if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
339 return 1;
340
341 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
342 if (clp->cl_minorversion != 0)
343 return 0;
332 /* 344 /*
333 * It might just be a normal user principal, in which case 345 * It might just be a normal user principal, in which case
334 * userspace won't bother to tell us the name at all. 346 * userspace won't bother to tell us the name at all.
335 */ 347 */
336 if (p == NULL) 348 if (p == NULL)
337 return SVC_DENIED; 349 return 0;
338 350
339 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 351 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
340 352
341 if (memcmp(p, "nfs@", 4) != 0) 353 if (memcmp(p, "nfs@", 4) != 0)
342 return SVC_DENIED; 354 return 0;
343 p += 4; 355 p += 4;
344 if (strcmp(p, r->cl_server) != 0) 356 if (strcmp(p, r->cl_server) != 0)
345 return SVC_DENIED; 357 return 0;
346 return SVC_OK; 358 return 1;
347} 359}
348 360
361/*
362 * pg_authenticate method for nfsv4 callback threads.
363 *
364 * The authflavor has been negotiated, so an incorrect flavor is a server
365 * bug. Drop packets with incorrect authflavor.
366 *
367 * All other checking done after NFS decoding where the nfs_client can be
368 * found in nfs4_callback_compound
369 */
349static int nfs_callback_authenticate(struct svc_rqst *rqstp) 370static int nfs_callback_authenticate(struct svc_rqst *rqstp)
350{ 371{
351 struct nfs_client *clp;
352 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
353 int ret = SVC_OK;
354
355 /* Don't talk to strangers */
356 clp = nfs_find_client(svc_addr(rqstp), 4);
357 if (clp == NULL)
358 return SVC_DROP;
359
360 dprintk("%s: %s NFSv4 callback!\n", __func__,
361 svc_print_addr(rqstp, buf, sizeof(buf)));
362
363 switch (rqstp->rq_authop->flavour) { 372 switch (rqstp->rq_authop->flavour) {
364 case RPC_AUTH_NULL: 373 case RPC_AUTH_NULL:
365 if (rqstp->rq_proc != CB_NULL) 374 if (rqstp->rq_proc != CB_NULL)
366 ret = SVC_DENIED; 375 return SVC_DROP;
367 break; 376 break;
368 case RPC_AUTH_UNIX: 377 case RPC_AUTH_GSS:
369 break; 378 /* No RPC_AUTH_GSS support yet in NFSv4.1 */
370 case RPC_AUTH_GSS: 379 if (svc_is_backchannel(rqstp))
371 ret = check_gss_callback_principal(clp, rqstp); 380 return SVC_DROP;
372 break;
373 default:
374 ret = SVC_DENIED;
375 } 381 }
376 nfs_put_client(clp); 382 return SVC_OK;
377 return ret;
378} 383}
379 384
380/* 385/*