projects/linux·blob master · refs

614 lines · 13.3 KiB

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