Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.20-rc2 636 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 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; 140out_size: 141 dprintk("NFS: returned netobj was too long: %u\n", length); 142 return -EIO; 143out_overflow: 144 print_overflow_msg(__func__, xdr); 145 return -EIO; 146} 147 148/* 149 * netobj cookie; 150 */ 151static 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 157static 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; 178out_hpux: 179 cookie->len = 4; 180 memset(cookie->data, 0, 4); 181 return 0; 182out_size: 183 dprintk("NFS: returned cookie was too long: %u\n", length); 184 return -EIO; 185out_overflow: 186 print_overflow_msg(__func__, xdr); 187 return -EIO; 188} 189 190/* 191 * netobj fh; 192 */ 193static 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 217static 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 227static 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; 239out_enum: 240 dprintk("%s: server returned invalid nlm_stats value: %u\n", 241 __func__, be32_to_cpup(p)); 242 return -EIO; 243out_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 */ 257static 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 274static 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; 313out: 314 return error; 315out_overflow: 316 print_overflow_msg(__func__, xdr); 317 return -EIO; 318} 319 320/* 321 * string caller_name<LM_MAXSTRLEN>; 322 */ 323static 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 */ 343static 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 */ 376static 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 */ 398static 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 */ 421static 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 */ 440static 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 */ 457static 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 */ 480static 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 487static 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 */ 519static 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); 529out: 530 return error; 531} 532 533static 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); 544out: 545 return error; 546} 547 548/* 549 * struct nlm_res { 550 * netobj cookie; 551 * nlm_stat stat; 552 * }; 553 */ 554static 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); 565out: 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 586static 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 604static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)]; 605static 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 612static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)]; 613static 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 620static 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 628static struct rpc_stat nlm_rpc_stats; 629 630const 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};