1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/nfs/callback.c 4 * 5 * Copyright (C) 2004 Trond Myklebust 6 * 7 * NFSv4 callback handling 8 */ 9 10 #include <linux/completion.h> 11 #include <linux/ip.h> 12 #include <linux/module.h> 13 #include <linux/sched/signal.h> 14 #include <linux/sunrpc/svc.h> 15 #include <linux/sunrpc/svcsock.h> 16 #include <linux/nfs_fs.h> 17 #include <linux/errno.h> 18 #include <linux/mutex.h> 19 #include <linux/freezer.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 const struct cred *cred = current_cred(); 44 int ret; 45 struct nfs_net *nn = net_generic(net, nfs_net_id); 46 47 ret = svc_xprt_create(serv, "tcp", net, PF_INET, 48 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 49 cred); 50 if (ret <= 0) 51 goto out_err; 52 nn->nfs_callback_tcpport = ret; 53 dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", 54 nn->nfs_callback_tcpport, PF_INET, net->ns.inum); 55 56 ret = svc_xprt_create(serv, "tcp", net, PF_INET6, 57 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS, 58 cred); 59 if (ret > 0) { 60 nn->nfs_callback_tcpport6 = ret; 61 dprintk("NFS: Callback listener port = %u (af %u, net %x)\n", 62 nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum); 63 } else if (ret != -EAFNOSUPPORT) 64 goto out_err; 65 return 0; 66 67 out_err: 68 return (ret) ? ret : -ENOMEM; 69 } 70 71 /* 72 * This is the NFSv4 callback kernel thread. 73 */ 74 static int 75 nfs4_callback_svc(void *vrqstp) 76 { 77 struct svc_rqst *rqstp = vrqstp; 78 79 svc_thread_init_status(rqstp, 0); 80 81 set_freezable(); 82 83 while (!svc_thread_should_stop(rqstp)) 84 svc_recv(rqstp, 0); 85 86 svc_exit_thread(rqstp); 87 return 0; 88 } 89 90 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 91 struct svc_serv *serv) 92 { 93 if (minorversion) 94 /* 95 * Save the svc_serv in the transport so that it can 96 * be referenced when the session backchannel is initialized 97 */ 98 xprt->bc_serv = serv; 99 } 100 101 static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, 102 struct svc_serv *serv) 103 { 104 int nrservs = nfs_callback_nr_threads; 105 int ret; 106 107 nfs_callback_bc_serv(minorversion, xprt, serv); 108 109 if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS) 110 nrservs = NFS4_MIN_NR_CALLBACK_THREADS; 111 112 if (serv->sv_nrthreads == nrservs) 113 return 0; 114 115 ret = svc_set_num_threads(serv, 0, nrservs); 116 if (ret) { 117 svc_set_num_threads(serv, 0, 0); 118 return ret; 119 } 120 dprintk("nfs_callback_up: service started\n"); 121 return 0; 122 } 123 124 static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net) 125 { 126 struct nfs_net *nn = net_generic(net, nfs_net_id); 127 128 if (--nn->cb_users[minorversion]) 129 return; 130 131 dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum); 132 svc_xprt_destroy_all(serv, net, false); 133 } 134 135 static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, 136 struct net *net, struct rpc_xprt *xprt) 137 { 138 struct nfs_net *nn = net_generic(net, nfs_net_id); 139 int ret; 140 141 if (nn->cb_users[minorversion]++) 142 return 0; 143 144 dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum); 145 146 ret = svc_bind(serv, net); 147 if (ret < 0) { 148 printk(KERN_WARNING "NFS: bind callback service failed\n"); 149 goto err; 150 } 151 152 ret = 0; 153 if (minorversion == 0) 154 ret = nfs4_callback_up_net(serv, net); 155 else if (xprt->ops->bc_setup) 156 set_bc_enabled(serv); 157 else 158 ret = -EPROTONOSUPPORT; 159 160 if (ret < 0) { 161 printk(KERN_ERR "NFS: callback service start failed\n"); 162 goto err; 163 } 164 return 0; 165 166 err: 167 nn->cb_users[minorversion]--; 168 dprintk("NFS: Couldn't create callback socket: err = %d; " 169 "net = %x\n", ret, net->ns.inum); 170 return ret; 171 } 172 173 static struct svc_serv *nfs_callback_create_svc(int minorversion) 174 { 175 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 176 int (*threadfn)(void *data); 177 struct svc_serv *serv; 178 179 /* 180 * Check whether we're already up and running. 181 */ 182 if (cb_info->serv) 183 return cb_info->serv; 184 185 /* 186 * Sanity check: if there's no task, 187 * we should be the first user ... 188 */ 189 if (cb_info->users) 190 printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n", 191 cb_info->users); 192 193 threadfn = nfs4_callback_svc; 194 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, 195 threadfn); 196 if (!serv) { 197 printk(KERN_ERR "nfs_callback_create_svc: create service failed\n"); 198 return ERR_PTR(-ENOMEM); 199 } 200 cb_info->serv = serv; 201 dprintk("nfs_callback_create_svc: service created\n"); 202 return serv; 203 } 204 205 /* 206 * Bring up the callback thread if it is not already up. 207 */ 208 int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) 209 { 210 struct svc_serv *serv; 211 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 212 int ret; 213 struct net *net = xprt->xprt_net; 214 215 mutex_lock(&nfs_callback_mutex); 216 217 serv = nfs_callback_create_svc(minorversion); 218 if (IS_ERR(serv)) { 219 ret = PTR_ERR(serv); 220 goto err_create; 221 } 222 223 ret = nfs_callback_up_net(minorversion, serv, net, xprt); 224 if (ret < 0) 225 goto err_net; 226 227 ret = nfs_callback_start_svc(minorversion, xprt, serv); 228 if (ret < 0) 229 goto err_start; 230 231 cb_info->users++; 232 err_net: 233 if (!cb_info->users) { 234 svc_set_num_threads(cb_info->serv, 0, 0); 235 svc_destroy(&cb_info->serv); 236 } 237 err_create: 238 mutex_unlock(&nfs_callback_mutex); 239 return ret; 240 241 err_start: 242 nfs_callback_down_net(minorversion, serv, net); 243 dprintk("NFS: Couldn't create server thread; err = %d\n", ret); 244 goto err_net; 245 } 246 247 /* 248 * Kill the callback thread if it's no longer being used. 249 */ 250 void nfs_callback_down(int minorversion, struct net *net, struct rpc_xprt *xprt) 251 { 252 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 253 struct svc_serv *serv; 254 255 mutex_lock(&nfs_callback_mutex); 256 serv = cb_info->serv; 257 nfs_callback_down_net(minorversion, serv, net); 258 cb_info->users--; 259 if (cb_info->users == 0) { 260 svc_set_num_threads(serv, 0, 0); 261 dprintk("nfs_callback_down: service destroyed\n"); 262 xprt_svc_destroy_nullify_bc(xprt, &cb_info->serv); 263 } 264 mutex_unlock(&nfs_callback_mutex); 265 } 266 267 /* Boolean check of RPC_AUTH_GSS principal */ 268 int 269 check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp) 270 { 271 char *p = rqstp->rq_cred.cr_principal; 272 273 if (rqstp->rq_authop->flavour != RPC_AUTH_GSS) 274 return 1; 275 276 /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */ 277 if (clp->cl_minorversion != 0) 278 return 0; 279 /* 280 * It might just be a normal user principal, in which case 281 * userspace won't bother to tell us the name at all. 282 */ 283 if (p == NULL) 284 return 0; 285 286 /* 287 * Did we get the acceptor from userland during the SETCLIENID 288 * negotiation? 289 */ 290 if (clp->cl_acceptor) 291 return !strcmp(p, clp->cl_acceptor); 292 293 /* 294 * Otherwise try to verify it using the cl_hostname. Note that this 295 * doesn't work if a non-canonical hostname was used in the devname. 296 */ 297 298 /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */ 299 300 if (memcmp(p, "nfs@", 4) != 0) 301 return 0; 302 p += 4; 303 if (strcmp(p, clp->cl_hostname) != 0) 304 return 0; 305 return 1; 306 } 307 308 /* 309 * pg_authenticate method for nfsv4 callback threads. 310 * 311 * The authflavor has been negotiated, so an incorrect flavor is a server 312 * bug. Deny packets with incorrect authflavor. 313 * 314 * All other checking done after NFS decoding where the nfs_client can be 315 * found in nfs4_callback_compound 316 */ 317 static enum svc_auth_status nfs_callback_authenticate(struct svc_rqst *rqstp) 318 { 319 rqstp->rq_auth_stat = rpc_autherr_badcred; 320 321 switch (rqstp->rq_authop->flavour) { 322 case RPC_AUTH_NULL: 323 if (rqstp->rq_proc != CB_NULL) 324 return SVC_DENIED; 325 break; 326 case RPC_AUTH_GSS: 327 /* No RPC_AUTH_GSS support yet in NFSv4.1 */ 328 if (svc_is_backchannel(rqstp)) 329 return SVC_DENIED; 330 } 331 332 rqstp->rq_auth_stat = rpc_auth_ok; 333 return SVC_OK; 334 } 335 336 /* 337 * Define NFS4 callback program 338 */ 339 static const struct svc_version *nfs4_callback_version[] = { 340 [1] = &nfs4_callback_version1, 341 [4] = &nfs4_callback_version4, 342 }; 343 344 static struct svc_program nfs4_callback_program = { 345 .pg_prog = NFS4_CALLBACK, /* RPC service number */ 346 .pg_nvers = ARRAY_SIZE(nfs4_callback_version), /* Number of entries */ 347 .pg_vers = nfs4_callback_version, /* version table */ 348 .pg_name = "NFSv4 callback", /* service name */ 349 .pg_class = "nfs", /* authentication class */ 350 .pg_authenticate = nfs_callback_authenticate, 351 .pg_init_request = svc_generic_init_request, 352 .pg_rpcbind_set = svc_generic_rpcbind_set, 353 }; 354