aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r--fs/nfs/callback.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 93a8b3bd69e3..e3d294269058 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -16,9 +16,7 @@
16#include <linux/freezer.h> 16#include <linux/freezer.h>
17#include <linux/kthread.h> 17#include <linux/kthread.h>
18#include <linux/sunrpc/svcauth_gss.h> 18#include <linux/sunrpc/svcauth_gss.h>
19#if defined(CONFIG_NFS_V4_1)
20#include <linux/sunrpc/bc_xprt.h> 19#include <linux/sunrpc/bc_xprt.h>
21#endif
22 20
23#include <net/inet_sock.h> 21#include <net/inet_sock.h>
24 22
@@ -177,30 +175,38 @@ nfs41_callback_svc(void *vrqstp)
177struct svc_rqst * 175struct svc_rqst *
178nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 176nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
179{ 177{
180 struct svc_xprt *bc_xprt; 178 struct svc_rqst *rqstp;
181 struct svc_rqst *rqstp = ERR_PTR(-ENOMEM); 179 int ret;
182 180
183 dprintk("--> %s\n", __func__); 181 /*
184 /* Create a svc_sock for the service */ 182 * Create an svc_sock for the back channel service that shares the
185 bc_xprt = svc_sock_create(serv, xprt->prot); 183 * fore channel connection.
186 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);
187 goto out; 190 goto out;
191 }
188 192
189 /* 193 /*
190 * Save the svc_serv in the transport so that it can 194 * Save the svc_serv in the transport so that it can
191 * be referenced when the session backchannel is initialized 195 * be referenced when the session backchannel is initialized
192 */ 196 */
193 serv->bc_xprt = bc_xprt;
194 xprt->bc_serv = serv; 197 xprt->bc_serv = serv;
195 198
196 INIT_LIST_HEAD(&serv->sv_cb_list); 199 INIT_LIST_HEAD(&serv->sv_cb_list);
197 spin_lock_init(&serv->sv_cb_lock); 200 spin_lock_init(&serv->sv_cb_lock);
198 init_waitqueue_head(&serv->sv_cb_waitq); 201 init_waitqueue_head(&serv->sv_cb_waitq);
199 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]); 202 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
200 if (IS_ERR(rqstp)) 203 if (IS_ERR(rqstp)) {
201 svc_sock_destroy(bc_xprt); 204 svc_xprt_put(serv->sv_bc_xprt);
205 serv->sv_bc_xprt = NULL;
206 }
202out: 207out:
203 dprintk("--> %s return %p\n", __func__, rqstp); 208 dprintk("--> %s return %ld\n", __func__,
209 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
204 return rqstp; 210 return rqstp;
205} 211}
206 212
@@ -322,58 +328,58 @@ void nfs_callback_down(int minorversion)
322 mutex_unlock(&nfs_callback_mutex); 328 mutex_unlock(&nfs_callback_mutex);
323} 329}
324 330
325static int check_gss_callback_principal(struct nfs_client *clp, 331/* Boolean check of RPC_AUTH_GSS principal */
326 struct svc_rqst *rqstp) 332int
333check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
327{ 334{
328 struct rpc_clnt *r = clp->cl_rpcclient; 335 struct rpc_clnt *r = clp->cl_rpcclient;
329 char *p = svc_gss_principal(rqstp); 336 char *p = svc_gss_principal(rqstp);
330 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;
331 /* 344 /*
332 * It might just be a normal user principal, in which case 345 * It might just be a normal user principal, in which case
333 * userspace won't bother to tell us the name at all. 346 * userspace won't bother to tell us the name at all.
334 */ 347 */
335 if (p == NULL) 348 if (p == NULL)
336 return SVC_DENIED; 349 return 0;
337 350
338 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 351 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
339 352
340 if (memcmp(p, "nfs@", 4) != 0) 353 if (memcmp(p, "nfs@", 4) != 0)
341 return SVC_DENIED; 354 return 0;
342 p += 4; 355 p += 4;
343 if (strcmp(p, r->cl_server) != 0) 356 if (strcmp(p, r->cl_server) != 0)
344 return SVC_DENIED; 357 return 0;
345 return SVC_OK; 358 return 1;
346} 359}
347 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 */
348static int nfs_callback_authenticate(struct svc_rqst *rqstp) 370static int nfs_callback_authenticate(struct svc_rqst *rqstp)
349{ 371{
350 struct nfs_client *clp;
351 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
352 int ret = SVC_OK;
353
354 /* Don't talk to strangers */
355 clp = nfs_find_client(svc_addr(rqstp), 4);
356 if (clp == NULL)
357 return SVC_DROP;
358
359 dprintk("%s: %s NFSv4 callback!\n", __func__,
360 svc_print_addr(rqstp, buf, sizeof(buf)));
361
362 switch (rqstp->rq_authop->flavour) { 372 switch (rqstp->rq_authop->flavour) {
363 case RPC_AUTH_NULL: 373 case RPC_AUTH_NULL:
364 if (rqstp->rq_proc != CB_NULL) 374 if (rqstp->rq_proc != CB_NULL)
365 ret = SVC_DENIED; 375 return SVC_DROP;
366 break; 376 break;
367 case RPC_AUTH_UNIX: 377 case RPC_AUTH_GSS:
368 break; 378 /* No RPC_AUTH_GSS support yet in NFSv4.1 */
369 case RPC_AUTH_GSS: 379 if (svc_is_backchannel(rqstp))
370 ret = check_gss_callback_principal(clp, rqstp); 380 return SVC_DROP;
371 break;
372 default:
373 ret = SVC_DENIED;
374 } 381 }
375 nfs_put_client(clp); 382 return SVC_OK;
376 return ret;
377} 383}
378 384
379/* 385/*