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