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