linux/fs/nfs/callback_xdr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/fs/nfs/callback_xdr.c
   4 *
   5 * Copyright (C) 2004 Trond Myklebust
   6 *
   7 * NFSv4 callback encode/decode procedures
   8 */
   9#include <linux/kernel.h>
  10#include <linux/sunrpc/svc.h>
  11#include <linux/nfs4.h>
  12#include <linux/nfs_fs.h>
  13#include <linux/ratelimit.h>
  14#include <linux/printk.h>
  15#include <linux/slab.h>
  16#include <linux/sunrpc/bc_xprt.h>
  17#include "nfs4_fs.h"
  18#include "callback.h"
  19#include "internal.h"
  20#include "nfs4session.h"
  21#include "nfs4trace.h"
  22
  23#define CB_OP_TAGLEN_MAXSZ              (512)
  24#define CB_OP_HDR_RES_MAXSZ             (2 * 4) // opcode, status
  25#define CB_OP_GETATTR_BITMAP_MAXSZ      (4 * 4) // bitmap length, 3 bitmaps
  26#define CB_OP_GETATTR_RES_MAXSZ         (CB_OP_HDR_RES_MAXSZ + \
  27                                         CB_OP_GETATTR_BITMAP_MAXSZ + \
  28                                         /* change, size, ctime, mtime */\
  29                                         (2 + 2 + 3 + 3) * 4)
  30#define CB_OP_RECALL_RES_MAXSZ          (CB_OP_HDR_RES_MAXSZ)
  31
  32#if defined(CONFIG_NFS_V4_1)
  33#define CB_OP_LAYOUTRECALL_RES_MAXSZ    (CB_OP_HDR_RES_MAXSZ)
  34#define CB_OP_DEVICENOTIFY_RES_MAXSZ    (CB_OP_HDR_RES_MAXSZ)
  35#define CB_OP_SEQUENCE_RES_MAXSZ        (CB_OP_HDR_RES_MAXSZ + \
  36                                         NFS4_MAX_SESSIONID_LEN + \
  37                                         (1 + 3) * 4) // seqid, 3 slotids
  38#define CB_OP_RECALLANY_RES_MAXSZ       (CB_OP_HDR_RES_MAXSZ)
  39#define CB_OP_RECALLSLOT_RES_MAXSZ      (CB_OP_HDR_RES_MAXSZ)
  40#define CB_OP_NOTIFY_LOCK_RES_MAXSZ     (CB_OP_HDR_RES_MAXSZ)
  41#endif /* CONFIG_NFS_V4_1 */
  42#ifdef CONFIG_NFS_V4_2
  43#define CB_OP_OFFLOAD_RES_MAXSZ         (CB_OP_HDR_RES_MAXSZ)
  44#endif /* CONFIG_NFS_V4_2 */
  45
  46#define NFSDBG_FACILITY NFSDBG_CALLBACK
  47
  48/* Internal error code */
  49#define NFS4ERR_RESOURCE_HDR    11050
  50
  51struct callback_op {
  52        __be32 (*process_op)(void *, void *, struct cb_process_state *);
  53        __be32 (*decode_args)(struct svc_rqst *, struct xdr_stream *, void *);
  54        __be32 (*encode_res)(struct svc_rqst *, struct xdr_stream *,
  55                        const void *);
  56        long res_maxsize;
  57};
  58
  59static struct callback_op callback_ops[];
  60
  61static __be32 nfs4_callback_null(struct svc_rqst *rqstp)
  62{
  63        return htonl(NFS4_OK);
  64}
  65
  66/*
  67 * svc_process_common() looks for an XDR encoder to know when
  68 * not to drop a Reply.
  69 */
  70static int nfs4_encode_void(struct svc_rqst *rqstp, __be32 *p)
  71{
  72        return xdr_ressize_check(rqstp, p);
  73}
  74
  75static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
  76                const char **str, size_t maxlen)
  77{
  78        ssize_t err;
  79
  80        err = xdr_stream_decode_opaque_inline(xdr, (void **)str, maxlen);
  81        if (err < 0)
  82                return cpu_to_be32(NFS4ERR_RESOURCE);
  83        *len = err;
  84        return 0;
  85}
  86
  87static __be32 decode_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
  88{
  89        __be32 *p;
  90
  91        p = xdr_inline_decode(xdr, 4);
  92        if (unlikely(p == NULL))
  93                return htonl(NFS4ERR_RESOURCE);
  94        fh->size = ntohl(*p);
  95        if (fh->size > NFS4_FHSIZE)
  96                return htonl(NFS4ERR_BADHANDLE);
  97        p = xdr_inline_decode(xdr, fh->size);
  98        if (unlikely(p == NULL))
  99                return htonl(NFS4ERR_RESOURCE);
 100        memcpy(&fh->data[0], p, fh->size);
 101        memset(&fh->data[fh->size], 0, sizeof(fh->data) - fh->size);
 102        return 0;
 103}
 104
 105static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 106{
 107        __be32 *p;
 108        unsigned int attrlen;
 109
 110        p = xdr_inline_decode(xdr, 4);
 111        if (unlikely(p == NULL))
 112                return htonl(NFS4ERR_RESOURCE);
 113        attrlen = ntohl(*p);
 114        p = xdr_inline_decode(xdr, attrlen << 2);
 115        if (unlikely(p == NULL))
 116                return htonl(NFS4ERR_RESOURCE);
 117        if (likely(attrlen > 0))
 118                bitmap[0] = ntohl(*p++);
 119        if (attrlen > 1)
 120                bitmap[1] = ntohl(*p);
 121        return 0;
 122}
 123
 124static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 125{
 126        __be32 *p;
 127
 128        p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE);
 129        if (unlikely(p == NULL))
 130                return htonl(NFS4ERR_RESOURCE);
 131        memcpy(stateid->data, p, NFS4_STATEID_SIZE);
 132        return 0;
 133}
 134
 135static __be32 decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 136{
 137        stateid->type = NFS4_DELEGATION_STATEID_TYPE;
 138        return decode_stateid(xdr, stateid);
 139}
 140
 141static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
 142{
 143        __be32 *p;
 144        __be32 status;
 145
 146        status = decode_string(xdr, &hdr->taglen, &hdr->tag, CB_OP_TAGLEN_MAXSZ);
 147        if (unlikely(status != 0))
 148                return status;
 149        p = xdr_inline_decode(xdr, 12);
 150        if (unlikely(p == NULL))
 151                return htonl(NFS4ERR_RESOURCE);
 152        hdr->minorversion = ntohl(*p++);
 153        /* Check for minor version support */
 154        if (hdr->minorversion <= NFS4_MAX_MINOR_VERSION) {
 155                hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 and v4.2 */
 156        } else {
 157                pr_warn_ratelimited("NFS: %s: NFSv4 server callback with "
 158                        "illegal minor version %u!\n",
 159                        __func__, hdr->minorversion);
 160                return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 161        }
 162        hdr->nops = ntohl(*p);
 163        return 0;
 164}
 165
 166static __be32 decode_op_hdr(struct xdr_stream *xdr, unsigned int *op)
 167{
 168        __be32 *p;
 169        p = xdr_inline_decode(xdr, 4);
 170        if (unlikely(p == NULL))
 171                return htonl(NFS4ERR_RESOURCE_HDR);
 172        *op = ntohl(*p);
 173        return 0;
 174}
 175
 176static __be32 decode_getattr_args(struct svc_rqst *rqstp,
 177                struct xdr_stream *xdr, void *argp)
 178{
 179        struct cb_getattrargs *args = argp;
 180        __be32 status;
 181
 182        status = decode_fh(xdr, &args->fh);
 183        if (unlikely(status != 0))
 184                return status;
 185        return decode_bitmap(xdr, args->bitmap);
 186}
 187
 188static __be32 decode_recall_args(struct svc_rqst *rqstp,
 189                struct xdr_stream *xdr, void *argp)
 190{
 191        struct cb_recallargs *args = argp;
 192        __be32 *p;
 193        __be32 status;
 194
 195        status = decode_delegation_stateid(xdr, &args->stateid);
 196        if (unlikely(status != 0))
 197                return status;
 198        p = xdr_inline_decode(xdr, 4);
 199        if (unlikely(p == NULL))
 200                return htonl(NFS4ERR_RESOURCE);
 201        args->truncate = ntohl(*p);
 202        return decode_fh(xdr, &args->fh);
 203}
 204
 205#if defined(CONFIG_NFS_V4_1)
 206static __be32 decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 207{
 208        stateid->type = NFS4_LAYOUT_STATEID_TYPE;
 209        return decode_stateid(xdr, stateid);
 210}
 211
 212static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
 213                                       struct xdr_stream *xdr, void *argp)
 214{
 215        struct cb_layoutrecallargs *args = argp;
 216        __be32 *p;
 217        __be32 status = 0;
 218        uint32_t iomode;
 219
 220        p = xdr_inline_decode(xdr, 4 * sizeof(uint32_t));
 221        if (unlikely(p == NULL))
 222                return htonl(NFS4ERR_BADXDR);
 223
 224        args->cbl_layout_type = ntohl(*p++);
 225        /* Depite the spec's xdr, iomode really belongs in the FILE switch,
 226         * as it is unusable and ignored with the other types.
 227         */
 228        iomode = ntohl(*p++);
 229        args->cbl_layoutchanged = ntohl(*p++);
 230        args->cbl_recall_type = ntohl(*p++);
 231
 232        if (args->cbl_recall_type == RETURN_FILE) {
 233                args->cbl_range.iomode = iomode;
 234                status = decode_fh(xdr, &args->cbl_fh);
 235                if (unlikely(status != 0))
 236                        return status;
 237
 238                p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t));
 239                if (unlikely(p == NULL))
 240                        return htonl(NFS4ERR_BADXDR);
 241                p = xdr_decode_hyper(p, &args->cbl_range.offset);
 242                p = xdr_decode_hyper(p, &args->cbl_range.length);
 243                return decode_layout_stateid(xdr, &args->cbl_stateid);
 244        } else if (args->cbl_recall_type == RETURN_FSID) {
 245                p = xdr_inline_decode(xdr, 2 * sizeof(uint64_t));
 246                if (unlikely(p == NULL))
 247                        return htonl(NFS4ERR_BADXDR);
 248                p = xdr_decode_hyper(p, &args->cbl_fsid.major);
 249                p = xdr_decode_hyper(p, &args->cbl_fsid.minor);
 250        } else if (args->cbl_recall_type != RETURN_ALL)
 251                return htonl(NFS4ERR_BADXDR);
 252        return 0;
 253}
 254
 255static
 256__be32 decode_devicenotify_args(struct svc_rqst *rqstp,
 257                                struct xdr_stream *xdr,
 258                                void *argp)
 259{
 260        struct cb_devicenotifyargs *args = argp;
 261        __be32 *p;
 262        __be32 status = 0;
 263        u32 tmp;
 264        int n, i;
 265        args->ndevs = 0;
 266
 267        /* Num of device notifications */
 268        p = xdr_inline_decode(xdr, sizeof(uint32_t));
 269        if (unlikely(p == NULL)) {
 270                status = htonl(NFS4ERR_BADXDR);
 271                goto out;
 272        }
 273        n = ntohl(*p++);
 274        if (n <= 0)
 275                goto out;
 276        if (n > ULONG_MAX / sizeof(*args->devs)) {
 277                status = htonl(NFS4ERR_BADXDR);
 278                goto out;
 279        }
 280
 281        args->devs = kmalloc_array(n, sizeof(*args->devs), GFP_KERNEL);
 282        if (!args->devs) {
 283                status = htonl(NFS4ERR_DELAY);
 284                goto out;
 285        }
 286
 287        /* Decode each dev notification */
 288        for (i = 0; i < n; i++) {
 289                struct cb_devicenotifyitem *dev = &args->devs[i];
 290
 291                p = xdr_inline_decode(xdr, (4 * sizeof(uint32_t)) +
 292                                      NFS4_DEVICEID4_SIZE);
 293                if (unlikely(p == NULL)) {
 294                        status = htonl(NFS4ERR_BADXDR);
 295                        goto err;
 296                }
 297
 298                tmp = ntohl(*p++);      /* bitmap size */
 299                if (tmp != 1) {
 300                        status = htonl(NFS4ERR_INVAL);
 301                        goto err;
 302                }
 303                dev->cbd_notify_type = ntohl(*p++);
 304                if (dev->cbd_notify_type != NOTIFY_DEVICEID4_CHANGE &&
 305                    dev->cbd_notify_type != NOTIFY_DEVICEID4_DELETE) {
 306                        status = htonl(NFS4ERR_INVAL);
 307                        goto err;
 308                }
 309
 310                tmp = ntohl(*p++);      /* opaque size */
 311                if (((dev->cbd_notify_type == NOTIFY_DEVICEID4_CHANGE) &&
 312                     (tmp != NFS4_DEVICEID4_SIZE + 8)) ||
 313                    ((dev->cbd_notify_type == NOTIFY_DEVICEID4_DELETE) &&
 314                     (tmp != NFS4_DEVICEID4_SIZE + 4))) {
 315                        status = htonl(NFS4ERR_INVAL);
 316                        goto err;
 317                }
 318                dev->cbd_layout_type = ntohl(*p++);
 319                memcpy(dev->cbd_dev_id.data, p, NFS4_DEVICEID4_SIZE);
 320                p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
 321
 322                if (dev->cbd_layout_type == NOTIFY_DEVICEID4_CHANGE) {
 323                        p = xdr_inline_decode(xdr, sizeof(uint32_t));
 324                        if (unlikely(p == NULL)) {
 325                                status = htonl(NFS4ERR_BADXDR);
 326                                goto err;
 327                        }
 328                        dev->cbd_immediate = ntohl(*p++);
 329                } else {
 330                        dev->cbd_immediate = 0;
 331                }
 332
 333                args->ndevs++;
 334
 335                dprintk("%s: type %d layout 0x%x immediate %d\n",
 336                        __func__, dev->cbd_notify_type, dev->cbd_layout_type,
 337                        dev->cbd_immediate);
 338        }
 339out:
 340        dprintk("%s: status %d ndevs %d\n",
 341                __func__, ntohl(status), args->ndevs);
 342        return status;
 343err:
 344        kfree(args->devs);
 345        goto out;
 346}
 347
 348static __be32 decode_sessionid(struct xdr_stream *xdr,
 349                                 struct nfs4_sessionid *sid)
 350{
 351        __be32 *p;
 352
 353        p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN);
 354        if (unlikely(p == NULL))
 355                return htonl(NFS4ERR_RESOURCE);
 356
 357        memcpy(sid->data, p, NFS4_MAX_SESSIONID_LEN);
 358        return 0;
 359}
 360
 361static __be32 decode_rc_list(struct xdr_stream *xdr,
 362                               struct referring_call_list *rc_list)
 363{
 364        __be32 *p;
 365        int i;
 366        __be32 status;
 367
 368        status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
 369        if (status)
 370                goto out;
 371
 372        status = htonl(NFS4ERR_RESOURCE);
 373        p = xdr_inline_decode(xdr, sizeof(uint32_t));
 374        if (unlikely(p == NULL))
 375                goto out;
 376
 377        rc_list->rcl_nrefcalls = ntohl(*p++);
 378        if (rc_list->rcl_nrefcalls) {
 379                p = xdr_inline_decode(xdr,
 380                             rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
 381                if (unlikely(p == NULL))
 382                        goto out;
 383                rc_list->rcl_refcalls = kmalloc_array(rc_list->rcl_nrefcalls,
 384                                                sizeof(*rc_list->rcl_refcalls),
 385                                                GFP_KERNEL);
 386                if (unlikely(rc_list->rcl_refcalls == NULL))
 387                        goto out;
 388                for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
 389                        rc_list->rcl_refcalls[i].rc_sequenceid = ntohl(*p++);
 390                        rc_list->rcl_refcalls[i].rc_slotid = ntohl(*p++);
 391                }
 392        }
 393        status = 0;
 394
 395out:
 396        return status;
 397}
 398
 399static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
 400                                        struct xdr_stream *xdr,
 401                                        void *argp)
 402{
 403        struct cb_sequenceargs *args = argp;
 404        __be32 *p;
 405        int i;
 406        __be32 status;
 407
 408        status = decode_sessionid(xdr, &args->csa_sessionid);
 409        if (status)
 410                return status;
 411
 412        p = xdr_inline_decode(xdr, 5 * sizeof(uint32_t));
 413        if (unlikely(p == NULL))
 414                return htonl(NFS4ERR_RESOURCE);
 415
 416        args->csa_addr = svc_addr(rqstp);
 417        args->csa_sequenceid = ntohl(*p++);
 418        args->csa_slotid = ntohl(*p++);
 419        args->csa_highestslotid = ntohl(*p++);
 420        args->csa_cachethis = ntohl(*p++);
 421        args->csa_nrclists = ntohl(*p++);
 422        args->csa_rclists = NULL;
 423        if (args->csa_nrclists) {
 424                args->csa_rclists = kmalloc_array(args->csa_nrclists,
 425                                                  sizeof(*args->csa_rclists),
 426                                                  GFP_KERNEL);
 427                if (unlikely(args->csa_rclists == NULL))
 428                        return htonl(NFS4ERR_RESOURCE);
 429
 430                for (i = 0; i < args->csa_nrclists; i++) {
 431                        status = decode_rc_list(xdr, &args->csa_rclists[i]);
 432                        if (status) {
 433                                args->csa_nrclists = i;
 434                                goto out_free;
 435                        }
 436                }
 437        }
 438        return 0;
 439
 440out_free:
 441        for (i = 0; i < args->csa_nrclists; i++)
 442                kfree(args->csa_rclists[i].rcl_refcalls);
 443        kfree(args->csa_rclists);
 444        return status;
 445}
 446
 447static __be32 decode_recallany_args(struct svc_rqst *rqstp,
 448                                      struct xdr_stream *xdr,
 449                                      void *argp)
 450{
 451        struct cb_recallanyargs *args = argp;
 452        uint32_t bitmap[2];
 453        __be32 *p, status;
 454
 455        p = xdr_inline_decode(xdr, 4);
 456        if (unlikely(p == NULL))
 457                return htonl(NFS4ERR_BADXDR);
 458        args->craa_objs_to_keep = ntohl(*p++);
 459        status = decode_bitmap(xdr, bitmap);
 460        if (unlikely(status))
 461                return status;
 462        args->craa_type_mask = bitmap[0];
 463
 464        return 0;
 465}
 466
 467static __be32 decode_recallslot_args(struct svc_rqst *rqstp,
 468                                        struct xdr_stream *xdr,
 469                                        void *argp)
 470{
 471        struct cb_recallslotargs *args = argp;
 472        __be32 *p;
 473
 474        p = xdr_inline_decode(xdr, 4);
 475        if (unlikely(p == NULL))
 476                return htonl(NFS4ERR_BADXDR);
 477        args->crsa_target_highest_slotid = ntohl(*p++);
 478        return 0;
 479}
 480
 481static __be32 decode_lockowner(struct xdr_stream *xdr, struct cb_notify_lock_args *args)
 482{
 483        __be32          *p;
 484        unsigned int    len;
 485
 486        p = xdr_inline_decode(xdr, 12);
 487        if (unlikely(p == NULL))
 488                return htonl(NFS4ERR_BADXDR);
 489
 490        p = xdr_decode_hyper(p, &args->cbnl_owner.clientid);
 491        len = be32_to_cpu(*p);
 492
 493        p = xdr_inline_decode(xdr, len);
 494        if (unlikely(p == NULL))
 495                return htonl(NFS4ERR_BADXDR);
 496
 497        /* Only try to decode if the length is right */
 498        if (len == 20) {
 499                p += 2; /* skip "lock id:" */
 500                args->cbnl_owner.s_dev = be32_to_cpu(*p++);
 501                xdr_decode_hyper(p, &args->cbnl_owner.id);
 502                args->cbnl_valid = true;
 503        } else {
 504                args->cbnl_owner.s_dev = 0;
 505                args->cbnl_owner.id = 0;
 506                args->cbnl_valid = false;
 507        }
 508        return 0;
 509}
 510
 511static __be32 decode_notify_lock_args(struct svc_rqst *rqstp,
 512                struct xdr_stream *xdr, void *argp)
 513{
 514        struct cb_notify_lock_args *args = argp;
 515        __be32 status;
 516
 517        status = decode_fh(xdr, &args->cbnl_fh);
 518        if (unlikely(status != 0))
 519                return status;
 520        return decode_lockowner(xdr, args);
 521}
 522
 523#endif /* CONFIG_NFS_V4_1 */
 524#ifdef CONFIG_NFS_V4_2
 525static __be32 decode_write_response(struct xdr_stream *xdr,
 526                                        struct cb_offloadargs *args)
 527{
 528        __be32 *p;
 529
 530        /* skip the always zero field */
 531        p = xdr_inline_decode(xdr, 4);
 532        if (unlikely(!p))
 533                goto out;
 534        p++;
 535
 536        /* decode count, stable_how, verifier */
 537        p = xdr_inline_decode(xdr, 8 + 4);
 538        if (unlikely(!p))
 539                goto out;
 540        p = xdr_decode_hyper(p, &args->wr_count);
 541        args->wr_writeverf.committed = be32_to_cpup(p);
 542        p = xdr_inline_decode(xdr, NFS4_VERIFIER_SIZE);
 543        if (likely(p)) {
 544                memcpy(&args->wr_writeverf.verifier.data[0], p,
 545                        NFS4_VERIFIER_SIZE);
 546                return 0;
 547        }
 548out:
 549        return htonl(NFS4ERR_RESOURCE);
 550}
 551
 552static __be32 decode_offload_args(struct svc_rqst *rqstp,
 553                                        struct xdr_stream *xdr,
 554                                        void *data)
 555{
 556        struct cb_offloadargs *args = data;
 557        __be32 *p;
 558        __be32 status;
 559
 560        /* decode fh */
 561        status = decode_fh(xdr, &args->coa_fh);
 562        if (unlikely(status != 0))
 563                return status;
 564
 565        /* decode stateid */
 566        status = decode_stateid(xdr, &args->coa_stateid);
 567        if (unlikely(status != 0))
 568                return status;
 569
 570        /* decode status */
 571        p = xdr_inline_decode(xdr, 4);
 572        if (unlikely(!p))
 573                goto out;
 574        args->error = ntohl(*p++);
 575        if (!args->error) {
 576                status = decode_write_response(xdr, args);
 577                if (unlikely(status != 0))
 578                        return status;
 579        } else {
 580                p = xdr_inline_decode(xdr, 8);
 581                if (unlikely(!p))
 582                        goto out;
 583                p = xdr_decode_hyper(p, &args->wr_count);
 584        }
 585        return 0;
 586out:
 587        return htonl(NFS4ERR_RESOURCE);
 588}
 589#endif /* CONFIG_NFS_V4_2 */
 590static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
 591{
 592        if (unlikely(xdr_stream_encode_opaque(xdr, str, len) < 0))
 593                return cpu_to_be32(NFS4ERR_RESOURCE);
 594        return 0;
 595}
 596
 597static __be32 encode_attr_bitmap(struct xdr_stream *xdr, const uint32_t *bitmap, size_t sz)
 598{
 599        if (xdr_stream_encode_uint32_array(xdr, bitmap, sz) < 0)
 600                return cpu_to_be32(NFS4ERR_RESOURCE);
 601        return 0;
 602}
 603
 604static __be32 encode_attr_change(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t change)
 605{
 606        __be32 *p;
 607
 608        if (!(bitmap[0] & FATTR4_WORD0_CHANGE))
 609                return 0;
 610        p = xdr_reserve_space(xdr, 8);
 611        if (unlikely(!p))
 612                return htonl(NFS4ERR_RESOURCE);
 613        p = xdr_encode_hyper(p, change);
 614        return 0;
 615}
 616
 617static __be32 encode_attr_size(struct xdr_stream *xdr, const uint32_t *bitmap, uint64_t size)
 618{
 619        __be32 *p;
 620
 621        if (!(bitmap[0] & FATTR4_WORD0_SIZE))
 622                return 0;
 623        p = xdr_reserve_space(xdr, 8);
 624        if (unlikely(!p))
 625                return htonl(NFS4ERR_RESOURCE);
 626        p = xdr_encode_hyper(p, size);
 627        return 0;
 628}
 629
 630static __be32 encode_attr_time(struct xdr_stream *xdr, const struct timespec64 *time)
 631{
 632        __be32 *p;
 633
 634        p = xdr_reserve_space(xdr, 12);
 635        if (unlikely(!p))
 636                return htonl(NFS4ERR_RESOURCE);
 637        p = xdr_encode_hyper(p, time->tv_sec);
 638        *p = htonl(time->tv_nsec);
 639        return 0;
 640}
 641
 642static __be32 encode_attr_ctime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time)
 643{
 644        if (!(bitmap[1] & FATTR4_WORD1_TIME_METADATA))
 645                return 0;
 646        return encode_attr_time(xdr,time);
 647}
 648
 649static __be32 encode_attr_mtime(struct xdr_stream *xdr, const uint32_t *bitmap, const struct timespec64 *time)
 650{
 651        if (!(bitmap[1] & FATTR4_WORD1_TIME_MODIFY))
 652                return 0;
 653        return encode_attr_time(xdr,time);
 654}
 655
 656static __be32 encode_compound_hdr_res(struct xdr_stream *xdr, struct cb_compound_hdr_res *hdr)
 657{
 658        __be32 status;
 659
 660        hdr->status = xdr_reserve_space(xdr, 4);
 661        if (unlikely(hdr->status == NULL))
 662                return htonl(NFS4ERR_RESOURCE);
 663        status = encode_string(xdr, hdr->taglen, hdr->tag);
 664        if (unlikely(status != 0))
 665                return status;
 666        hdr->nops = xdr_reserve_space(xdr, 4);
 667        if (unlikely(hdr->nops == NULL))
 668                return htonl(NFS4ERR_RESOURCE);
 669        return 0;
 670}
 671
 672static __be32 encode_op_hdr(struct xdr_stream *xdr, uint32_t op, __be32 res)
 673{
 674        __be32 *p;
 675        
 676        p = xdr_reserve_space(xdr, 8);
 677        if (unlikely(p == NULL))
 678                return htonl(NFS4ERR_RESOURCE_HDR);
 679        *p++ = htonl(op);
 680        *p = res;
 681        return 0;
 682}
 683
 684static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 685                const void *resp)
 686{
 687        const struct cb_getattrres *res = resp;
 688        __be32 *savep = NULL;
 689        __be32 status = res->status;
 690        
 691        if (unlikely(status != 0))
 692                goto out;
 693        status = encode_attr_bitmap(xdr, res->bitmap, ARRAY_SIZE(res->bitmap));
 694        if (unlikely(status != 0))
 695                goto out;
 696        status = cpu_to_be32(NFS4ERR_RESOURCE);
 697        savep = xdr_reserve_space(xdr, sizeof(*savep));
 698        if (unlikely(!savep))
 699                goto out;
 700        status = encode_attr_change(xdr, res->bitmap, res->change_attr);
 701        if (unlikely(status != 0))
 702                goto out;
 703        status = encode_attr_size(xdr, res->bitmap, res->size);
 704        if (unlikely(status != 0))
 705                goto out;
 706        status = encode_attr_ctime(xdr, res->bitmap, &res->ctime);
 707        if (unlikely(status != 0))
 708                goto out;
 709        status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
 710        *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
 711out:
 712        return status;
 713}
 714
 715#if defined(CONFIG_NFS_V4_1)
 716
 717static __be32 encode_sessionid(struct xdr_stream *xdr,
 718                                 const struct nfs4_sessionid *sid)
 719{
 720        __be32 *p;
 721
 722        p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN);
 723        if (unlikely(p == NULL))
 724                return htonl(NFS4ERR_RESOURCE);
 725
 726        memcpy(p, sid, NFS4_MAX_SESSIONID_LEN);
 727        return 0;
 728}
 729
 730static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
 731                                       struct xdr_stream *xdr,
 732                                       const void *resp)
 733{
 734        const struct cb_sequenceres *res = resp;
 735        __be32 *p;
 736        __be32 status = res->csr_status;
 737
 738        if (unlikely(status != 0))
 739                return status;
 740
 741        status = encode_sessionid(xdr, &res->csr_sessionid);
 742        if (status)
 743                return status;
 744
 745        p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
 746        if (unlikely(p == NULL))
 747                return htonl(NFS4ERR_RESOURCE);
 748
 749        *p++ = htonl(res->csr_sequenceid);
 750        *p++ = htonl(res->csr_slotid);
 751        *p++ = htonl(res->csr_highestslotid);
 752        *p++ = htonl(res->csr_target_highestslotid);
 753        return 0;
 754}
 755
 756static __be32
 757preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
 758{
 759        if (op_nr == OP_CB_SEQUENCE) {
 760                if (nop != 0)
 761                        return htonl(NFS4ERR_SEQUENCE_POS);
 762        } else {
 763                if (nop == 0)
 764                        return htonl(NFS4ERR_OP_NOT_IN_SESSION);
 765        }
 766
 767        switch (op_nr) {
 768        case OP_CB_GETATTR:
 769        case OP_CB_RECALL:
 770        case OP_CB_SEQUENCE:
 771        case OP_CB_RECALL_ANY:
 772        case OP_CB_RECALL_SLOT:
 773        case OP_CB_LAYOUTRECALL:
 774        case OP_CB_NOTIFY_DEVICEID:
 775        case OP_CB_NOTIFY_LOCK:
 776                *op = &callback_ops[op_nr];
 777                break;
 778
 779        case OP_CB_NOTIFY:
 780        case OP_CB_PUSH_DELEG:
 781        case OP_CB_RECALLABLE_OBJ_AVAIL:
 782        case OP_CB_WANTS_CANCELLED:
 783                return htonl(NFS4ERR_NOTSUPP);
 784
 785        default:
 786                return htonl(NFS4ERR_OP_ILLEGAL);
 787        }
 788
 789        return htonl(NFS_OK);
 790}
 791
 792static void nfs4_callback_free_slot(struct nfs4_session *session,
 793                struct nfs4_slot *slot)
 794{
 795        struct nfs4_slot_table *tbl = &session->bc_slot_table;
 796
 797        spin_lock(&tbl->slot_tbl_lock);
 798        /*
 799         * Let the state manager know callback processing done.
 800         * A single slot, so highest used slotid is either 0 or -1
 801         */
 802        nfs4_free_slot(tbl, slot);
 803        spin_unlock(&tbl->slot_tbl_lock);
 804}
 805
 806static void nfs4_cb_free_slot(struct cb_process_state *cps)
 807{
 808        if (cps->slot) {
 809                nfs4_callback_free_slot(cps->clp->cl_session, cps->slot);
 810                cps->slot = NULL;
 811        }
 812}
 813
 814#else /* CONFIG_NFS_V4_1 */
 815
 816static __be32
 817preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
 818{
 819        return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 820}
 821
 822static void nfs4_cb_free_slot(struct cb_process_state *cps)
 823{
 824}
 825#endif /* CONFIG_NFS_V4_1 */
 826
 827#ifdef CONFIG_NFS_V4_2
 828static __be32
 829preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op)
 830{
 831        __be32 status = preprocess_nfs41_op(nop, op_nr, op);
 832        if (status != htonl(NFS4ERR_OP_ILLEGAL))
 833                return status;
 834
 835        if (op_nr == OP_CB_OFFLOAD) {
 836                *op = &callback_ops[op_nr];
 837                return htonl(NFS_OK);
 838        } else
 839                return htonl(NFS4ERR_NOTSUPP);
 840        return htonl(NFS4ERR_OP_ILLEGAL);
 841}
 842#else /* CONFIG_NFS_V4_2 */
 843static __be32
 844preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op)
 845{
 846        return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 847}
 848#endif /* CONFIG_NFS_V4_2 */
 849
 850static __be32
 851preprocess_nfs4_op(unsigned int op_nr, struct callback_op **op)
 852{
 853        switch (op_nr) {
 854        case OP_CB_GETATTR:
 855        case OP_CB_RECALL:
 856                *op = &callback_ops[op_nr];
 857                break;
 858        default:
 859                return htonl(NFS4ERR_OP_ILLEGAL);
 860        }
 861
 862        return htonl(NFS_OK);
 863}
 864
 865static __be32 process_op(int nop, struct svc_rqst *rqstp,
 866                         struct cb_process_state *cps)
 867{
 868        struct xdr_stream *xdr_out = &rqstp->rq_res_stream;
 869        struct callback_op *op = &callback_ops[0];
 870        unsigned int op_nr;
 871        __be32 status;
 872        long maxlen;
 873        __be32 res;
 874
 875        status = decode_op_hdr(&rqstp->rq_arg_stream, &op_nr);
 876        if (unlikely(status))
 877                return status;
 878
 879        switch (cps->minorversion) {
 880        case 0:
 881                status = preprocess_nfs4_op(op_nr, &op);
 882                break;
 883        case 1:
 884                status = preprocess_nfs41_op(nop, op_nr, &op);
 885                break;
 886        case 2:
 887                status = preprocess_nfs42_op(nop, op_nr, &op);
 888                break;
 889        default:
 890                status = htonl(NFS4ERR_MINOR_VERS_MISMATCH);
 891        }
 892
 893        if (status == htonl(NFS4ERR_OP_ILLEGAL))
 894                op_nr = OP_CB_ILLEGAL;
 895        if (status)
 896                goto encode_hdr;
 897
 898        if (cps->drc_status) {
 899                status = cps->drc_status;
 900                goto encode_hdr;
 901        }
 902
 903        maxlen = xdr_out->end - xdr_out->p;
 904        if (maxlen > 0 && maxlen < PAGE_SIZE) {
 905                status = op->decode_args(rqstp, &rqstp->rq_arg_stream,
 906                                         rqstp->rq_argp);
 907                if (likely(status == 0))
 908                        status = op->process_op(rqstp->rq_argp, rqstp->rq_resp,
 909                                                cps);
 910        } else
 911                status = htonl(NFS4ERR_RESOURCE);
 912
 913encode_hdr:
 914        res = encode_op_hdr(xdr_out, op_nr, status);
 915        if (unlikely(res))
 916                return res;
 917        if (op->encode_res != NULL && status == 0)
 918                status = op->encode_res(rqstp, xdr_out, rqstp->rq_resp);
 919        return status;
 920}
 921
 922/*
 923 * Decode, process and encode a COMPOUND
 924 */
 925static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
 926{
 927        struct cb_compound_hdr_arg hdr_arg = { 0 };
 928        struct cb_compound_hdr_res hdr_res = { NULL };
 929        struct cb_process_state cps = {
 930                .drc_status = 0,
 931                .clp = NULL,
 932                .net = SVC_NET(rqstp),
 933        };
 934        unsigned int nops = 0;
 935        __be32 status;
 936
 937        status = decode_compound_hdr_arg(&rqstp->rq_arg_stream, &hdr_arg);
 938        if (status == htonl(NFS4ERR_RESOURCE))
 939                return rpc_garbage_args;
 940
 941        if (hdr_arg.minorversion == 0) {
 942                cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
 943                if (!cps.clp) {
 944                        trace_nfs_cb_no_clp(rqstp->rq_xid, hdr_arg.cb_ident);
 945                        goto out_invalidcred;
 946                }
 947                if (!check_gss_callback_principal(cps.clp, rqstp)) {
 948                        trace_nfs_cb_badprinc(rqstp->rq_xid, hdr_arg.cb_ident);
 949                        nfs_put_client(cps.clp);
 950                        goto out_invalidcred;
 951                }
 952        }
 953
 954        cps.minorversion = hdr_arg.minorversion;
 955        hdr_res.taglen = hdr_arg.taglen;
 956        hdr_res.tag = hdr_arg.tag;
 957        if (encode_compound_hdr_res(&rqstp->rq_res_stream, &hdr_res) != 0) {
 958                if (cps.clp)
 959                        nfs_put_client(cps.clp);
 960                return rpc_system_err;
 961        }
 962        while (status == 0 && nops != hdr_arg.nops) {
 963                status = process_op(nops, rqstp, &cps);
 964                nops++;
 965        }
 966
 967        /* Buffer overflow in decode_ops_hdr or encode_ops_hdr. Return
 968        * resource error in cb_compound status without returning op */
 969        if (unlikely(status == htonl(NFS4ERR_RESOURCE_HDR))) {
 970                status = htonl(NFS4ERR_RESOURCE);
 971                nops--;
 972        }
 973
 974        *hdr_res.status = status;
 975        *hdr_res.nops = htonl(nops);
 976        nfs4_cb_free_slot(&cps);
 977        nfs_put_client(cps.clp);
 978        return rpc_success;
 979
 980out_invalidcred:
 981        pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
 982        rqstp->rq_auth_stat = rpc_autherr_badcred;
 983        return rpc_success;
 984}
 985
 986static int
 987nfs_callback_dispatch(struct svc_rqst *rqstp, __be32 *statp)
 988{
 989        const struct svc_procedure *procp = rqstp->rq_procinfo;
 990
 991        svcxdr_init_decode(rqstp);
 992        svcxdr_init_encode(rqstp);
 993
 994        *statp = procp->pc_func(rqstp);
 995        return 1;
 996}
 997
 998/*
 999 * Define NFS4 callback COMPOUND ops.
1000 */
1001static struct callback_op callback_ops[] = {
1002        [0] = {
1003                .res_maxsize = CB_OP_HDR_RES_MAXSZ,
1004        },
1005        [OP_CB_GETATTR] = {
1006                .process_op = nfs4_callback_getattr,
1007                .decode_args = decode_getattr_args,
1008                .encode_res = encode_getattr_res,
1009                .res_maxsize = CB_OP_GETATTR_RES_MAXSZ,
1010        },
1011        [OP_CB_RECALL] = {
1012                .process_op = nfs4_callback_recall,
1013                .decode_args = decode_recall_args,
1014                .res_maxsize = CB_OP_RECALL_RES_MAXSZ,
1015        },
1016#if defined(CONFIG_NFS_V4_1)
1017        [OP_CB_LAYOUTRECALL] = {
1018                .process_op = nfs4_callback_layoutrecall,
1019                .decode_args = decode_layoutrecall_args,
1020                .res_maxsize = CB_OP_LAYOUTRECALL_RES_MAXSZ,
1021        },
1022        [OP_CB_NOTIFY_DEVICEID] = {
1023                .process_op = nfs4_callback_devicenotify,
1024                .decode_args = decode_devicenotify_args,
1025                .res_maxsize = CB_OP_DEVICENOTIFY_RES_MAXSZ,
1026        },
1027        [OP_CB_SEQUENCE] = {
1028                .process_op = nfs4_callback_sequence,
1029                .decode_args = decode_cb_sequence_args,
1030                .encode_res = encode_cb_sequence_res,
1031                .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
1032        },
1033        [OP_CB_RECALL_ANY] = {
1034                .process_op = nfs4_callback_recallany,
1035                .decode_args = decode_recallany_args,
1036                .res_maxsize = CB_OP_RECALLANY_RES_MAXSZ,
1037        },
1038        [OP_CB_RECALL_SLOT] = {
1039                .process_op = nfs4_callback_recallslot,
1040                .decode_args = decode_recallslot_args,
1041                .res_maxsize = CB_OP_RECALLSLOT_RES_MAXSZ,
1042        },
1043        [OP_CB_NOTIFY_LOCK] = {
1044                .process_op = nfs4_callback_notify_lock,
1045                .decode_args = decode_notify_lock_args,
1046                .res_maxsize = CB_OP_NOTIFY_LOCK_RES_MAXSZ,
1047        },
1048#endif /* CONFIG_NFS_V4_1 */
1049#ifdef CONFIG_NFS_V4_2
1050        [OP_CB_OFFLOAD] = {
1051                .process_op = nfs4_callback_offload,
1052                .decode_args = decode_offload_args,
1053                .res_maxsize = CB_OP_OFFLOAD_RES_MAXSZ,
1054        },
1055#endif /* CONFIG_NFS_V4_2 */
1056};
1057
1058/*
1059 * Define NFS4 callback procedures
1060 */
1061static const struct svc_procedure nfs4_callback_procedures1[] = {
1062        [CB_NULL] = {
1063                .pc_func = nfs4_callback_null,
1064                .pc_encode = nfs4_encode_void,
1065                .pc_xdrressize = 1,
1066                .pc_name = "NULL",
1067        },
1068        [CB_COMPOUND] = {
1069                .pc_func = nfs4_callback_compound,
1070                .pc_encode = nfs4_encode_void,
1071                .pc_argsize = 256,
1072                .pc_ressize = 256,
1073                .pc_xdrressize = NFS4_CALLBACK_BUFSIZE,
1074                .pc_name = "COMPOUND",
1075        }
1076};
1077
1078static unsigned int nfs4_callback_count1[ARRAY_SIZE(nfs4_callback_procedures1)];
1079const struct svc_version nfs4_callback_version1 = {
1080        .vs_vers = 1,
1081        .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1),
1082        .vs_proc = nfs4_callback_procedures1,
1083        .vs_count = nfs4_callback_count1,
1084        .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
1085        .vs_dispatch = nfs_callback_dispatch,
1086        .vs_hidden = true,
1087        .vs_need_cong_ctrl = true,
1088};
1089
1090static unsigned int nfs4_callback_count4[ARRAY_SIZE(nfs4_callback_procedures1)];
1091const struct svc_version nfs4_callback_version4 = {
1092        .vs_vers = 4,
1093        .vs_nproc = ARRAY_SIZE(nfs4_callback_procedures1),
1094        .vs_proc = nfs4_callback_procedures1,
1095        .vs_count = nfs4_callback_count4,
1096        .vs_xdrsize = NFS4_CALLBACK_XDRSIZE,
1097        .vs_dispatch = nfs_callback_dispatch,
1098        .vs_hidden = true,
1099        .vs_need_cong_ctrl = true,
1100};
1101