1 /* 2 * linux/fs/nfs/callback.c 3 * 4 * Copyright (C) 2004 Trond Myklebust 5 * 6 * NFSv4 callback handling 7 */ 8 9 #include <linux/completion.h> 10 #include <linux/ip.h> 11 #include <linux/module.h> 12 #include <linux/sched/signal.h> 13 #include <linux/sunrpc/svc.h> 14 #include <linux/sunrpc/svcsock.h> 15 #include <linux/nfs_fs.h> 16 #include <linux/errno.h> 17 #include <linux/mutex.h> 18 #include <linux/freezer.h> 19 #include <linux/kthread.h> 20 #include <linux/sunrpc/svcauth_gss.h> 21 #include <linux/sunrpc/bc_xprt.h> 22 23 #include <net/inet_sock.h> 24 25 #include "nfs4_fs.h" 26 #include "callback.h" 27 #include "internal.h" 28 #include "netns.h" 29 30 #define NFSDBG_FACILITY NFSDBG_CALLBACK 31 32 struct nfs_callback_data { 33 unsigned int users; 34 struct svc_serv *serv; 35 }; 36 37 static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; 38 static DEFINE_MUTEX(nfs_callback_mutex); 39 static struct svc_program nfs4_callback_program; 40 41 static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) 42 { 43 int ret; 44 struct nfs_net *nn = net_generic(net, nfs_net_id); 45 46 ret = svc_create_xprt(serv, "tcp", net, PF_INET, 47 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 48 if (ret <= 0) 49 goto out_err; 50 nn->nfs_callback_tcpport = ret; 51 dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", 52 nn->nfs_callback_tcpport, PF_INET, net); 53 54 ret = svc_create_xprt(serv, "tcp", net, PF_INET6, 55 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); 56 if (ret > 0) { 57 nn->nfs_callback_tcpport6 = ret; 58 dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", 59 nn->nfs_callback_tcpport6, PF_INET6, net); 60 } else if (ret != -EAFNOSUPPORT) 61 goto out_err; 62 return 0; 63 64 out_err: 65 return (ret) ? ret : -ENOMEM; 66 } 67 68 /* 69 * This is the NFSv4 callback kernel thread. 70 */ 71 static int 72 nfs4_callback_svc(void *vrqstp) 73 { 74 int err; 75 struct svc_rqst *rqstp = vrqstp; 76 77 set_freezable(); 78 79 while (!kthread_freezable_should_stop(NULL)) { 80 81 if (signal_pending(current)) 82 flush_signals(current); 83 /* 84 * Listen for a request on the socket 85 */ 86 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); 87 if (err == -EAGAIN || err == -EINTR) 88 continue; 89 svc_process(rqstp); 90 } 91 svc_exit_thread(rqstp); 92 module_put_and_exit(0); 93 return 0; 94 } 95 96 #if defined(CONFIG_NFS_V4_1) 97 /* 98 * The callback service for NFSv4.1 callbacks 99 */ 100 static int 101 nfs41_callback_svc(void *vrqstp) 102 { 103 struct svc_rqst *rqstp = vrqstp; 104 struct svc_serv *serv = rqstp->rq_server; 105 struct rpc_rqst *req; 106 int error; 107 DEFINE_WAIT(wq); 108 109 set_freezable(); 110 111 while (!kthread_freezable_should_stop(NULL)) { 112 113 if (signal_pending(current)) 114 flush_signals(current); 115 116 prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); 117 spin_lock_bh(&serv->sv_cb_lock); 118 if (!list_empty(&serv->sv_cb_list)) { 119 req = list_first_entry(&serv->sv_cb_list, 120 struct rpc_rqst, rq_bc_list); 121 list_del(&req->rq_bc_list); 122 spin_unlock_bh(&serv->sv_cb_lock); 123 finish_wait(&serv->sv_cb_waitq, &wq); 124 dprintk("Invoking bc_svc_process()\n"); 125 error = bc_svc_process(serv, req, rqstp); 126 dprintk("bc_svc_process() returned w/ error code= %d\n", 127 error); 128 } else { 129 spin_unlock_bh(&serv->sv_cb_lock); 130 if (!kthread_should_stop()) 131 schedule(); 132 finish_wait(&serv->sv_cb_waitq, &wq); 133 } 134 } 135 svc_exit_thread(rqstp); 136 module_put_and_exit(0); 137 return 0; 138 } 139 140 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 141 struct svc_serv *serv) 142 { 143 if (minorversion) 144 /* 145 * Save the svc_serv in the transport so that it can 146 * be referenced when the session backchannel is initialized 147 */ 148 xprt->bc_serv = serv; 149 } 150 #else 151 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 152 struct svc_serv *serv) 153 { 154 } 155 #endif /* CONFIG_NFS_V4_1 */ 156 157 static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, 158 struct svc_serv *serv) 159 { 160 int nrservs = nfs_callback_nr_threads; 161 int ret; 162 163 nfs_callback_bc_serv(minorversion, xprt, serv); 164 165 if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS) 166 nrservs = NFS4_MIN_NR_CALLBACK_THREADS; 167 168 if (serv->sv_nrthreads-1 == nrservs) 169 return 0; 170 171 ret = serv->sv_ops->svo_setup(serv, NULL, nrservs); 172 if (ret) { 173 serv->sv_ops->svo_setup(serv, NULL, 0); 174 return ret; 175 } 176 dprintk("nfs_callback_up: service started\n"); 177 return 0; 178 } 179 180 static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net) 181 { 182 struct nfs_net *nn = net_generic(net, nfs_net_id); 183 184 if (--nn->cb_users[minorversion]) 185 return; 186 187 dprintk("NFS: destroy per-net callback data; net=%p\n", net); 188 svc_shutdown_net(serv, net); 189 } 190 191 static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, 192 struct net *net, struct rpc_xprt *xprt) 193 { 194 struct nfs_net *nn = net_generic(net, nfs_net_id); 195 int ret; 196 197 if (nn->cb_users[minorversion]++) 198 return 0; 199 200 dprintk("NFS: create per-net callback data; net=%p\n", net); 201 202 ret = svc_bind(serv, net); 203 if (ret < 0) { 204 printk(KERN_WARNING "NFS: bind callback service failed\n"); 205 goto err_bind; 206 } 207 208 ret = -EPROTONOSUPPORT; 209 if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0) 210 ret = nfs4_callback_up_net(serv, net); 211 else if (xprt->ops->bc_up) 212 ret = xprt->ops->bc_up(serv, net); 213 214 if (ret < 0) { 215 printk(KERN_ERR "NFS: callback service start failed\n"); 216 goto err_socks; 217 } 218 return 0; 219 220 err_socks: 221 svc_rpcb_cleanup(serv, net); 222 err_bind: 223 nn->cb_users[minorversion]--; 224 dprintk("NFS: Couldn't create callback socket: err = %d; " 225 "net = %p\n", ret, net); 226 return ret; 227 } 228 229 static struct svc_serv_ops nfs40_cb_sv_ops = { 230 .svo_function = nfs4_callback_svc, 231 .svo_enqueue_xprt = svc_xprt_do_enqueue, 232 .svo_setup = svc_set_num_threads_sync, 233 .svo_module = THIS_MODULE, 234 }; 235 #if defined(CONFIG_NFS_V4_1) 236 static struct svc_serv_ops nfs41_cb_sv_ops = { 237 .svo_function = nfs41_callback_svc, 238 .svo_enqueue_xprt = svc_xprt_do_enqueue, 239 .svo_setup = svc_set_num_threads_sync, 240 .svo_module = THIS_MODULE, 241 }; 242 243 static struct svc_serv_ops *nfs4_cb_sv_ops[] = { 244 [0] = &nfs40_cb_sv_ops, 245 [1] = &nfs41_cb_sv_ops, 246 }; 247 #else 248 static struct svc_serv_ops *nfs4_cb_sv_ops[] = { 249 [0] = &nfs40_cb_sv_ops, 250 [1] = NULL, 251 }; 252 #endif 253 254 static struct svc_serv *nfs_callback_create_svc(int minorversion) 255 { 256 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 257 struct svc_serv *serv; 258 struct svc_serv_ops *sv_ops; 259 260 /* 261 * Check whether we're already up and running. 262 */ 263 if (cb_info->serv) { 264 /* 265 * Note: increase service usage, because later in case of error 266 * svc_destroy() will be called. 267 */ 268 svc_get(cb_info->serv); 269 return cb_info->serv; 270 } 271 272 switch (minorversion) { 273 case 0: 274 sv_ops = nfs4_cb_sv_ops[0]; 275 break; 276 default: 277 sv_ops = nfs4_cb_sv_ops[1]; 278 } 279 280 if (sv_ops == NULL) 281 return ERR_PTR(-ENOTSUPP); 282 283 /* 284 * Sanity check: if there's no task, 285 * we should be the first user ... 286 */ 287 if (cb_info->users) 288 printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n", 289 cb_info->users); 290 291 serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops); 292 if (!serv) { 293 printk(KERN_ERR "nfs_callback_create_svc: create service failed\n"); 294 return ERR_PTR(-ENOMEM); 295 } 296 cb_info->serv = serv; 297 /* As there is only one thread we need to over-ride the 298 * default maximum of 80 connections 299 */ 300 serv->sv_maxconn = 1024; 301 dprintk("nfs_callback_create_svc: service created\n"); 302 return serv; 303 } 304 305 /* 306 * Bring up the callback thread if it is not already up. 307 */ 308 int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) 309 { 310 struct svc_serv *serv; 311 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 312 int ret; 313 struct net *net = xprt->xprt_net; 314 315 mutex_lock(&nfs_callback_mutex); 316 317 serv = nfs_callback_create_svc(minorversion); 318 if (IS_ERR(serv)) { 319 ret = PTR_ERR(serv); 320 goto err_create; 321 } 322 323 ret = nfs_callback_up_net(minorversion, serv, net, xprt); 324 if (ret < 0) 325 goto err_net; 326 327 ret = nfs_callback_start_svc(minorversion, xprt, serv); 328 if (ret < 0) 329 goto err_start; 330 331 cb_info->users++; 332 /* 333 * svc_create creates the svc_serv with sv_nrthreads == 1, and then 334 * svc_prepare_thread increments that. So we need to call svc_destroy 335 * on both success and failure so that the refcount is 1 when the 336 * thread exits. 337 */ 338 err_net: 339 if (!cb_info->users) 340 cb_info->serv = NULL; 341 svc_destroy(serv); 342 err_create: 343 mutex_unlock(&nfs_callback_mutex); 344 return ret; 345 346 err_start: 347 nfs_callback_down_net(minorversion, serv, net); 348 dprintk("NFS: Couldn't create server thread; err = %d\n", ret); 349 goto err_net; 350 } 351 352 /* 353 * Kill the callback thread if it's no longer being used. 354 */ 355 void nfs_callback_down(int minorversion, struct net *net) 356 { 357 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 358 struct svc_serv *serv; 359 360 mutex_lock(&nfs_callback_mutex); 361 serv = cb_info->serv; 362 nfs_callback_down_net(minorversion, serv, net); 363 cb_info->users--; 364 if (cb_info->users == 0) { 365 svc_get(serv); 366 serv->sv_ops->svo_setup(serv, NULL, 0); 367 svc_destroy(serv); 368 dprintk("nfs_callback_down: service destroyed\n"); 369 cb_info->serv = NULL; 370 } 371 mutex_unlock(&nfs_callback_mutex); 372 } 373 374 /* Boolean check of RPC_AUTH_GSS principal */ 375 int 376 check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp) 377 { 378 char *p = rqstp->rq_cred.cr_principal; 379 380 if (rqstp->rq_authop->flavour != RPC_AUTH_GSS) 381 return 1; 382 383 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ 384 if (clp->cl_minorversion != 0) 385 return 0; 386 /* 387 * It might just be a normal user principal, in which case 388 * userspace won't bother to tell us the name at all. 389 */ 390 if (p == NULL) 391 return 0; 392 393 /* 394 * Did we get the acceptor from userland during the SETCLIENID 395 * negotiation? 396 */ 397 if (clp->cl_acceptor) 398 return !strcmp(p, clp->cl_acceptor); 399 400 /* 401 * Otherwise try to verify it using the cl_hostname. Note that this 402 * doesn't work if a non-canonical hostname was used in the devname. 403 */ 404 405 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 406 407 if (memcmp(p, "nfs@", 4) != 0) 408 return 0; 409 p += 4; 410 if (strcmp(p, clp->cl_hostname) != 0) 411 return 0; 412 return 1; 413 } 414 415 /* 416 * pg_authenticate method for nfsv4 callback threads. 417 * 418 * The authflavor has been negotiated, so an incorrect flavor is a server 419 * bug. Deny packets with incorrect authflavor. 420 * 421 * All other checking done after NFS decoding where the nfs_client can be 422 * found in nfs4_callback_compound 423 */ 424 static int nfs_callback_authenticate(struct svc_rqst *rqstp) 425 { 426 switch (rqstp->rq_authop->flavour) { 427 case RPC_AUTH_NULL: 428 if (rqstp->rq_proc != CB_NULL) 429 return SVC_DENIED; 430 break; 431 case RPC_AUTH_GSS: 432 /* No RPC_AUTH_GSS support yet in NFSv4.1 */ 433 if (svc_is_backchannel(rqstp)) 434 return SVC_DENIED; 435 } 436 return SVC_OK; 437 } 438 439 /* 440 * Define NFS4 callback program 441 */ 442 static struct svc_version *nfs4_callback_version[] = { 443 [1] = &nfs4_callback_version1, 444 [4] = &nfs4_callback_version4, 445 }; 446 447 static struct svc_stat nfs4_callback_stats; 448 449 static struct svc_program nfs4_callback_program = { 450 .pg_prog = NFS4_CALLBACK, /* RPC service number */ 451 .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */ 452 .pg_vers = nfs4_callback_version, /* version table */ 453 .pg_name = "NFSv4 callback", /* service name */ 454 .pg_class = "nfs", /* authentication class */ 455 .pg_stats = &nfs4_callback_stats, 456 .pg_authenticate = nfs_callback_authenticate, 457 }; 458