xref: /linux/fs/nfs/callback.c (revision 077248fcce5edabb1b77ba3269e6c72341769d94)
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/mutex.h>
16 #include <linux/freezer.h>
17 #include <linux/kthread.h>
18 #include <linux/sunrpc/svcauth_gss.h>
19 #if defined(CONFIG_NFS_V4_1)
20 #include <linux/sunrpc/bc_xprt.h>
21 #endif
22 
23 #include <net/inet_sock.h>
24 
25 #include "nfs4_fs.h"
26 #include "callback.h"
27 #include "internal.h"
28 
29 #define NFSDBG_FACILITY NFSDBG_CALLBACK
30 
31 struct nfs_callback_data {
32 	unsigned int users;
33 	struct svc_serv *serv;
34 	struct svc_rqst *rqst;
35 	struct task_struct *task;
36 };
37 
38 static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
39 static DEFINE_MUTEX(nfs_callback_mutex);
40 static struct svc_program nfs4_callback_program;
41 
42 unsigned int nfs_callback_set_tcpport;
43 unsigned short nfs_callback_tcpport;
44 unsigned short nfs_callback_tcpport6;
45 #define NFS_CALLBACK_MAXPORTNR (65535U)
46 
47 static int param_set_portnr(const char *val, const struct kernel_param *kp)
48 {
49 	unsigned long num;
50 	int ret;
51 
52 	if (!val)
53 		return -EINVAL;
54 	ret = strict_strtoul(val, 0, &num);
55 	if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
56 		return -EINVAL;
57 	*((unsigned int *)kp->arg) = num;
58 	return 0;
59 }
60 static struct kernel_param_ops param_ops_portnr = {
61 	.set = param_set_portnr,
62 	.get = param_get_uint,
63 };
64 #define param_check_portnr(name, p) __param_check(name, p, unsigned int);
65 
66 module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
67 
68 /*
69  * This is the NFSv4 callback kernel thread.
70  */
71 static int
72 nfs4_callback_svc(void *vrqstp)
73 {
74 	int err, preverr = 0;
75 	struct svc_rqst *rqstp = vrqstp;
76 
77 	set_freezable();
78 
79 	while (!kthread_should_stop()) {
80 		/*
81 		 * Listen for a request on the socket
82 		 */
83 		err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
84 		if (err == -EAGAIN || err == -EINTR) {
85 			preverr = err;
86 			continue;
87 		}
88 		if (err < 0) {
89 			if (err != preverr) {
90 				printk(KERN_WARNING "%s: unexpected error "
91 					"from svc_recv (%d)\n", __func__, err);
92 				preverr = err;
93 			}
94 			schedule_timeout_uninterruptible(HZ);
95 			continue;
96 		}
97 		preverr = err;
98 		svc_process(rqstp);
99 	}
100 	return 0;
101 }
102 
103 /*
104  * Prepare to bring up the NFSv4 callback service
105  */
106 struct svc_rqst *
107 nfs4_callback_up(struct svc_serv *serv)
108 {
109 	int ret;
110 
111 	ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
112 				nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
113 	if (ret <= 0)
114 		goto out_err;
115 	nfs_callback_tcpport = ret;
116 	dprintk("NFS: Callback listener port = %u (af %u)\n",
117 			nfs_callback_tcpport, PF_INET);
118 
119 	ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
120 				nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
121 	if (ret > 0) {
122 		nfs_callback_tcpport6 = ret;
123 		dprintk("NFS: Callback listener port = %u (af %u)\n",
124 				nfs_callback_tcpport6, PF_INET6);
125 	} else if (ret == -EAFNOSUPPORT)
126 		ret = 0;
127 	else
128 		goto out_err;
129 
130 	return svc_prepare_thread(serv, &serv->sv_pools[0]);
131 
132 out_err:
133 	if (ret == 0)
134 		ret = -ENOMEM;
135 	return ERR_PTR(ret);
136 }
137 
138 #if defined(CONFIG_NFS_V4_1)
139 /*
140  * The callback service for NFSv4.1 callbacks
141  */
142 static int
143 nfs41_callback_svc(void *vrqstp)
144 {
145 	struct svc_rqst *rqstp = vrqstp;
146 	struct svc_serv *serv = rqstp->rq_server;
147 	struct rpc_rqst *req;
148 	int error;
149 	DEFINE_WAIT(wq);
150 
151 	set_freezable();
152 
153 	while (!kthread_should_stop()) {
154 		prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
155 		spin_lock_bh(&serv->sv_cb_lock);
156 		if (!list_empty(&serv->sv_cb_list)) {
157 			req = list_first_entry(&serv->sv_cb_list,
158 					struct rpc_rqst, rq_bc_list);
159 			list_del(&req->rq_bc_list);
160 			spin_unlock_bh(&serv->sv_cb_lock);
161 			dprintk("Invoking bc_svc_process()\n");
162 			error = bc_svc_process(serv, req, rqstp);
163 			dprintk("bc_svc_process() returned w/ error code= %d\n",
164 				error);
165 		} else {
166 			spin_unlock_bh(&serv->sv_cb_lock);
167 			schedule();
168 		}
169 		finish_wait(&serv->sv_cb_waitq, &wq);
170 	}
171 	return 0;
172 }
173 
174 /*
175  * Bring up the NFSv4.1 callback service
176  */
177 struct svc_rqst *
178 nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
179 {
180 	struct svc_xprt *bc_xprt;
181 	struct svc_rqst *rqstp = ERR_PTR(-ENOMEM);
182 
183 	dprintk("--> %s\n", __func__);
184 	/* Create a svc_sock for the service */
185 	bc_xprt = svc_sock_create(serv, xprt->prot);
186 	if (!bc_xprt)
187 		goto out;
188 
189 	/*
190 	 * Save the svc_serv in the transport so that it can
191 	 * be referenced when the session backchannel is initialized
192 	 */
193 	serv->bc_xprt = bc_xprt;
194 	xprt->bc_serv = serv;
195 
196 	INIT_LIST_HEAD(&serv->sv_cb_list);
197 	spin_lock_init(&serv->sv_cb_lock);
198 	init_waitqueue_head(&serv->sv_cb_waitq);
199 	rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
200 	if (IS_ERR(rqstp))
201 		svc_sock_destroy(bc_xprt);
202 out:
203 	dprintk("--> %s return %p\n", __func__, rqstp);
204 	return rqstp;
205 }
206 
207 static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
208 		struct svc_serv *serv, struct rpc_xprt *xprt,
209 		struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
210 {
211 	if (minorversion) {
212 		*rqstpp = nfs41_callback_up(serv, xprt);
213 		*callback_svc = nfs41_callback_svc;
214 	}
215 	return minorversion;
216 }
217 
218 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
219 		struct nfs_callback_data *cb_info)
220 {
221 	if (minorversion)
222 		xprt->bc_serv = cb_info->serv;
223 }
224 #else
225 static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
226 		struct svc_serv *serv, struct rpc_xprt *xprt,
227 		struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
228 {
229 	return 0;
230 }
231 
232 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
233 		struct nfs_callback_data *cb_info)
234 {
235 }
236 #endif /* CONFIG_NFS_V4_1 */
237 
238 /*
239  * Bring up the callback thread if it is not already up.
240  */
241 int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
242 {
243 	struct svc_serv *serv = NULL;
244 	struct svc_rqst *rqstp;
245 	int (*callback_svc)(void *vrqstp);
246 	struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
247 	char svc_name[12];
248 	int ret = 0;
249 	int minorversion_setup;
250 
251 	mutex_lock(&nfs_callback_mutex);
252 	if (cb_info->users++ || cb_info->task != NULL) {
253 		nfs_callback_bc_serv(minorversion, xprt, cb_info);
254 		goto out;
255 	}
256 	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
257 	if (!serv) {
258 		ret = -ENOMEM;
259 		goto out_err;
260 	}
261 
262 	minorversion_setup =  nfs_minorversion_callback_svc_setup(minorversion,
263 					serv, xprt, &rqstp, &callback_svc);
264 	if (!minorversion_setup) {
265 		/* v4.0 callback setup */
266 		rqstp = nfs4_callback_up(serv);
267 		callback_svc = nfs4_callback_svc;
268 	}
269 
270 	if (IS_ERR(rqstp)) {
271 		ret = PTR_ERR(rqstp);
272 		goto out_err;
273 	}
274 
275 	svc_sock_update_bufs(serv);
276 
277 	sprintf(svc_name, "nfsv4.%u-svc", minorversion);
278 	cb_info->serv = serv;
279 	cb_info->rqst = rqstp;
280 	cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name);
281 	if (IS_ERR(cb_info->task)) {
282 		ret = PTR_ERR(cb_info->task);
283 		svc_exit_thread(cb_info->rqst);
284 		cb_info->rqst = NULL;
285 		cb_info->task = NULL;
286 		goto out_err;
287 	}
288 out:
289 	/*
290 	 * svc_create creates the svc_serv with sv_nrthreads == 1, and then
291 	 * svc_prepare_thread increments that. So we need to call svc_destroy
292 	 * on both success and failure so that the refcount is 1 when the
293 	 * thread exits.
294 	 */
295 	if (serv)
296 		svc_destroy(serv);
297 	mutex_unlock(&nfs_callback_mutex);
298 	return ret;
299 out_err:
300 	dprintk("NFS: Couldn't create callback socket or server thread; "
301 		"err = %d\n", ret);
302 	cb_info->users--;
303 	goto out;
304 }
305 
306 /*
307  * Kill the callback thread if it's no longer being used.
308  */
309 void nfs_callback_down(int minorversion)
310 {
311 	struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
312 
313 	mutex_lock(&nfs_callback_mutex);
314 	cb_info->users--;
315 	if (cb_info->users == 0 && cb_info->task != NULL) {
316 		kthread_stop(cb_info->task);
317 		svc_exit_thread(cb_info->rqst);
318 		cb_info->serv = NULL;
319 		cb_info->rqst = NULL;
320 		cb_info->task = NULL;
321 	}
322 	mutex_unlock(&nfs_callback_mutex);
323 }
324 
325 static int check_gss_callback_principal(struct nfs_client *clp,
326 					struct svc_rqst *rqstp)
327 {
328 	struct rpc_clnt *r = clp->cl_rpcclient;
329 	char *p = svc_gss_principal(rqstp);
330 
331 	/*
332 	 * It might just be a normal user principal, in which case
333 	 * userspace won't bother to tell us the name at all.
334 	 */
335 	if (p == NULL)
336 		return SVC_DENIED;
337 
338 	/* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
339 
340 	if (memcmp(p, "nfs@", 4) != 0)
341 		return SVC_DENIED;
342 	p += 4;
343 	if (strcmp(p, r->cl_server) != 0)
344 		return SVC_DENIED;
345 	return SVC_OK;
346 }
347 
348 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
349 {
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) {
363 		case RPC_AUTH_NULL:
364 			if (rqstp->rq_proc != CB_NULL)
365 				ret = SVC_DENIED;
366 			break;
367 		case RPC_AUTH_UNIX:
368 			break;
369 		case RPC_AUTH_GSS:
370 			ret = check_gss_callback_principal(clp, rqstp);
371 			break;
372 		default:
373 			ret = SVC_DENIED;
374 	}
375 	nfs_put_client(clp);
376 	return ret;
377 }
378 
379 /*
380  * Define NFS4 callback program
381  */
382 static struct svc_version *nfs4_callback_version[] = {
383 	[1] = &nfs4_callback_version1,
384 	[4] = &nfs4_callback_version4,
385 };
386 
387 static struct svc_stat nfs4_callback_stats;
388 
389 static struct svc_program nfs4_callback_program = {
390 	.pg_prog = NFS4_CALLBACK,			/* RPC service number */
391 	.pg_nvers = ARRAY_SIZE(nfs4_callback_version),	/* Number of entries */
392 	.pg_vers = nfs4_callback_version,		/* version table */
393 	.pg_name = "NFSv4 callback",			/* service name */
394 	.pg_class = "nfs",				/* authentication class */
395 	.pg_stats = &nfs4_callback_stats,
396 	.pg_authenticate = nfs_callback_authenticate,
397 };
398