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