linux/fs/lockd/clntxdr.c
<<
>>
Prefs
   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};
 627