xref: /openbmc/linux/fs/lockd/clntxdr.c (revision d2ba09c1)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * linux/fs/lockd/clntxdr.c
4  *
5  * XDR functions to encode/decode NLM version 3 RPC arguments and results.
6  * NLM version 3 is backwards compatible with NLM versions 1 and 2.
7  *
8  * NLM client-side only.
9  *
10  * Copyright (C) 2010, Oracle.  All rights reserved.
11  */
12 
13 #include <linux/types.h>
14 #include <linux/sunrpc/xdr.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/stats.h>
17 #include <linux/lockd/lockd.h>
18 
19 #include <uapi/linux/nfs2.h>
20 
21 #define NLMDBG_FACILITY		NLMDBG_XDR
22 
23 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
24 #  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
25 #endif
26 
27 /*
28  * Declare the space requirements for NLM arguments and replies as
29  * number of 32bit-words
30  */
31 #define NLM_cookie_sz		(1+(NLM_MAXCOOKIELEN>>2))
32 #define NLM_caller_sz		(1+(NLMCLNT_OHSIZE>>2))
33 #define NLM_owner_sz		(1+(NLMCLNT_OHSIZE>>2))
34 #define NLM_fhandle_sz		(1+(NFS2_FHSIZE>>2))
35 #define NLM_lock_sz		(3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz)
36 #define NLM_holder_sz		(4+NLM_owner_sz)
37 
38 #define NLM_testargs_sz		(NLM_cookie_sz+1+NLM_lock_sz)
39 #define NLM_lockargs_sz		(NLM_cookie_sz+4+NLM_lock_sz)
40 #define NLM_cancargs_sz		(NLM_cookie_sz+2+NLM_lock_sz)
41 #define NLM_unlockargs_sz	(NLM_cookie_sz+NLM_lock_sz)
42 
43 #define NLM_testres_sz		(NLM_cookie_sz+1+NLM_holder_sz)
44 #define NLM_res_sz		(NLM_cookie_sz+1)
45 #define NLM_norep_sz		(0)
46 
47 
48 static s32 loff_t_to_s32(loff_t offset)
49 {
50 	s32 res;
51 
52 	if (offset >= NLM_OFFSET_MAX)
53 		res = NLM_OFFSET_MAX;
54 	else if (offset <= -NLM_OFFSET_MAX)
55 		res = -NLM_OFFSET_MAX;
56 	else
57 		res = offset;
58 	return res;
59 }
60 
61 static void nlm_compute_offsets(const struct nlm_lock *lock,
62 				u32 *l_offset, u32 *l_len)
63 {
64 	const struct file_lock *fl = &lock->fl;
65 
66 	*l_offset = loff_t_to_s32(fl->fl_start);
67 	if (fl->fl_end == OFFSET_MAX)
68 		*l_len = 0;
69 	else
70 		*l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
71 }
72 
73 /*
74  * Handle decode buffer overflows out-of-line.
75  */
76 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
77 {
78 	dprintk("lockd: %s prematurely hit the end of our receive buffer. "
79 		"Remaining buffer length is %tu words.\n",
80 		func, xdr->end - xdr->p);
81 }
82 
83 
84 /*
85  * Encode/decode NLMv3 basic data types
86  *
87  * Basic NLMv3 data types are not defined in an IETF standards
88  * document.  X/Open has a description of these data types that
89  * is useful.  See Chapter 10 of "Protocols for Interworking:
90  * XNFS, Version 3W".
91  *
92  * Not all basic data types have their own encoding and decoding
93  * functions.  For run-time efficiency, some data types are encoded
94  * or decoded inline.
95  */
96 
97 static void encode_bool(struct xdr_stream *xdr, const int value)
98 {
99 	__be32 *p;
100 
101 	p = xdr_reserve_space(xdr, 4);
102 	*p = value ? xdr_one : xdr_zero;
103 }
104 
105 static void encode_int32(struct xdr_stream *xdr, const s32 value)
106 {
107 	__be32 *p;
108 
109 	p = xdr_reserve_space(xdr, 4);
110 	*p = cpu_to_be32(value);
111 }
112 
113 /*
114  *	typedef opaque netobj<MAXNETOBJ_SZ>
115  */
116 static void encode_netobj(struct xdr_stream *xdr,
117 			  const u8 *data, const unsigned int length)
118 {
119 	__be32 *p;
120 
121 	p = xdr_reserve_space(xdr, 4 + length);
122 	xdr_encode_opaque(p, data, length);
123 }
124 
125 static int decode_netobj(struct xdr_stream *xdr,
126 			 struct xdr_netobj *obj)
127 {
128 	u32 length;
129 	__be32 *p;
130 
131 	p = xdr_inline_decode(xdr, 4);
132 	if (unlikely(p == NULL))
133 		goto out_overflow;
134 	length = be32_to_cpup(p++);
135 	if (unlikely(length > XDR_MAX_NETOBJ))
136 		goto out_size;
137 	obj->len = length;
138 	obj->data = (u8 *)p;
139 	return 0;
140 out_size:
141 	dprintk("NFS: returned netobj was too long: %u\n", length);
142 	return -EIO;
143 out_overflow:
144 	print_overflow_msg(__func__, xdr);
145 	return -EIO;
146 }
147 
148 /*
149  *	netobj cookie;
150  */
151 static void encode_cookie(struct xdr_stream *xdr,
152 			  const struct nlm_cookie *cookie)
153 {
154 	encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
155 }
156 
157 static int decode_cookie(struct xdr_stream *xdr,
158 			 struct nlm_cookie *cookie)
159 {
160 	u32 length;
161 	__be32 *p;
162 
163 	p = xdr_inline_decode(xdr, 4);
164 	if (unlikely(p == NULL))
165 		goto out_overflow;
166 	length = be32_to_cpup(p++);
167 	/* apparently HPUX can return empty cookies */
168 	if (length == 0)
169 		goto out_hpux;
170 	if (length > NLM_MAXCOOKIELEN)
171 		goto out_size;
172 	p = xdr_inline_decode(xdr, length);
173 	if (unlikely(p == NULL))
174 		goto out_overflow;
175 	cookie->len = length;
176 	memcpy(cookie->data, p, length);
177 	return 0;
178 out_hpux:
179 	cookie->len = 4;
180 	memset(cookie->data, 0, 4);
181 	return 0;
182 out_size:
183 	dprintk("NFS: returned cookie was too long: %u\n", length);
184 	return -EIO;
185 out_overflow:
186 	print_overflow_msg(__func__, xdr);
187 	return -EIO;
188 }
189 
190 /*
191  *	netobj fh;
192  */
193 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
194 {
195 	encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
196 }
197 
198 /*
199  *	enum nlm_stats {
200  *		LCK_GRANTED = 0,
201  *		LCK_DENIED = 1,
202  *		LCK_DENIED_NOLOCKS = 2,
203  *		LCK_BLOCKED = 3,
204  *		LCK_DENIED_GRACE_PERIOD = 4
205  *	};
206  *
207  *
208  *	struct nlm_stat {
209  *		nlm_stats stat;
210  *	};
211  *
212  * NB: we don't swap bytes for the NLM status values.  The upper
213  * layers deal directly with the status value in network byte
214  * order.
215  */
216 
217 static void encode_nlm_stat(struct xdr_stream *xdr,
218 			    const __be32 stat)
219 {
220 	__be32 *p;
221 
222 	WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
223 	p = xdr_reserve_space(xdr, 4);
224 	*p = stat;
225 }
226 
227 static int decode_nlm_stat(struct xdr_stream *xdr,
228 			   __be32 *stat)
229 {
230 	__be32 *p;
231 
232 	p = xdr_inline_decode(xdr, 4);
233 	if (unlikely(p == NULL))
234 		goto out_overflow;
235 	if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
236 		goto out_enum;
237 	*stat = *p;
238 	return 0;
239 out_enum:
240 	dprintk("%s: server returned invalid nlm_stats value: %u\n",
241 		__func__, be32_to_cpup(p));
242 	return -EIO;
243 out_overflow:
244 	print_overflow_msg(__func__, xdr);
245 	return -EIO;
246 }
247 
248 /*
249  *	struct nlm_holder {
250  *		bool exclusive;
251  *		int uppid;
252  *		netobj oh;
253  *		unsigned l_offset;
254  *		unsigned l_len;
255  *	};
256  */
257 static void encode_nlm_holder(struct xdr_stream *xdr,
258 			      const struct nlm_res *result)
259 {
260 	const struct nlm_lock *lock = &result->lock;
261 	u32 l_offset, l_len;
262 	__be32 *p;
263 
264 	encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
265 	encode_int32(xdr, lock->svid);
266 	encode_netobj(xdr, lock->oh.data, lock->oh.len);
267 
268 	p = xdr_reserve_space(xdr, 4 + 4);
269 	nlm_compute_offsets(lock, &l_offset, &l_len);
270 	*p++ = cpu_to_be32(l_offset);
271 	*p   = cpu_to_be32(l_len);
272 }
273 
274 static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
275 {
276 	struct nlm_lock *lock = &result->lock;
277 	struct file_lock *fl = &lock->fl;
278 	u32 exclusive, l_offset, l_len;
279 	int error;
280 	__be32 *p;
281 	s32 end;
282 
283 	memset(lock, 0, sizeof(*lock));
284 	locks_init_lock(fl);
285 
286 	p = xdr_inline_decode(xdr, 4 + 4);
287 	if (unlikely(p == NULL))
288 		goto out_overflow;
289 	exclusive = be32_to_cpup(p++);
290 	lock->svid = be32_to_cpup(p);
291 	fl->fl_pid = (pid_t)lock->svid;
292 
293 	error = decode_netobj(xdr, &lock->oh);
294 	if (unlikely(error))
295 		goto out;
296 
297 	p = xdr_inline_decode(xdr, 4 + 4);
298 	if (unlikely(p == NULL))
299 		goto out_overflow;
300 
301 	fl->fl_flags = FL_POSIX;
302 	fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
303 	l_offset = be32_to_cpup(p++);
304 	l_len = be32_to_cpup(p);
305 	end = l_offset + l_len - 1;
306 
307 	fl->fl_start = (loff_t)l_offset;
308 	if (l_len == 0 || end < 0)
309 		fl->fl_end = OFFSET_MAX;
310 	else
311 		fl->fl_end = (loff_t)end;
312 	error = 0;
313 out:
314 	return error;
315 out_overflow:
316 	print_overflow_msg(__func__, xdr);
317 	return -EIO;
318 }
319 
320 /*
321  *	string caller_name<LM_MAXSTRLEN>;
322  */
323 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
324 {
325 	/* NB: client-side does not set lock->len */
326 	u32 length = strlen(name);
327 	__be32 *p;
328 
329 	p = xdr_reserve_space(xdr, 4 + length);
330 	xdr_encode_opaque(p, name, length);
331 }
332 
333 /*
334  *	struct nlm_lock {
335  *		string caller_name<LM_MAXSTRLEN>;
336  *		netobj fh;
337  *		netobj oh;
338  *		int uppid;
339  *		unsigned l_offset;
340  *		unsigned l_len;
341  *	};
342  */
343 static void encode_nlm_lock(struct xdr_stream *xdr,
344 			    const struct nlm_lock *lock)
345 {
346 	u32 l_offset, l_len;
347 	__be32 *p;
348 
349 	encode_caller_name(xdr, lock->caller);
350 	encode_fh(xdr, &lock->fh);
351 	encode_netobj(xdr, lock->oh.data, lock->oh.len);
352 
353 	p = xdr_reserve_space(xdr, 4 + 4 + 4);
354 	*p++ = cpu_to_be32(lock->svid);
355 
356 	nlm_compute_offsets(lock, &l_offset, &l_len);
357 	*p++ = cpu_to_be32(l_offset);
358 	*p   = cpu_to_be32(l_len);
359 }
360 
361 
362 /*
363  * NLMv3 XDR encode functions
364  *
365  * NLMv3 argument types are defined in Chapter 10 of The Open Group's
366  * "Protocols for Interworking: XNFS, Version 3W".
367  */
368 
369 /*
370  *	struct nlm_testargs {
371  *		netobj cookie;
372  *		bool exclusive;
373  *		struct nlm_lock alock;
374  *	};
375  */
376 static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
377 				 struct xdr_stream *xdr,
378 				 const void *data)
379 {
380 	const struct nlm_args *args = data;
381 	const struct nlm_lock *lock = &args->lock;
382 
383 	encode_cookie(xdr, &args->cookie);
384 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
385 	encode_nlm_lock(xdr, lock);
386 }
387 
388 /*
389  *	struct nlm_lockargs {
390  *		netobj cookie;
391  *		bool block;
392  *		bool exclusive;
393  *		struct nlm_lock alock;
394  *		bool reclaim;
395  *		int state;
396  *	};
397  */
398 static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
399 				 struct xdr_stream *xdr,
400 				 const void *data)
401 {
402 	const struct nlm_args *args = data;
403 	const struct nlm_lock *lock = &args->lock;
404 
405 	encode_cookie(xdr, &args->cookie);
406 	encode_bool(xdr, args->block);
407 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
408 	encode_nlm_lock(xdr, lock);
409 	encode_bool(xdr, args->reclaim);
410 	encode_int32(xdr, args->state);
411 }
412 
413 /*
414  *	struct nlm_cancargs {
415  *		netobj cookie;
416  *		bool block;
417  *		bool exclusive;
418  *		struct nlm_lock alock;
419  *	};
420  */
421 static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
422 				 struct xdr_stream *xdr,
423 				 const void *data)
424 {
425 	const struct nlm_args *args = data;
426 	const struct nlm_lock *lock = &args->lock;
427 
428 	encode_cookie(xdr, &args->cookie);
429 	encode_bool(xdr, args->block);
430 	encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
431 	encode_nlm_lock(xdr, lock);
432 }
433 
434 /*
435  *	struct nlm_unlockargs {
436  *		netobj cookie;
437  *		struct nlm_lock alock;
438  *	};
439  */
440 static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
441 				   struct xdr_stream *xdr,
442 				   const void *data)
443 {
444 	const struct nlm_args *args = data;
445 	const struct nlm_lock *lock = &args->lock;
446 
447 	encode_cookie(xdr, &args->cookie);
448 	encode_nlm_lock(xdr, lock);
449 }
450 
451 /*
452  *	struct nlm_res {
453  *		netobj cookie;
454  *		nlm_stat stat;
455  *	};
456  */
457 static void nlm_xdr_enc_res(struct rpc_rqst *req,
458 			    struct xdr_stream *xdr,
459 			    const void *data)
460 {
461 	const struct nlm_res *result = data;
462 
463 	encode_cookie(xdr, &result->cookie);
464 	encode_nlm_stat(xdr, result->status);
465 }
466 
467 /*
468  *	union nlm_testrply switch (nlm_stats stat) {
469  *	case LCK_DENIED:
470  *		struct nlm_holder holder;
471  *	default:
472  *		void;
473  *	};
474  *
475  *	struct nlm_testres {
476  *		netobj cookie;
477  *		nlm_testrply test_stat;
478  *	};
479  */
480 static void encode_nlm_testrply(struct xdr_stream *xdr,
481 				const struct nlm_res *result)
482 {
483 	if (result->status == nlm_lck_denied)
484 		encode_nlm_holder(xdr, result);
485 }
486 
487 static void nlm_xdr_enc_testres(struct rpc_rqst *req,
488 				struct xdr_stream *xdr,
489 				const void *data)
490 {
491 	const struct nlm_res *result = data;
492 
493 	encode_cookie(xdr, &result->cookie);
494 	encode_nlm_stat(xdr, result->status);
495 	encode_nlm_testrply(xdr, result);
496 }
497 
498 
499 /*
500  * NLMv3 XDR decode functions
501  *
502  * NLMv3 result types are defined in Chapter 10 of The Open Group's
503  * "Protocols for Interworking: XNFS, Version 3W".
504  */
505 
506 /*
507  *	union nlm_testrply switch (nlm_stats stat) {
508  *	case LCK_DENIED:
509  *		struct nlm_holder holder;
510  *	default:
511  *		void;
512  *	};
513  *
514  *	struct nlm_testres {
515  *		netobj cookie;
516  *		nlm_testrply test_stat;
517  *	};
518  */
519 static int decode_nlm_testrply(struct xdr_stream *xdr,
520 			       struct nlm_res *result)
521 {
522 	int error;
523 
524 	error = decode_nlm_stat(xdr, &result->status);
525 	if (unlikely(error))
526 		goto out;
527 	if (result->status == nlm_lck_denied)
528 		error = decode_nlm_holder(xdr, result);
529 out:
530 	return error;
531 }
532 
533 static int nlm_xdr_dec_testres(struct rpc_rqst *req,
534 			       struct xdr_stream *xdr,
535 			       void *data)
536 {
537 	struct nlm_res *result = data;
538 	int error;
539 
540 	error = decode_cookie(xdr, &result->cookie);
541 	if (unlikely(error))
542 		goto out;
543 	error = decode_nlm_testrply(xdr, result);
544 out:
545 	return error;
546 }
547 
548 /*
549  *	struct nlm_res {
550  *		netobj cookie;
551  *		nlm_stat stat;
552  *	};
553  */
554 static int nlm_xdr_dec_res(struct rpc_rqst *req,
555 			   struct xdr_stream *xdr,
556 			   void *data)
557 {
558 	struct nlm_res *result = data;
559 	int error;
560 
561 	error = decode_cookie(xdr, &result->cookie);
562 	if (unlikely(error))
563 		goto out;
564 	error = decode_nlm_stat(xdr, &result->status);
565 out:
566 	return error;
567 }
568 
569 
570 /*
571  * For NLM, a void procedure really returns nothing
572  */
573 #define nlm_xdr_dec_norep	NULL
574 
575 #define PROC(proc, argtype, restype)	\
576 [NLMPROC_##proc] = {							\
577 	.p_proc      = NLMPROC_##proc,					\
578 	.p_encode    = nlm_xdr_enc_##argtype,		\
579 	.p_decode    = nlm_xdr_dec_##restype,				\
580 	.p_arglen    = NLM_##argtype##_sz,				\
581 	.p_replen    = NLM_##restype##_sz,				\
582 	.p_statidx   = NLMPROC_##proc,					\
583 	.p_name      = #proc,						\
584 	}
585 
586 static const struct rpc_procinfo nlm_procedures[] = {
587 	PROC(TEST,		testargs,	testres),
588 	PROC(LOCK,		lockargs,	res),
589 	PROC(CANCEL,		cancargs,	res),
590 	PROC(UNLOCK,		unlockargs,	res),
591 	PROC(GRANTED,		testargs,	res),
592 	PROC(TEST_MSG,		testargs,	norep),
593 	PROC(LOCK_MSG,		lockargs,	norep),
594 	PROC(CANCEL_MSG,	cancargs,	norep),
595 	PROC(UNLOCK_MSG,	unlockargs,	norep),
596 	PROC(GRANTED_MSG,	testargs,	norep),
597 	PROC(TEST_RES,		testres,	norep),
598 	PROC(LOCK_RES,		res,		norep),
599 	PROC(CANCEL_RES,	res,		norep),
600 	PROC(UNLOCK_RES,	res,		norep),
601 	PROC(GRANTED_RES,	res,		norep),
602 };
603 
604 static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)];
605 static const struct rpc_version	nlm_version1 = {
606 	.number		= 1,
607 	.nrprocs	= ARRAY_SIZE(nlm_procedures),
608 	.procs		= nlm_procedures,
609 	.counts		= nlm_version1_counts,
610 };
611 
612 static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)];
613 static const struct rpc_version	nlm_version3 = {
614 	.number		= 3,
615 	.nrprocs	= ARRAY_SIZE(nlm_procedures),
616 	.procs		= nlm_procedures,
617 	.counts		= nlm_version3_counts,
618 };
619 
620 static const struct rpc_version	*nlm_versions[] = {
621 	[1] = &nlm_version1,
622 	[3] = &nlm_version3,
623 #ifdef CONFIG_LOCKD_V4
624 	[4] = &nlm_version4,
625 #endif
626 };
627 
628 static struct rpc_stat		nlm_rpc_stats;
629 
630 const struct rpc_program	nlm_program = {
631 	.name		= "lockd",
632 	.number		= NLM_PROGRAM,
633 	.nrvers		= ARRAY_SIZE(nlm_versions),
634 	.version	= nlm_versions,
635 	.stats		= &nlm_rpc_stats,
636 };
637