nfs3xdr.c (32068B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * XDR support for nfsd/protocol version 3. 4 * 5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 6 * 7 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()! 8 */ 9 10#include <linux/namei.h> 11#include <linux/sunrpc/svc_xprt.h> 12#include "xdr3.h" 13#include "auth.h" 14#include "netns.h" 15#include "vfs.h" 16 17/* 18 * Force construction of an empty post-op attr 19 */ 20static const struct svc_fh nfs3svc_null_fh = { 21 .fh_no_wcc = true, 22}; 23 24/* 25 * time_delta. {1, 0} means the server is accurate only 26 * to the nearest second. 27 */ 28static const struct timespec64 nfs3svc_time_delta = { 29 .tv_sec = 1, 30 .tv_nsec = 0, 31}; 32 33/* 34 * Mapping of S_IF* types to NFS file types 35 */ 36static const u32 nfs3_ftypes[] = { 37 NF3NON, NF3FIFO, NF3CHR, NF3BAD, 38 NF3DIR, NF3BAD, NF3BLK, NF3BAD, 39 NF3REG, NF3BAD, NF3LNK, NF3BAD, 40 NF3SOCK, NF3BAD, NF3LNK, NF3BAD, 41}; 42 43 44/* 45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6) 46 */ 47 48static __be32 * 49encode_nfstime3(__be32 *p, const struct timespec64 *time) 50{ 51 *p++ = cpu_to_be32((u32)time->tv_sec); 52 *p++ = cpu_to_be32(time->tv_nsec); 53 54 return p; 55} 56 57static bool 58svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep) 59{ 60 __be32 *p; 61 62 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 63 if (!p) 64 return false; 65 timep->tv_sec = be32_to_cpup(p++); 66 timep->tv_nsec = be32_to_cpup(p); 67 68 return true; 69} 70 71/** 72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle 73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH 74 * @fhp: OUT: filled-in server file handle 75 * 76 * Return values: 77 * %false: The encoded file handle was not valid 78 * %true: @fhp has been initialized 79 */ 80bool 81svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp) 82{ 83 __be32 *p; 84 u32 size; 85 86 if (xdr_stream_decode_u32(xdr, &size) < 0) 87 return false; 88 if (size == 0 || size > NFS3_FHSIZE) 89 return false; 90 p = xdr_inline_decode(xdr, size); 91 if (!p) 92 return false; 93 fh_init(fhp, NFS3_FHSIZE); 94 fhp->fh_handle.fh_size = size; 95 memcpy(&fhp->fh_handle.fh_raw, p, size); 96 97 return true; 98} 99 100/** 101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code 102 * @xdr: XDR stream 103 * @status: status value to encode 104 * 105 * Return values: 106 * %false: Send buffer space was exhausted 107 * %true: Success 108 */ 109bool 110svcxdr_encode_nfsstat3(struct xdr_stream *xdr, __be32 status) 111{ 112 __be32 *p; 113 114 p = xdr_reserve_space(xdr, sizeof(status)); 115 if (!p) 116 return false; 117 *p = status; 118 119 return true; 120} 121 122static bool 123svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp) 124{ 125 u32 size = fhp->fh_handle.fh_size; 126 __be32 *p; 127 128 p = xdr_reserve_space(xdr, XDR_UNIT + size); 129 if (!p) 130 return false; 131 *p++ = cpu_to_be32(size); 132 if (size) 133 p[XDR_QUADLEN(size) - 1] = 0; 134 memcpy(p, &fhp->fh_handle.fh_raw, size); 135 136 return true; 137} 138 139static bool 140svcxdr_encode_post_op_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp) 141{ 142 if (xdr_stream_encode_item_present(xdr) < 0) 143 return false; 144 if (!svcxdr_encode_nfs_fh3(xdr, fhp)) 145 return false; 146 147 return true; 148} 149 150static bool 151svcxdr_encode_cookieverf3(struct xdr_stream *xdr, const __be32 *verf) 152{ 153 __be32 *p; 154 155 p = xdr_reserve_space(xdr, NFS3_COOKIEVERFSIZE); 156 if (!p) 157 return false; 158 memcpy(p, verf, NFS3_COOKIEVERFSIZE); 159 160 return true; 161} 162 163static bool 164svcxdr_encode_writeverf3(struct xdr_stream *xdr, const __be32 *verf) 165{ 166 __be32 *p; 167 168 p = xdr_reserve_space(xdr, NFS3_WRITEVERFSIZE); 169 if (!p) 170 return false; 171 memcpy(p, verf, NFS3_WRITEVERFSIZE); 172 173 return true; 174} 175 176static bool 177svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len) 178{ 179 u32 size, i; 180 __be32 *p; 181 char *c; 182 183 if (xdr_stream_decode_u32(xdr, &size) < 0) 184 return false; 185 if (size == 0 || size > NFS3_MAXNAMLEN) 186 return false; 187 p = xdr_inline_decode(xdr, size); 188 if (!p) 189 return false; 190 191 *len = size; 192 *name = (char *)p; 193 for (i = 0, c = *name; i < size; i++, c++) { 194 if (*c == '\0' || *c == '/') 195 return false; 196 } 197 198 return true; 199} 200 201static bool 202svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp, 203 char **name, unsigned int *len) 204{ 205 return svcxdr_decode_nfs_fh3(xdr, fhp) && 206 svcxdr_decode_filename3(xdr, name, len); 207} 208 209static bool 210svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 211 struct iattr *iap) 212{ 213 u32 set_it; 214 215 iap->ia_valid = 0; 216 217 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 218 return false; 219 if (set_it) { 220 u32 mode; 221 222 if (xdr_stream_decode_u32(xdr, &mode) < 0) 223 return false; 224 iap->ia_valid |= ATTR_MODE; 225 iap->ia_mode = mode; 226 } 227 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 228 return false; 229 if (set_it) { 230 u32 uid; 231 232 if (xdr_stream_decode_u32(xdr, &uid) < 0) 233 return false; 234 iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid); 235 if (uid_valid(iap->ia_uid)) 236 iap->ia_valid |= ATTR_UID; 237 } 238 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 239 return false; 240 if (set_it) { 241 u32 gid; 242 243 if (xdr_stream_decode_u32(xdr, &gid) < 0) 244 return false; 245 iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid); 246 if (gid_valid(iap->ia_gid)) 247 iap->ia_valid |= ATTR_GID; 248 } 249 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 250 return false; 251 if (set_it) { 252 u64 newsize; 253 254 if (xdr_stream_decode_u64(xdr, &newsize) < 0) 255 return false; 256 iap->ia_valid |= ATTR_SIZE; 257 iap->ia_size = newsize; 258 } 259 if (xdr_stream_decode_u32(xdr, &set_it) < 0) 260 return false; 261 switch (set_it) { 262 case DONT_CHANGE: 263 break; 264 case SET_TO_SERVER_TIME: 265 iap->ia_valid |= ATTR_ATIME; 266 break; 267 case SET_TO_CLIENT_TIME: 268 if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime)) 269 return false; 270 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 271 break; 272 default: 273 return false; 274 } 275 if (xdr_stream_decode_u32(xdr, &set_it) < 0) 276 return false; 277 switch (set_it) { 278 case DONT_CHANGE: 279 break; 280 case SET_TO_SERVER_TIME: 281 iap->ia_valid |= ATTR_MTIME; 282 break; 283 case SET_TO_CLIENT_TIME: 284 if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime)) 285 return false; 286 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 287 break; 288 default: 289 return false; 290 } 291 292 return true; 293} 294 295static bool 296svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args) 297{ 298 __be32 *p; 299 u32 check; 300 301 if (xdr_stream_decode_bool(xdr, &check) < 0) 302 return false; 303 if (check) { 304 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 305 if (!p) 306 return false; 307 args->check_guard = 1; 308 args->guardtime = be32_to_cpup(p); 309 } else 310 args->check_guard = 0; 311 312 return true; 313} 314 315static bool 316svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args) 317{ 318 __be32 *p; 319 320 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 321 if (!p) 322 return false; 323 args->major = be32_to_cpup(p++); 324 args->minor = be32_to_cpup(p); 325 326 return true; 327} 328 329static bool 330svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 331 struct nfsd3_mknodargs *args) 332{ 333 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 334 svcxdr_decode_specdata3(xdr, args); 335} 336 337static bool 338svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 339 const struct svc_fh *fhp, const struct kstat *stat) 340{ 341 struct user_namespace *userns = nfsd_user_namespace(rqstp); 342 __be32 *p; 343 u64 fsid; 344 345 p = xdr_reserve_space(xdr, XDR_UNIT * 21); 346 if (!p) 347 return false; 348 349 *p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 350 *p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO)); 351 *p++ = cpu_to_be32((u32)stat->nlink); 352 *p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid)); 353 *p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid)); 354 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) 355 p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN); 356 else 357 p = xdr_encode_hyper(p, (u64)stat->size); 358 359 /* used */ 360 p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); 361 362 /* rdev */ 363 *p++ = cpu_to_be32((u32)MAJOR(stat->rdev)); 364 *p++ = cpu_to_be32((u32)MINOR(stat->rdev)); 365 366 switch(fsid_source(fhp)) { 367 case FSIDSOURCE_FSID: 368 fsid = (u64)fhp->fh_export->ex_fsid; 369 break; 370 case FSIDSOURCE_UUID: 371 fsid = ((u64 *)fhp->fh_export->ex_uuid)[0]; 372 fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1]; 373 break; 374 default: 375 fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev); 376 } 377 p = xdr_encode_hyper(p, fsid); 378 379 /* fileid */ 380 p = xdr_encode_hyper(p, stat->ino); 381 382 p = encode_nfstime3(p, &stat->atime); 383 p = encode_nfstime3(p, &stat->mtime); 384 encode_nfstime3(p, &stat->ctime); 385 386 return true; 387} 388 389static bool 390svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp) 391{ 392 __be32 *p; 393 394 p = xdr_reserve_space(xdr, XDR_UNIT * 6); 395 if (!p) 396 return false; 397 p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size); 398 p = encode_nfstime3(p, &fhp->fh_pre_mtime); 399 encode_nfstime3(p, &fhp->fh_pre_ctime); 400 401 return true; 402} 403 404static bool 405svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp) 406{ 407 if (!fhp->fh_pre_saved) { 408 if (xdr_stream_encode_item_absent(xdr) < 0) 409 return false; 410 return true; 411 } 412 413 if (xdr_stream_encode_item_present(xdr) < 0) 414 return false; 415 return svcxdr_encode_wcc_attr(xdr, fhp); 416} 417 418/** 419 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes 420 * @rqstp: Context of a completed RPC transaction 421 * @xdr: XDR stream 422 * @fhp: File handle to encode 423 * 424 * Return values: 425 * %false: Send buffer space was exhausted 426 * %true: Success 427 */ 428bool 429svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr, 430 const struct svc_fh *fhp) 431{ 432 struct dentry *dentry = fhp->fh_dentry; 433 struct kstat stat; 434 435 /* 436 * The inode may be NULL if the call failed because of a 437 * stale file handle. In this case, no attributes are 438 * returned. 439 */ 440 if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry)) 441 goto no_post_op_attrs; 442 if (fh_getattr(fhp, &stat) != nfs_ok) 443 goto no_post_op_attrs; 444 445 if (xdr_stream_encode_item_present(xdr) < 0) 446 return false; 447 lease_get_mtime(d_inode(dentry), &stat.mtime); 448 if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat)) 449 return false; 450 451 return true; 452 453no_post_op_attrs: 454 return xdr_stream_encode_item_absent(xdr) > 0; 455} 456 457/* 458 * Encode weak cache consistency data 459 */ 460static bool 461svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr, 462 const struct svc_fh *fhp) 463{ 464 struct dentry *dentry = fhp->fh_dentry; 465 466 if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved) 467 goto neither; 468 469 /* before */ 470 if (!svcxdr_encode_pre_op_attr(xdr, fhp)) 471 return false; 472 473 /* after */ 474 if (xdr_stream_encode_item_present(xdr) < 0) 475 return false; 476 if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr)) 477 return false; 478 479 return true; 480 481neither: 482 if (xdr_stream_encode_item_absent(xdr) < 0) 483 return false; 484 if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp)) 485 return false; 486 487 return true; 488} 489 490/* 491 * XDR decode functions 492 */ 493 494bool 495nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 496{ 497 struct nfsd_fhandle *args = rqstp->rq_argp; 498 499 return svcxdr_decode_nfs_fh3(xdr, &args->fh); 500} 501 502bool 503nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 504{ 505 struct nfsd3_sattrargs *args = rqstp->rq_argp; 506 507 return svcxdr_decode_nfs_fh3(xdr, &args->fh) && 508 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 509 svcxdr_decode_sattrguard3(xdr, args); 510} 511 512bool 513nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 514{ 515 struct nfsd3_diropargs *args = rqstp->rq_argp; 516 517 return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len); 518} 519 520bool 521nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 522{ 523 struct nfsd3_accessargs *args = rqstp->rq_argp; 524 525 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 526 return false; 527 if (xdr_stream_decode_u32(xdr, &args->access) < 0) 528 return false; 529 530 return true; 531} 532 533bool 534nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 535{ 536 struct nfsd3_readargs *args = rqstp->rq_argp; 537 538 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 539 return false; 540 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 541 return false; 542 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 543 return false; 544 545 return true; 546} 547 548bool 549nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 550{ 551 struct nfsd3_writeargs *args = rqstp->rq_argp; 552 u32 max_blocksize = svc_max_payload(rqstp); 553 554 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 555 return false; 556 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 557 return false; 558 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 559 return false; 560 if (xdr_stream_decode_u32(xdr, &args->stable) < 0) 561 return false; 562 563 /* opaque data */ 564 if (xdr_stream_decode_u32(xdr, &args->len) < 0) 565 return false; 566 567 /* request sanity */ 568 if (args->count != args->len) 569 return false; 570 if (args->count > max_blocksize) { 571 args->count = max_blocksize; 572 args->len = max_blocksize; 573 } 574 if (!xdr_stream_subsegment(xdr, &args->payload, args->count)) 575 return false; 576 577 return true; 578} 579 580bool 581nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 582{ 583 struct nfsd3_createargs *args = rqstp->rq_argp; 584 585 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 586 return false; 587 if (xdr_stream_decode_u32(xdr, &args->createmode) < 0) 588 return false; 589 switch (args->createmode) { 590 case NFS3_CREATE_UNCHECKED: 591 case NFS3_CREATE_GUARDED: 592 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 593 case NFS3_CREATE_EXCLUSIVE: 594 args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE); 595 if (!args->verf) 596 return false; 597 break; 598 default: 599 return false; 600 } 601 return true; 602} 603 604bool 605nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 606{ 607 struct nfsd3_createargs *args = rqstp->rq_argp; 608 609 return svcxdr_decode_diropargs3(xdr, &args->fh, 610 &args->name, &args->len) && 611 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 612} 613 614bool 615nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 616{ 617 struct nfsd3_symlinkargs *args = rqstp->rq_argp; 618 struct kvec *head = rqstp->rq_arg.head; 619 struct kvec *tail = rqstp->rq_arg.tail; 620 size_t remaining; 621 622 if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen)) 623 return false; 624 if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs)) 625 return false; 626 if (xdr_stream_decode_u32(xdr, &args->tlen) < 0) 627 return false; 628 629 /* request sanity */ 630 remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; 631 remaining -= xdr_stream_pos(xdr); 632 if (remaining < xdr_align_size(args->tlen)) 633 return false; 634 635 args->first.iov_base = xdr->p; 636 args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); 637 638 return true; 639} 640 641bool 642nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 643{ 644 struct nfsd3_mknodargs *args = rqstp->rq_argp; 645 646 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 647 return false; 648 if (xdr_stream_decode_u32(xdr, &args->ftype) < 0) 649 return false; 650 switch (args->ftype) { 651 case NF3CHR: 652 case NF3BLK: 653 return svcxdr_decode_devicedata3(rqstp, xdr, args); 654 case NF3SOCK: 655 case NF3FIFO: 656 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 657 case NF3REG: 658 case NF3DIR: 659 case NF3LNK: 660 /* Valid XDR but illegal file types */ 661 break; 662 default: 663 return false; 664 } 665 666 return true; 667} 668 669bool 670nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 671{ 672 struct nfsd3_renameargs *args = rqstp->rq_argp; 673 674 return svcxdr_decode_diropargs3(xdr, &args->ffh, 675 &args->fname, &args->flen) && 676 svcxdr_decode_diropargs3(xdr, &args->tfh, 677 &args->tname, &args->tlen); 678} 679 680bool 681nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 682{ 683 struct nfsd3_linkargs *args = rqstp->rq_argp; 684 685 return svcxdr_decode_nfs_fh3(xdr, &args->ffh) && 686 svcxdr_decode_diropargs3(xdr, &args->tfh, 687 &args->tname, &args->tlen); 688} 689 690bool 691nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 692{ 693 struct nfsd3_readdirargs *args = rqstp->rq_argp; 694 695 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 696 return false; 697 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 698 return false; 699 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 700 if (!args->verf) 701 return false; 702 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 703 return false; 704 705 return true; 706} 707 708bool 709nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 710{ 711 struct nfsd3_readdirargs *args = rqstp->rq_argp; 712 u32 dircount; 713 714 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 715 return false; 716 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 717 return false; 718 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 719 if (!args->verf) 720 return false; 721 /* dircount is ignored */ 722 if (xdr_stream_decode_u32(xdr, &dircount) < 0) 723 return false; 724 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 725 return false; 726 727 return true; 728} 729 730bool 731nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 732{ 733 struct nfsd3_commitargs *args = rqstp->rq_argp; 734 735 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 736 return false; 737 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 738 return false; 739 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 740 return false; 741 742 return true; 743} 744 745/* 746 * XDR encode functions 747 */ 748 749/* GETATTR */ 750bool 751nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 752{ 753 struct nfsd3_attrstat *resp = rqstp->rq_resp; 754 755 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 756 return false; 757 switch (resp->status) { 758 case nfs_ok: 759 lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime); 760 if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat)) 761 return false; 762 break; 763 } 764 765 return true; 766} 767 768/* SETATTR, REMOVE, RMDIR */ 769bool 770nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr) 771{ 772 struct nfsd3_attrstat *resp = rqstp->rq_resp; 773 774 return svcxdr_encode_nfsstat3(xdr, resp->status) && 775 svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh); 776} 777 778/* LOOKUP */ 779bool 780nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 781{ 782 struct nfsd3_diropres *resp = rqstp->rq_resp; 783 784 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 785 return false; 786 switch (resp->status) { 787 case nfs_ok: 788 if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh)) 789 return false; 790 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 791 return false; 792 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 793 return false; 794 break; 795 default: 796 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 797 return false; 798 } 799 800 return true; 801} 802 803/* ACCESS */ 804bool 805nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 806{ 807 struct nfsd3_accessres *resp = rqstp->rq_resp; 808 809 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 810 return false; 811 switch (resp->status) { 812 case nfs_ok: 813 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 814 return false; 815 if (xdr_stream_encode_u32(xdr, resp->access) < 0) 816 return false; 817 break; 818 default: 819 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 820 return false; 821 } 822 823 return true; 824} 825 826/* READLINK */ 827bool 828nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 829{ 830 struct nfsd3_readlinkres *resp = rqstp->rq_resp; 831 struct kvec *head = rqstp->rq_res.head; 832 833 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 834 return false; 835 switch (resp->status) { 836 case nfs_ok: 837 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 838 return false; 839 if (xdr_stream_encode_u32(xdr, resp->len) < 0) 840 return false; 841 xdr_write_pages(xdr, resp->pages, 0, resp->len); 842 if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0) 843 return false; 844 break; 845 default: 846 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 847 return false; 848 } 849 850 return true; 851} 852 853/* READ */ 854bool 855nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 856{ 857 struct nfsd3_readres *resp = rqstp->rq_resp; 858 struct kvec *head = rqstp->rq_res.head; 859 860 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 861 return false; 862 switch (resp->status) { 863 case nfs_ok: 864 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 865 return false; 866 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 867 return false; 868 if (xdr_stream_encode_bool(xdr, resp->eof) < 0) 869 return false; 870 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 871 return false; 872 xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base, 873 resp->count); 874 if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0) 875 return false; 876 break; 877 default: 878 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 879 return false; 880 } 881 882 return true; 883} 884 885/* WRITE */ 886bool 887nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 888{ 889 struct nfsd3_writeres *resp = rqstp->rq_resp; 890 891 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 892 return false; 893 switch (resp->status) { 894 case nfs_ok: 895 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 896 return false; 897 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 898 return false; 899 if (xdr_stream_encode_u32(xdr, resp->committed) < 0) 900 return false; 901 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 902 return false; 903 break; 904 default: 905 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 906 return false; 907 } 908 909 return true; 910} 911 912/* CREATE, MKDIR, SYMLINK, MKNOD */ 913bool 914nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 915{ 916 struct nfsd3_diropres *resp = rqstp->rq_resp; 917 918 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 919 return false; 920 switch (resp->status) { 921 case nfs_ok: 922 if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh)) 923 return false; 924 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 925 return false; 926 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 927 return false; 928 break; 929 default: 930 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 931 return false; 932 } 933 934 return true; 935} 936 937/* RENAME */ 938bool 939nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 940{ 941 struct nfsd3_renameres *resp = rqstp->rq_resp; 942 943 return svcxdr_encode_nfsstat3(xdr, resp->status) && 944 svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) && 945 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 946} 947 948/* LINK */ 949bool 950nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 951{ 952 struct nfsd3_linkres *resp = rqstp->rq_resp; 953 954 return svcxdr_encode_nfsstat3(xdr, resp->status) && 955 svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) && 956 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 957} 958 959/* READDIR */ 960bool 961nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 962{ 963 struct nfsd3_readdirres *resp = rqstp->rq_resp; 964 struct xdr_buf *dirlist = &resp->dirlist; 965 966 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 967 return false; 968 switch (resp->status) { 969 case nfs_ok: 970 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 971 return false; 972 if (!svcxdr_encode_cookieverf3(xdr, resp->verf)) 973 return false; 974 xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len); 975 /* no more entries */ 976 if (xdr_stream_encode_item_absent(xdr) < 0) 977 return false; 978 if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0) 979 return false; 980 break; 981 default: 982 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 983 return false; 984 } 985 986 return true; 987} 988 989static __be32 990compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 991 const char *name, int namlen, u64 ino) 992{ 993 struct svc_export *exp; 994 struct dentry *dparent, *dchild; 995 __be32 rv = nfserr_noent; 996 997 dparent = cd->fh.fh_dentry; 998 exp = cd->fh.fh_export; 999 1000 if (isdotent(name, namlen)) { 1001 if (namlen == 2) { 1002 dchild = dget_parent(dparent); 1003 /* 1004 * Don't return filehandle for ".." if we're at 1005 * the filesystem or export root: 1006 */ 1007 if (dchild == dparent) 1008 goto out; 1009 if (dparent == exp->ex_path.dentry) 1010 goto out; 1011 } else 1012 dchild = dget(dparent); 1013 } else 1014 dchild = lookup_positive_unlocked(name, dparent, namlen); 1015 if (IS_ERR(dchild)) 1016 return rv; 1017 if (d_mountpoint(dchild)) 1018 goto out; 1019 if (dchild->d_inode->i_ino != ino) 1020 goto out; 1021 rv = fh_compose(fhp, exp, dchild, &cd->fh); 1022out: 1023 dput(dchild); 1024 return rv; 1025} 1026 1027/** 1028 * nfs3svc_encode_cookie3 - Encode a directory offset cookie 1029 * @resp: readdir result context 1030 * @offset: offset cookie to encode 1031 * 1032 * The buffer space for the offset cookie has already been reserved 1033 * by svcxdr_encode_entry3_common(). 1034 */ 1035void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset) 1036{ 1037 __be64 cookie = cpu_to_be64(offset); 1038 1039 if (!resp->cookie_offset) 1040 return; 1041 write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie, 1042 sizeof(cookie)); 1043 resp->cookie_offset = 0; 1044} 1045 1046static bool 1047svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name, 1048 int namlen, loff_t offset, u64 ino) 1049{ 1050 struct xdr_buf *dirlist = &resp->dirlist; 1051 struct xdr_stream *xdr = &resp->xdr; 1052 1053 if (xdr_stream_encode_item_present(xdr) < 0) 1054 return false; 1055 /* fileid */ 1056 if (xdr_stream_encode_u64(xdr, ino) < 0) 1057 return false; 1058 /* name */ 1059 if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0) 1060 return false; 1061 /* cookie */ 1062 resp->cookie_offset = dirlist->len; 1063 if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0) 1064 return false; 1065 1066 return true; 1067} 1068 1069/** 1070 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry 1071 * @data: directory context 1072 * @name: name of the object to be encoded 1073 * @namlen: length of that name, in bytes 1074 * @offset: the offset of the previous entry 1075 * @ino: the fileid of this entry 1076 * @d_type: unused 1077 * 1078 * Return values: 1079 * %0: Entry was successfully encoded. 1080 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1081 * 1082 * On exit, the following fields are updated: 1083 * - resp->xdr 1084 * - resp->common.err 1085 * - resp->cookie_offset 1086 */ 1087int nfs3svc_encode_entry3(void *data, const char *name, int namlen, 1088 loff_t offset, u64 ino, unsigned int d_type) 1089{ 1090 struct readdir_cd *ccd = data; 1091 struct nfsd3_readdirres *resp = container_of(ccd, 1092 struct nfsd3_readdirres, 1093 common); 1094 unsigned int starting_length = resp->dirlist.len; 1095 1096 /* The offset cookie for the previous entry */ 1097 nfs3svc_encode_cookie3(resp, offset); 1098 1099 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1100 goto out_toosmall; 1101 1102 xdr_commit_encode(&resp->xdr); 1103 resp->common.err = nfs_ok; 1104 return 0; 1105 1106out_toosmall: 1107 resp->cookie_offset = 0; 1108 resp->common.err = nfserr_toosmall; 1109 resp->dirlist.len = starting_length; 1110 return -EINVAL; 1111} 1112 1113static bool 1114svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name, 1115 int namlen, u64 ino) 1116{ 1117 struct xdr_stream *xdr = &resp->xdr; 1118 struct svc_fh *fhp = &resp->scratch; 1119 bool result; 1120 1121 result = false; 1122 fh_init(fhp, NFS3_FHSIZE); 1123 if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok) 1124 goto out_noattrs; 1125 1126 if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp)) 1127 goto out; 1128 if (!svcxdr_encode_post_op_fh3(xdr, fhp)) 1129 goto out; 1130 result = true; 1131 1132out: 1133 fh_put(fhp); 1134 return result; 1135 1136out_noattrs: 1137 if (xdr_stream_encode_item_absent(xdr) < 0) 1138 return false; 1139 if (xdr_stream_encode_item_absent(xdr) < 0) 1140 return false; 1141 return true; 1142} 1143 1144/** 1145 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry 1146 * @data: directory context 1147 * @name: name of the object to be encoded 1148 * @namlen: length of that name, in bytes 1149 * @offset: the offset of the previous entry 1150 * @ino: the fileid of this entry 1151 * @d_type: unused 1152 * 1153 * Return values: 1154 * %0: Entry was successfully encoded. 1155 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1156 * 1157 * On exit, the following fields are updated: 1158 * - resp->xdr 1159 * - resp->common.err 1160 * - resp->cookie_offset 1161 */ 1162int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen, 1163 loff_t offset, u64 ino, unsigned int d_type) 1164{ 1165 struct readdir_cd *ccd = data; 1166 struct nfsd3_readdirres *resp = container_of(ccd, 1167 struct nfsd3_readdirres, 1168 common); 1169 unsigned int starting_length = resp->dirlist.len; 1170 1171 /* The offset cookie for the previous entry */ 1172 nfs3svc_encode_cookie3(resp, offset); 1173 1174 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1175 goto out_toosmall; 1176 if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino)) 1177 goto out_toosmall; 1178 1179 xdr_commit_encode(&resp->xdr); 1180 resp->common.err = nfs_ok; 1181 return 0; 1182 1183out_toosmall: 1184 resp->cookie_offset = 0; 1185 resp->common.err = nfserr_toosmall; 1186 resp->dirlist.len = starting_length; 1187 return -EINVAL; 1188} 1189 1190static bool 1191svcxdr_encode_fsstat3resok(struct xdr_stream *xdr, 1192 const struct nfsd3_fsstatres *resp) 1193{ 1194 const struct kstatfs *s = &resp->stats; 1195 u64 bs = s->f_bsize; 1196 __be32 *p; 1197 1198 p = xdr_reserve_space(xdr, XDR_UNIT * 13); 1199 if (!p) 1200 return false; 1201 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1202 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1203 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1204 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1205 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1206 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1207 *p = cpu_to_be32(resp->invarsec); /* mean unchanged time */ 1208 1209 return true; 1210} 1211 1212/* FSSTAT */ 1213bool 1214nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1215{ 1216 struct nfsd3_fsstatres *resp = rqstp->rq_resp; 1217 1218 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1219 return false; 1220 switch (resp->status) { 1221 case nfs_ok: 1222 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1223 return false; 1224 if (!svcxdr_encode_fsstat3resok(xdr, resp)) 1225 return false; 1226 break; 1227 default: 1228 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1229 return false; 1230 } 1231 1232 return true; 1233} 1234 1235static bool 1236svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr, 1237 const struct nfsd3_fsinfores *resp) 1238{ 1239 __be32 *p; 1240 1241 p = xdr_reserve_space(xdr, XDR_UNIT * 12); 1242 if (!p) 1243 return false; 1244 *p++ = cpu_to_be32(resp->f_rtmax); 1245 *p++ = cpu_to_be32(resp->f_rtpref); 1246 *p++ = cpu_to_be32(resp->f_rtmult); 1247 *p++ = cpu_to_be32(resp->f_wtmax); 1248 *p++ = cpu_to_be32(resp->f_wtpref); 1249 *p++ = cpu_to_be32(resp->f_wtmult); 1250 *p++ = cpu_to_be32(resp->f_dtpref); 1251 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1252 p = encode_nfstime3(p, &nfs3svc_time_delta); 1253 *p = cpu_to_be32(resp->f_properties); 1254 1255 return true; 1256} 1257 1258/* FSINFO */ 1259bool 1260nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1261{ 1262 struct nfsd3_fsinfores *resp = rqstp->rq_resp; 1263 1264 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1265 return false; 1266 switch (resp->status) { 1267 case nfs_ok: 1268 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1269 return false; 1270 if (!svcxdr_encode_fsinfo3resok(xdr, resp)) 1271 return false; 1272 break; 1273 default: 1274 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1275 return false; 1276 } 1277 1278 return true; 1279} 1280 1281static bool 1282svcxdr_encode_pathconf3resok(struct xdr_stream *xdr, 1283 const struct nfsd3_pathconfres *resp) 1284{ 1285 __be32 *p; 1286 1287 p = xdr_reserve_space(xdr, XDR_UNIT * 6); 1288 if (!p) 1289 return false; 1290 *p++ = cpu_to_be32(resp->p_link_max); 1291 *p++ = cpu_to_be32(resp->p_name_max); 1292 p = xdr_encode_bool(p, resp->p_no_trunc); 1293 p = xdr_encode_bool(p, resp->p_chown_restricted); 1294 p = xdr_encode_bool(p, resp->p_case_insensitive); 1295 xdr_encode_bool(p, resp->p_case_preserving); 1296 1297 return true; 1298} 1299 1300/* PATHCONF */ 1301bool 1302nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1303{ 1304 struct nfsd3_pathconfres *resp = rqstp->rq_resp; 1305 1306 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1307 return false; 1308 switch (resp->status) { 1309 case nfs_ok: 1310 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1311 return false; 1312 if (!svcxdr_encode_pathconf3resok(xdr, resp)) 1313 return false; 1314 break; 1315 default: 1316 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1317 return false; 1318 } 1319 1320 return true; 1321} 1322 1323/* COMMIT */ 1324bool 1325nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1326{ 1327 struct nfsd3_commitres *resp = rqstp->rq_resp; 1328 1329 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1330 return false; 1331 switch (resp->status) { 1332 case nfs_ok: 1333 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1334 return false; 1335 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 1336 return false; 1337 break; 1338 default: 1339 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1340 return false; 1341 } 1342 1343 return true; 1344} 1345 1346/* 1347 * XDR release functions 1348 */ 1349void 1350nfs3svc_release_fhandle(struct svc_rqst *rqstp) 1351{ 1352 struct nfsd3_attrstat *resp = rqstp->rq_resp; 1353 1354 fh_put(&resp->fh); 1355} 1356 1357void 1358nfs3svc_release_fhandle2(struct svc_rqst *rqstp) 1359{ 1360 struct nfsd3_fhandle_pair *resp = rqstp->rq_resp; 1361 1362 fh_put(&resp->fh1); 1363 fh_put(&resp->fh2); 1364}