xref: /openbmc/linux/fs/lockd/svcproc.c (revision a44d924c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * linux/fs/lockd/svcproc.c
4  *
5  * Lockd server procedures. We don't implement the NLM_*_RES
6  * procedures because we don't use the async procedures.
7  *
8  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
9  */
10 
11 #include <linux/types.h>
12 #include <linux/time.h>
13 #include <linux/lockd/lockd.h>
14 #include <linux/lockd/share.h>
15 #include <linux/sunrpc/svc_xprt.h>
16 
17 #define NLMDBG_FACILITY		NLMDBG_CLIENT
18 
19 #ifdef CONFIG_LOCKD_V4
20 static __be32
21 cast_to_nlm(__be32 status, u32 vers)
22 {
23 	/* Note: status is assumed to be in network byte order !!! */
24 	if (vers != 4){
25 		switch (status) {
26 		case nlm_granted:
27 		case nlm_lck_denied:
28 		case nlm_lck_denied_nolocks:
29 		case nlm_lck_blocked:
30 		case nlm_lck_denied_grace_period:
31 		case nlm_drop_reply:
32 			break;
33 		case nlm4_deadlock:
34 			status = nlm_lck_denied;
35 			break;
36 		default:
37 			status = nlm_lck_denied_nolocks;
38 		}
39 	}
40 
41 	return (status);
42 }
43 #define	cast_status(status) (cast_to_nlm(status, rqstp->rq_vers))
44 #else
45 #define cast_status(status) (status)
46 #endif
47 
48 /*
49  * Obtain client and file from arguments
50  */
51 static __be32
52 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
53 			struct nlm_host **hostp, struct nlm_file **filp)
54 {
55 	struct nlm_host		*host = NULL;
56 	struct nlm_file		*file = NULL;
57 	struct nlm_lock		*lock = &argp->lock;
58 	__be32			error = 0;
59 
60 	/* nfsd callbacks must have been installed for this procedure */
61 	if (!nlmsvc_ops)
62 		return nlm_lck_denied_nolocks;
63 
64 	/* Obtain host handle */
65 	if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
66 	 || (argp->monitor && nsm_monitor(host) < 0))
67 		goto no_locks;
68 	*hostp = host;
69 
70 	/* Obtain file pointer. Not used by FREE_ALL call. */
71 	if (filp != NULL) {
72 		error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
73 		if (error != 0)
74 			goto no_locks;
75 		*filp = file;
76 
77 		/* Set up the missing parts of the file_lock structure */
78 		lock->fl.fl_file  = file->f_file;
79 		lock->fl.fl_owner = (fl_owner_t) host;
80 		lock->fl.fl_lmops = &nlmsvc_lock_operations;
81 	}
82 
83 	return 0;
84 
85 no_locks:
86 	nlmsvc_release_host(host);
87 	if (error)
88 		return error;
89 	return nlm_lck_denied_nolocks;
90 }
91 
92 /*
93  * NULL: Test for presence of service
94  */
95 static __be32
96 nlmsvc_proc_null(struct svc_rqst *rqstp)
97 {
98 	dprintk("lockd: NULL          called\n");
99 	return rpc_success;
100 }
101 
102 /*
103  * TEST: Check for conflicting lock
104  */
105 static __be32
106 __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
107 {
108 	struct nlm_args *argp = rqstp->rq_argp;
109 	struct nlm_host	*host;
110 	struct nlm_file	*file;
111 	__be32 rc = rpc_success;
112 
113 	dprintk("lockd: TEST          called\n");
114 	resp->cookie = argp->cookie;
115 
116 	/* Obtain client and file */
117 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
118 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
119 
120 	/* Now check for conflicting locks */
121 	resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
122 	if (resp->status == nlm_drop_reply)
123 		rc = rpc_drop_reply;
124 	else
125 		dprintk("lockd: TEST          status %d vers %d\n",
126 			ntohl(resp->status), rqstp->rq_vers);
127 
128 	nlmsvc_release_host(host);
129 	nlm_release_file(file);
130 	return rc;
131 }
132 
133 static __be32
134 nlmsvc_proc_test(struct svc_rqst *rqstp)
135 {
136 	return __nlmsvc_proc_test(rqstp, rqstp->rq_resp);
137 }
138 
139 static __be32
140 __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
141 {
142 	struct nlm_args *argp = rqstp->rq_argp;
143 	struct nlm_host	*host;
144 	struct nlm_file	*file;
145 	__be32 rc = rpc_success;
146 
147 	dprintk("lockd: LOCK          called\n");
148 
149 	resp->cookie = argp->cookie;
150 
151 	/* Obtain client and file */
152 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
153 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
154 
155 #if 0
156 	/* If supplied state doesn't match current state, we assume it's
157 	 * an old request that time-warped somehow. Any error return would
158 	 * do in this case because it's irrelevant anyway.
159 	 *
160 	 * NB: We don't retrieve the remote host's state yet.
161 	 */
162 	if (host->h_nsmstate && host->h_nsmstate != argp->state) {
163 		resp->status = nlm_lck_denied_nolocks;
164 	} else
165 #endif
166 
167 	/* Now try to lock the file */
168 	resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
169 					       argp->block, &argp->cookie,
170 					       argp->reclaim));
171 	if (resp->status == nlm_drop_reply)
172 		rc = rpc_drop_reply;
173 	else
174 		dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
175 
176 	nlmsvc_release_host(host);
177 	nlm_release_file(file);
178 	return rc;
179 }
180 
181 static __be32
182 nlmsvc_proc_lock(struct svc_rqst *rqstp)
183 {
184 	return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp);
185 }
186 
187 static __be32
188 __nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
189 {
190 	struct nlm_args *argp = rqstp->rq_argp;
191 	struct nlm_host	*host;
192 	struct nlm_file	*file;
193 	struct net *net = SVC_NET(rqstp);
194 
195 	dprintk("lockd: CANCEL        called\n");
196 
197 	resp->cookie = argp->cookie;
198 
199 	/* Don't accept requests during grace period */
200 	if (locks_in_grace(net)) {
201 		resp->status = nlm_lck_denied_grace_period;
202 		return rpc_success;
203 	}
204 
205 	/* Obtain client and file */
206 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
207 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
208 
209 	/* Try to cancel request. */
210 	resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
211 
212 	dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
213 	nlmsvc_release_host(host);
214 	nlm_release_file(file);
215 	return rpc_success;
216 }
217 
218 static __be32
219 nlmsvc_proc_cancel(struct svc_rqst *rqstp)
220 {
221 	return __nlmsvc_proc_cancel(rqstp, rqstp->rq_resp);
222 }
223 
224 /*
225  * UNLOCK: release a lock
226  */
227 static __be32
228 __nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
229 {
230 	struct nlm_args *argp = rqstp->rq_argp;
231 	struct nlm_host	*host;
232 	struct nlm_file	*file;
233 	struct net *net = SVC_NET(rqstp);
234 
235 	dprintk("lockd: UNLOCK        called\n");
236 
237 	resp->cookie = argp->cookie;
238 
239 	/* Don't accept new lock requests during grace period */
240 	if (locks_in_grace(net)) {
241 		resp->status = nlm_lck_denied_grace_period;
242 		return rpc_success;
243 	}
244 
245 	/* Obtain client and file */
246 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
247 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
248 
249 	/* Now try to remove the lock */
250 	resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
251 
252 	dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
253 	nlmsvc_release_host(host);
254 	nlm_release_file(file);
255 	return rpc_success;
256 }
257 
258 static __be32
259 nlmsvc_proc_unlock(struct svc_rqst *rqstp)
260 {
261 	return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp);
262 }
263 
264 /*
265  * GRANTED: A server calls us to tell that a process' lock request
266  * was granted
267  */
268 static __be32
269 __nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
270 {
271 	struct nlm_args *argp = rqstp->rq_argp;
272 
273 	resp->cookie = argp->cookie;
274 
275 	dprintk("lockd: GRANTED       called\n");
276 	resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
277 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
278 	return rpc_success;
279 }
280 
281 static __be32
282 nlmsvc_proc_granted(struct svc_rqst *rqstp)
283 {
284 	return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp);
285 }
286 
287 /*
288  * This is the generic lockd callback for async RPC calls
289  */
290 static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
291 {
292 	dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
293 			-task->tk_status);
294 }
295 
296 void nlmsvc_release_call(struct nlm_rqst *call)
297 {
298 	if (!refcount_dec_and_test(&call->a_count))
299 		return;
300 	nlmsvc_release_host(call->a_host);
301 	kfree(call);
302 }
303 
304 static void nlmsvc_callback_release(void *data)
305 {
306 	nlmsvc_release_call(data);
307 }
308 
309 static const struct rpc_call_ops nlmsvc_callback_ops = {
310 	.rpc_call_done = nlmsvc_callback_exit,
311 	.rpc_release = nlmsvc_callback_release,
312 };
313 
314 /*
315  * `Async' versions of the above service routines. They aren't really,
316  * because we send the callback before the reply proper. I hope this
317  * doesn't break any clients.
318  */
319 static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc,
320 		__be32 (*func)(struct svc_rqst *, struct nlm_res *))
321 {
322 	struct nlm_args *argp = rqstp->rq_argp;
323 	struct nlm_host	*host;
324 	struct nlm_rqst	*call;
325 	__be32 stat;
326 
327 	host = nlmsvc_lookup_host(rqstp,
328 				  argp->lock.caller,
329 				  argp->lock.len);
330 	if (host == NULL)
331 		return rpc_system_err;
332 
333 	call = nlm_alloc_call(host);
334 	nlmsvc_release_host(host);
335 	if (call == NULL)
336 		return rpc_system_err;
337 
338 	stat = func(rqstp, &call->a_res);
339 	if (stat != 0) {
340 		nlmsvc_release_call(call);
341 		return stat;
342 	}
343 
344 	call->a_flags = RPC_TASK_ASYNC;
345 	if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0)
346 		return rpc_system_err;
347 	return rpc_success;
348 }
349 
350 static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp)
351 {
352 	dprintk("lockd: TEST_MSG      called\n");
353 	return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, __nlmsvc_proc_test);
354 }
355 
356 static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp)
357 {
358 	dprintk("lockd: LOCK_MSG      called\n");
359 	return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, __nlmsvc_proc_lock);
360 }
361 
362 static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp)
363 {
364 	dprintk("lockd: CANCEL_MSG    called\n");
365 	return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, __nlmsvc_proc_cancel);
366 }
367 
368 static __be32
369 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp)
370 {
371 	dprintk("lockd: UNLOCK_MSG    called\n");
372 	return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlmsvc_proc_unlock);
373 }
374 
375 static __be32
376 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp)
377 {
378 	dprintk("lockd: GRANTED_MSG   called\n");
379 	return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, __nlmsvc_proc_granted);
380 }
381 
382 /*
383  * SHARE: create a DOS share or alter existing share.
384  */
385 static __be32
386 nlmsvc_proc_share(struct svc_rqst *rqstp)
387 {
388 	struct nlm_args *argp = rqstp->rq_argp;
389 	struct nlm_res *resp = rqstp->rq_resp;
390 	struct nlm_host	*host;
391 	struct nlm_file	*file;
392 
393 	dprintk("lockd: SHARE         called\n");
394 
395 	resp->cookie = argp->cookie;
396 
397 	/* Don't accept new lock requests during grace period */
398 	if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
399 		resp->status = nlm_lck_denied_grace_period;
400 		return rpc_success;
401 	}
402 
403 	/* Obtain client and file */
404 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
405 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
406 
407 	/* Now try to create the share */
408 	resp->status = cast_status(nlmsvc_share_file(host, file, argp));
409 
410 	dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
411 	nlmsvc_release_host(host);
412 	nlm_release_file(file);
413 	return rpc_success;
414 }
415 
416 /*
417  * UNSHARE: Release a DOS share.
418  */
419 static __be32
420 nlmsvc_proc_unshare(struct svc_rqst *rqstp)
421 {
422 	struct nlm_args *argp = rqstp->rq_argp;
423 	struct nlm_res *resp = rqstp->rq_resp;
424 	struct nlm_host	*host;
425 	struct nlm_file	*file;
426 
427 	dprintk("lockd: UNSHARE       called\n");
428 
429 	resp->cookie = argp->cookie;
430 
431 	/* Don't accept requests during grace period */
432 	if (locks_in_grace(SVC_NET(rqstp))) {
433 		resp->status = nlm_lck_denied_grace_period;
434 		return rpc_success;
435 	}
436 
437 	/* Obtain client and file */
438 	if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
439 		return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
440 
441 	/* Now try to unshare the file */
442 	resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
443 
444 	dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
445 	nlmsvc_release_host(host);
446 	nlm_release_file(file);
447 	return rpc_success;
448 }
449 
450 /*
451  * NM_LOCK: Create an unmonitored lock
452  */
453 static __be32
454 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
455 {
456 	struct nlm_args *argp = rqstp->rq_argp;
457 
458 	dprintk("lockd: NM_LOCK       called\n");
459 
460 	argp->monitor = 0;		/* just clean the monitor flag */
461 	return nlmsvc_proc_lock(rqstp);
462 }
463 
464 /*
465  * FREE_ALL: Release all locks and shares held by client
466  */
467 static __be32
468 nlmsvc_proc_free_all(struct svc_rqst *rqstp)
469 {
470 	struct nlm_args *argp = rqstp->rq_argp;
471 	struct nlm_host	*host;
472 
473 	/* Obtain client */
474 	if (nlmsvc_retrieve_args(rqstp, argp, &host, NULL))
475 		return rpc_success;
476 
477 	nlmsvc_free_host_resources(host);
478 	nlmsvc_release_host(host);
479 	return rpc_success;
480 }
481 
482 /*
483  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
484  */
485 static __be32
486 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
487 {
488 	struct nlm_reboot *argp = rqstp->rq_argp;
489 
490 	dprintk("lockd: SM_NOTIFY     called\n");
491 
492 	if (!nlm_privileged_requester(rqstp)) {
493 		char buf[RPC_MAX_ADDRBUFLEN];
494 		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
495 				svc_print_addr(rqstp, buf, sizeof(buf)));
496 		return rpc_system_err;
497 	}
498 
499 	nlm_host_rebooted(SVC_NET(rqstp), argp);
500 	return rpc_success;
501 }
502 
503 /*
504  * client sent a GRANTED_RES, let's remove the associated block
505  */
506 static __be32
507 nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
508 {
509 	struct nlm_res *argp = rqstp->rq_argp;
510 
511 	if (!nlmsvc_ops)
512 		return rpc_success;
513 
514 	dprintk("lockd: GRANTED_RES   called\n");
515 
516 	nlmsvc_grant_reply(&argp->cookie, argp->status);
517 	return rpc_success;
518 }
519 
520 /*
521  * NLM Server procedures.
522  */
523 
524 #define nlmsvc_encode_norep	nlmsvc_encode_void
525 #define nlmsvc_decode_norep	nlmsvc_decode_void
526 #define nlmsvc_decode_testres	nlmsvc_decode_void
527 #define nlmsvc_decode_lockres	nlmsvc_decode_void
528 #define nlmsvc_decode_unlockres	nlmsvc_decode_void
529 #define nlmsvc_decode_cancelres	nlmsvc_decode_void
530 #define nlmsvc_decode_grantedres	nlmsvc_decode_void
531 
532 #define nlmsvc_proc_none	nlmsvc_proc_null
533 #define nlmsvc_proc_test_res	nlmsvc_proc_null
534 #define nlmsvc_proc_lock_res	nlmsvc_proc_null
535 #define nlmsvc_proc_cancel_res	nlmsvc_proc_null
536 #define nlmsvc_proc_unlock_res	nlmsvc_proc_null
537 
538 struct nlm_void			{ int dummy; };
539 
540 #define PROC(name, xargt, xrest, argt, rest, respsize)	\
541  { .pc_func	= nlmsvc_proc_##name,			\
542    .pc_decode	= nlmsvc_decode_##xargt,		\
543    .pc_encode	= nlmsvc_encode_##xrest,		\
544    .pc_release	= NULL,					\
545    .pc_argsize	= sizeof(struct nlm_##argt),		\
546    .pc_ressize	= sizeof(struct nlm_##rest),		\
547    .pc_xdrressize = respsize,				\
548  }
549 
550 #define	Ck	(1+XDR_QUADLEN(NLM_MAXCOOKIELEN))	/* cookie */
551 #define	St	1				/* status */
552 #define	No	(1+1024/4)			/* Net Obj */
553 #define	Rg	2				/* range - offset + size */
554 
555 const struct svc_procedure nlmsvc_procedures[] = {
556   PROC(null,		void,		void,		void,	void, 1),
557   PROC(test,		testargs,	testres,	args,	res, Ck+St+2+No+Rg),
558   PROC(lock,		lockargs,	res,		args,	res, Ck+St),
559   PROC(cancel,		cancargs,	res,		args,	res, Ck+St),
560   PROC(unlock,		unlockargs,	res,		args,	res, Ck+St),
561   PROC(granted,		testargs,	res,		args,	res, Ck+St),
562   PROC(test_msg,	testargs,	norep,		args,	void, 1),
563   PROC(lock_msg,	lockargs,	norep,		args,	void, 1),
564   PROC(cancel_msg,	cancargs,	norep,		args,	void, 1),
565   PROC(unlock_msg,	unlockargs,	norep,		args,	void, 1),
566   PROC(granted_msg,	testargs,	norep,		args,	void, 1),
567   PROC(test_res,	testres,	norep,		res,	void, 1),
568   PROC(lock_res,	lockres,	norep,		res,	void, 1),
569   PROC(cancel_res,	cancelres,	norep,		res,	void, 1),
570   PROC(unlock_res,	unlockres,	norep,		res,	void, 1),
571   PROC(granted_res,	res,		norep,		res,	void, 1),
572   /* statd callback */
573   PROC(sm_notify,	reboot,		void,		reboot,	void, 1),
574   PROC(none,		void,		void,		void,	void, 1),
575   PROC(none,		void,		void,		void,	void, 1),
576   PROC(none,		void,		void,		void,	void, 1),
577   PROC(share,		shareargs,	shareres,	args,	res, Ck+St+1),
578   PROC(unshare,		shareargs,	shareres,	args,	res, Ck+St+1),
579   PROC(nm_lock,		lockargs,	res,		args,	res, Ck+St),
580   PROC(free_all,	notify,		void,		args,	void, 0),
581 
582 };
583