Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.0-rc8 626 lines 14 kB view raw
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 48static 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 61static 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 */ 76static 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 97static 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 105static 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 */ 116static 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 125static int decode_netobj(struct xdr_stream *xdr, 126 struct xdr_netobj *obj) 127{ 128 ssize_t ret; 129 130 ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data, 131 XDR_MAX_NETOBJ); 132 if (unlikely(ret < 0)) 133 return -EIO; 134 obj->len = ret; 135 return 0; 136} 137 138/* 139 * netobj cookie; 140 */ 141static void encode_cookie(struct xdr_stream *xdr, 142 const struct nlm_cookie *cookie) 143{ 144 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 145} 146 147static int decode_cookie(struct xdr_stream *xdr, 148 struct nlm_cookie *cookie) 149{ 150 u32 length; 151 __be32 *p; 152 153 p = xdr_inline_decode(xdr, 4); 154 if (unlikely(p == NULL)) 155 goto out_overflow; 156 length = be32_to_cpup(p++); 157 /* apparently HPUX can return empty cookies */ 158 if (length == 0) 159 goto out_hpux; 160 if (length > NLM_MAXCOOKIELEN) 161 goto out_size; 162 p = xdr_inline_decode(xdr, length); 163 if (unlikely(p == NULL)) 164 goto out_overflow; 165 cookie->len = length; 166 memcpy(cookie->data, p, length); 167 return 0; 168out_hpux: 169 cookie->len = 4; 170 memset(cookie->data, 0, 4); 171 return 0; 172out_size: 173 dprintk("NFS: returned cookie was too long: %u\n", length); 174 return -EIO; 175out_overflow: 176 print_overflow_msg(__func__, xdr); 177 return -EIO; 178} 179 180/* 181 * netobj fh; 182 */ 183static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 184{ 185 encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE); 186} 187 188/* 189 * enum nlm_stats { 190 * LCK_GRANTED = 0, 191 * LCK_DENIED = 1, 192 * LCK_DENIED_NOLOCKS = 2, 193 * LCK_BLOCKED = 3, 194 * LCK_DENIED_GRACE_PERIOD = 4 195 * }; 196 * 197 * 198 * struct nlm_stat { 199 * nlm_stats stat; 200 * }; 201 * 202 * NB: we don't swap bytes for the NLM status values. The upper 203 * layers deal directly with the status value in network byte 204 * order. 205 */ 206 207static void encode_nlm_stat(struct xdr_stream *xdr, 208 const __be32 stat) 209{ 210 __be32 *p; 211 212 WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); 213 p = xdr_reserve_space(xdr, 4); 214 *p = stat; 215} 216 217static int decode_nlm_stat(struct xdr_stream *xdr, 218 __be32 *stat) 219{ 220 __be32 *p; 221 222 p = xdr_inline_decode(xdr, 4); 223 if (unlikely(p == NULL)) 224 goto out_overflow; 225 if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period))) 226 goto out_enum; 227 *stat = *p; 228 return 0; 229out_enum: 230 dprintk("%s: server returned invalid nlm_stats value: %u\n", 231 __func__, be32_to_cpup(p)); 232 return -EIO; 233out_overflow: 234 print_overflow_msg(__func__, xdr); 235 return -EIO; 236} 237 238/* 239 * struct nlm_holder { 240 * bool exclusive; 241 * int uppid; 242 * netobj oh; 243 * unsigned l_offset; 244 * unsigned l_len; 245 * }; 246 */ 247static void encode_nlm_holder(struct xdr_stream *xdr, 248 const struct nlm_res *result) 249{ 250 const struct nlm_lock *lock = &result->lock; 251 u32 l_offset, l_len; 252 __be32 *p; 253 254 encode_bool(xdr, lock->fl.fl_type == F_RDLCK); 255 encode_int32(xdr, lock->svid); 256 encode_netobj(xdr, lock->oh.data, lock->oh.len); 257 258 p = xdr_reserve_space(xdr, 4 + 4); 259 nlm_compute_offsets(lock, &l_offset, &l_len); 260 *p++ = cpu_to_be32(l_offset); 261 *p = cpu_to_be32(l_len); 262} 263 264static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result) 265{ 266 struct nlm_lock *lock = &result->lock; 267 struct file_lock *fl = &lock->fl; 268 u32 exclusive, l_offset, l_len; 269 int error; 270 __be32 *p; 271 s32 end; 272 273 memset(lock, 0, sizeof(*lock)); 274 locks_init_lock(fl); 275 276 p = xdr_inline_decode(xdr, 4 + 4); 277 if (unlikely(p == NULL)) 278 goto out_overflow; 279 exclusive = be32_to_cpup(p++); 280 lock->svid = be32_to_cpup(p); 281 fl->fl_pid = (pid_t)lock->svid; 282 283 error = decode_netobj(xdr, &lock->oh); 284 if (unlikely(error)) 285 goto out; 286 287 p = xdr_inline_decode(xdr, 4 + 4); 288 if (unlikely(p == NULL)) 289 goto out_overflow; 290 291 fl->fl_flags = FL_POSIX; 292 fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; 293 l_offset = be32_to_cpup(p++); 294 l_len = be32_to_cpup(p); 295 end = l_offset + l_len - 1; 296 297 fl->fl_start = (loff_t)l_offset; 298 if (l_len == 0 || end < 0) 299 fl->fl_end = OFFSET_MAX; 300 else 301 fl->fl_end = (loff_t)end; 302 error = 0; 303out: 304 return error; 305out_overflow: 306 print_overflow_msg(__func__, xdr); 307 return -EIO; 308} 309 310/* 311 * string caller_name<LM_MAXSTRLEN>; 312 */ 313static void encode_caller_name(struct xdr_stream *xdr, const char *name) 314{ 315 /* NB: client-side does not set lock->len */ 316 u32 length = strlen(name); 317 __be32 *p; 318 319 p = xdr_reserve_space(xdr, 4 + length); 320 xdr_encode_opaque(p, name, length); 321} 322 323/* 324 * struct nlm_lock { 325 * string caller_name<LM_MAXSTRLEN>; 326 * netobj fh; 327 * netobj oh; 328 * int uppid; 329 * unsigned l_offset; 330 * unsigned l_len; 331 * }; 332 */ 333static void encode_nlm_lock(struct xdr_stream *xdr, 334 const struct nlm_lock *lock) 335{ 336 u32 l_offset, l_len; 337 __be32 *p; 338 339 encode_caller_name(xdr, lock->caller); 340 encode_fh(xdr, &lock->fh); 341 encode_netobj(xdr, lock->oh.data, lock->oh.len); 342 343 p = xdr_reserve_space(xdr, 4 + 4 + 4); 344 *p++ = cpu_to_be32(lock->svid); 345 346 nlm_compute_offsets(lock, &l_offset, &l_len); 347 *p++ = cpu_to_be32(l_offset); 348 *p = cpu_to_be32(l_len); 349} 350 351 352/* 353 * NLMv3 XDR encode functions 354 * 355 * NLMv3 argument types are defined in Chapter 10 of The Open Group's 356 * "Protocols for Interworking: XNFS, Version 3W". 357 */ 358 359/* 360 * struct nlm_testargs { 361 * netobj cookie; 362 * bool exclusive; 363 * struct nlm_lock alock; 364 * }; 365 */ 366static void nlm_xdr_enc_testargs(struct rpc_rqst *req, 367 struct xdr_stream *xdr, 368 const void *data) 369{ 370 const struct nlm_args *args = data; 371 const struct nlm_lock *lock = &args->lock; 372 373 encode_cookie(xdr, &args->cookie); 374 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 375 encode_nlm_lock(xdr, lock); 376} 377 378/* 379 * struct nlm_lockargs { 380 * netobj cookie; 381 * bool block; 382 * bool exclusive; 383 * struct nlm_lock alock; 384 * bool reclaim; 385 * int state; 386 * }; 387 */ 388static void nlm_xdr_enc_lockargs(struct rpc_rqst *req, 389 struct xdr_stream *xdr, 390 const void *data) 391{ 392 const struct nlm_args *args = data; 393 const struct nlm_lock *lock = &args->lock; 394 395 encode_cookie(xdr, &args->cookie); 396 encode_bool(xdr, args->block); 397 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 398 encode_nlm_lock(xdr, lock); 399 encode_bool(xdr, args->reclaim); 400 encode_int32(xdr, args->state); 401} 402 403/* 404 * struct nlm_cancargs { 405 * netobj cookie; 406 * bool block; 407 * bool exclusive; 408 * struct nlm_lock alock; 409 * }; 410 */ 411static void nlm_xdr_enc_cancargs(struct rpc_rqst *req, 412 struct xdr_stream *xdr, 413 const void *data) 414{ 415 const struct nlm_args *args = data; 416 const struct nlm_lock *lock = &args->lock; 417 418 encode_cookie(xdr, &args->cookie); 419 encode_bool(xdr, args->block); 420 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 421 encode_nlm_lock(xdr, lock); 422} 423 424/* 425 * struct nlm_unlockargs { 426 * netobj cookie; 427 * struct nlm_lock alock; 428 * }; 429 */ 430static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req, 431 struct xdr_stream *xdr, 432 const void *data) 433{ 434 const struct nlm_args *args = data; 435 const struct nlm_lock *lock = &args->lock; 436 437 encode_cookie(xdr, &args->cookie); 438 encode_nlm_lock(xdr, lock); 439} 440 441/* 442 * struct nlm_res { 443 * netobj cookie; 444 * nlm_stat stat; 445 * }; 446 */ 447static void nlm_xdr_enc_res(struct rpc_rqst *req, 448 struct xdr_stream *xdr, 449 const void *data) 450{ 451 const struct nlm_res *result = data; 452 453 encode_cookie(xdr, &result->cookie); 454 encode_nlm_stat(xdr, result->status); 455} 456 457/* 458 * union nlm_testrply switch (nlm_stats stat) { 459 * case LCK_DENIED: 460 * struct nlm_holder holder; 461 * default: 462 * void; 463 * }; 464 * 465 * struct nlm_testres { 466 * netobj cookie; 467 * nlm_testrply test_stat; 468 * }; 469 */ 470static void encode_nlm_testrply(struct xdr_stream *xdr, 471 const struct nlm_res *result) 472{ 473 if (result->status == nlm_lck_denied) 474 encode_nlm_holder(xdr, result); 475} 476 477static void nlm_xdr_enc_testres(struct rpc_rqst *req, 478 struct xdr_stream *xdr, 479 const void *data) 480{ 481 const struct nlm_res *result = data; 482 483 encode_cookie(xdr, &result->cookie); 484 encode_nlm_stat(xdr, result->status); 485 encode_nlm_testrply(xdr, result); 486} 487 488 489/* 490 * NLMv3 XDR decode functions 491 * 492 * NLMv3 result types are defined in Chapter 10 of The Open Group's 493 * "Protocols for Interworking: XNFS, Version 3W". 494 */ 495 496/* 497 * union nlm_testrply switch (nlm_stats stat) { 498 * case LCK_DENIED: 499 * struct nlm_holder holder; 500 * default: 501 * void; 502 * }; 503 * 504 * struct nlm_testres { 505 * netobj cookie; 506 * nlm_testrply test_stat; 507 * }; 508 */ 509static int decode_nlm_testrply(struct xdr_stream *xdr, 510 struct nlm_res *result) 511{ 512 int error; 513 514 error = decode_nlm_stat(xdr, &result->status); 515 if (unlikely(error)) 516 goto out; 517 if (result->status == nlm_lck_denied) 518 error = decode_nlm_holder(xdr, result); 519out: 520 return error; 521} 522 523static int nlm_xdr_dec_testres(struct rpc_rqst *req, 524 struct xdr_stream *xdr, 525 void *data) 526{ 527 struct nlm_res *result = data; 528 int error; 529 530 error = decode_cookie(xdr, &result->cookie); 531 if (unlikely(error)) 532 goto out; 533 error = decode_nlm_testrply(xdr, result); 534out: 535 return error; 536} 537 538/* 539 * struct nlm_res { 540 * netobj cookie; 541 * nlm_stat stat; 542 * }; 543 */ 544static int nlm_xdr_dec_res(struct rpc_rqst *req, 545 struct xdr_stream *xdr, 546 void *data) 547{ 548 struct nlm_res *result = data; 549 int error; 550 551 error = decode_cookie(xdr, &result->cookie); 552 if (unlikely(error)) 553 goto out; 554 error = decode_nlm_stat(xdr, &result->status); 555out: 556 return error; 557} 558 559 560/* 561 * For NLM, a void procedure really returns nothing 562 */ 563#define nlm_xdr_dec_norep NULL 564 565#define PROC(proc, argtype, restype) \ 566[NLMPROC_##proc] = { \ 567 .p_proc = NLMPROC_##proc, \ 568 .p_encode = nlm_xdr_enc_##argtype, \ 569 .p_decode = nlm_xdr_dec_##restype, \ 570 .p_arglen = NLM_##argtype##_sz, \ 571 .p_replen = NLM_##restype##_sz, \ 572 .p_statidx = NLMPROC_##proc, \ 573 .p_name = #proc, \ 574 } 575 576static const struct rpc_procinfo nlm_procedures[] = { 577 PROC(TEST, testargs, testres), 578 PROC(LOCK, lockargs, res), 579 PROC(CANCEL, cancargs, res), 580 PROC(UNLOCK, unlockargs, res), 581 PROC(GRANTED, testargs, res), 582 PROC(TEST_MSG, testargs, norep), 583 PROC(LOCK_MSG, lockargs, norep), 584 PROC(CANCEL_MSG, cancargs, norep), 585 PROC(UNLOCK_MSG, unlockargs, norep), 586 PROC(GRANTED_MSG, testargs, norep), 587 PROC(TEST_RES, testres, norep), 588 PROC(LOCK_RES, res, norep), 589 PROC(CANCEL_RES, res, norep), 590 PROC(UNLOCK_RES, res, norep), 591 PROC(GRANTED_RES, res, norep), 592}; 593 594static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)]; 595static const struct rpc_version nlm_version1 = { 596 .number = 1, 597 .nrprocs = ARRAY_SIZE(nlm_procedures), 598 .procs = nlm_procedures, 599 .counts = nlm_version1_counts, 600}; 601 602static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)]; 603static const struct rpc_version nlm_version3 = { 604 .number = 3, 605 .nrprocs = ARRAY_SIZE(nlm_procedures), 606 .procs = nlm_procedures, 607 .counts = nlm_version3_counts, 608}; 609 610static const struct rpc_version *nlm_versions[] = { 611 [1] = &nlm_version1, 612 [3] = &nlm_version3, 613#ifdef CONFIG_LOCKD_V4 614 [4] = &nlm_version4, 615#endif 616}; 617 618static struct rpc_stat nlm_rpc_stats; 619 620const struct rpc_program nlm_program = { 621 .name = "lockd", 622 .number = NLM_PROGRAM, 623 .nrvers = ARRAY_SIZE(nlm_versions), 624 .version = nlm_versions, 625 .stats = &nlm_rpc_stats, 626};