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