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