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 */ 20 static 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 */ 28 static 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 */ 36 static 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 48 static __be32 * 49 encode_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 57 static bool 58 svcxdr_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 */ 80 bool 81 svcxdr_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 */ 109 bool 110 svcxdr_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 122 static bool 123 svcxdr_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 139 static bool 140 svcxdr_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 150 static bool 151 svcxdr_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 163 static bool 164 svcxdr_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 176 static bool 177 svcxdr_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 201 static bool 202 svcxdr_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 209 static bool 210 svcxdr_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 295 static bool 296 svcxdr_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 315 static bool 316 svcxdr_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 329 static bool 330 svcxdr_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 337 static bool 338 svcxdr_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 389 static bool 390 svcxdr_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 404 static bool 405 svcxdr_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 */ 428 bool 429 svcxdr_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 453 no_post_op_attrs: 454 return xdr_stream_encode_item_absent(xdr) > 0; 455 } 456 457 /* 458 * Encode weak cache consistency data 459 */ 460 static bool 461 svcxdr_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 481 neither: 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 494 bool 495 nfs3svc_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 502 bool 503 nfs3svc_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 512 bool 513 nfs3svc_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 520 bool 521 nfs3svc_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 533 bool 534 nfs3svc_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 548 bool 549 nfs3svc_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 575 return xdr_stream_subsegment(xdr, &args->payload, args->count); 576 } 577 578 bool 579 nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 580 { 581 struct nfsd3_createargs *args = rqstp->rq_argp; 582 583 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 584 return false; 585 if (xdr_stream_decode_u32(xdr, &args->createmode) < 0) 586 return false; 587 switch (args->createmode) { 588 case NFS3_CREATE_UNCHECKED: 589 case NFS3_CREATE_GUARDED: 590 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 591 case NFS3_CREATE_EXCLUSIVE: 592 args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE); 593 if (!args->verf) 594 return false; 595 break; 596 default: 597 return false; 598 } 599 return true; 600 } 601 602 bool 603 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 604 { 605 struct nfsd3_createargs *args = rqstp->rq_argp; 606 607 return svcxdr_decode_diropargs3(xdr, &args->fh, 608 &args->name, &args->len) && 609 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 610 } 611 612 bool 613 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 614 { 615 struct nfsd3_symlinkargs *args = rqstp->rq_argp; 616 struct kvec *head = rqstp->rq_arg.head; 617 618 if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen)) 619 return false; 620 if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs)) 621 return false; 622 if (xdr_stream_decode_u32(xdr, &args->tlen) < 0) 623 return false; 624 625 /* symlink_data */ 626 args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); 627 args->first.iov_base = xdr_inline_decode(xdr, args->tlen); 628 return args->first.iov_base != NULL; 629 } 630 631 bool 632 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 633 { 634 struct nfsd3_mknodargs *args = rqstp->rq_argp; 635 636 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 637 return false; 638 if (xdr_stream_decode_u32(xdr, &args->ftype) < 0) 639 return false; 640 switch (args->ftype) { 641 case NF3CHR: 642 case NF3BLK: 643 return svcxdr_decode_devicedata3(rqstp, xdr, args); 644 case NF3SOCK: 645 case NF3FIFO: 646 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 647 case NF3REG: 648 case NF3DIR: 649 case NF3LNK: 650 /* Valid XDR but illegal file types */ 651 break; 652 default: 653 return false; 654 } 655 656 return true; 657 } 658 659 bool 660 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 661 { 662 struct nfsd3_renameargs *args = rqstp->rq_argp; 663 664 return svcxdr_decode_diropargs3(xdr, &args->ffh, 665 &args->fname, &args->flen) && 666 svcxdr_decode_diropargs3(xdr, &args->tfh, 667 &args->tname, &args->tlen); 668 } 669 670 bool 671 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 672 { 673 struct nfsd3_linkargs *args = rqstp->rq_argp; 674 675 return svcxdr_decode_nfs_fh3(xdr, &args->ffh) && 676 svcxdr_decode_diropargs3(xdr, &args->tfh, 677 &args->tname, &args->tlen); 678 } 679 680 bool 681 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 682 { 683 struct nfsd3_readdirargs *args = rqstp->rq_argp; 684 685 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 686 return false; 687 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 688 return false; 689 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 690 if (!args->verf) 691 return false; 692 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 693 return false; 694 695 return true; 696 } 697 698 bool 699 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 700 { 701 struct nfsd3_readdirargs *args = rqstp->rq_argp; 702 u32 dircount; 703 704 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 705 return false; 706 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 707 return false; 708 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 709 if (!args->verf) 710 return false; 711 /* dircount is ignored */ 712 if (xdr_stream_decode_u32(xdr, &dircount) < 0) 713 return false; 714 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 715 return false; 716 717 return true; 718 } 719 720 bool 721 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 722 { 723 struct nfsd3_commitargs *args = rqstp->rq_argp; 724 725 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 726 return false; 727 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 728 return false; 729 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 730 return false; 731 732 return true; 733 } 734 735 /* 736 * XDR encode functions 737 */ 738 739 /* GETATTR */ 740 bool 741 nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 742 { 743 struct nfsd3_attrstat *resp = rqstp->rq_resp; 744 745 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 746 return false; 747 switch (resp->status) { 748 case nfs_ok: 749 lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime); 750 if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat)) 751 return false; 752 break; 753 } 754 755 return true; 756 } 757 758 /* SETATTR, REMOVE, RMDIR */ 759 bool 760 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr) 761 { 762 struct nfsd3_attrstat *resp = rqstp->rq_resp; 763 764 return svcxdr_encode_nfsstat3(xdr, resp->status) && 765 svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh); 766 } 767 768 /* LOOKUP */ 769 bool 770 nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 771 { 772 struct nfsd3_diropres *resp = rqstp->rq_resp; 773 774 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 775 return false; 776 switch (resp->status) { 777 case nfs_ok: 778 if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh)) 779 return false; 780 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 781 return false; 782 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 783 return false; 784 break; 785 default: 786 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 787 return false; 788 } 789 790 return true; 791 } 792 793 /* ACCESS */ 794 bool 795 nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 796 { 797 struct nfsd3_accessres *resp = rqstp->rq_resp; 798 799 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 800 return false; 801 switch (resp->status) { 802 case nfs_ok: 803 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 804 return false; 805 if (xdr_stream_encode_u32(xdr, resp->access) < 0) 806 return false; 807 break; 808 default: 809 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 810 return false; 811 } 812 813 return true; 814 } 815 816 /* READLINK */ 817 bool 818 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 819 { 820 struct nfsd3_readlinkres *resp = rqstp->rq_resp; 821 struct kvec *head = rqstp->rq_res.head; 822 823 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 824 return false; 825 switch (resp->status) { 826 case nfs_ok: 827 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 828 return false; 829 if (xdr_stream_encode_u32(xdr, resp->len) < 0) 830 return false; 831 svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0, 832 resp->len); 833 if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0) 834 return false; 835 break; 836 default: 837 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 838 return false; 839 } 840 841 return true; 842 } 843 844 /* READ */ 845 bool 846 nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 847 { 848 struct nfsd3_readres *resp = rqstp->rq_resp; 849 struct kvec *head = rqstp->rq_res.head; 850 851 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 852 return false; 853 switch (resp->status) { 854 case nfs_ok: 855 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 856 return false; 857 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 858 return false; 859 if (xdr_stream_encode_bool(xdr, resp->eof) < 0) 860 return false; 861 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 862 return false; 863 svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 864 rqstp->rq_res.page_base, 865 resp->count); 866 if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0) 867 return false; 868 break; 869 default: 870 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 871 return false; 872 } 873 874 return true; 875 } 876 877 /* WRITE */ 878 bool 879 nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 880 { 881 struct nfsd3_writeres *resp = rqstp->rq_resp; 882 883 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 884 return false; 885 switch (resp->status) { 886 case nfs_ok: 887 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 888 return false; 889 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 890 return false; 891 if (xdr_stream_encode_u32(xdr, resp->committed) < 0) 892 return false; 893 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 894 return false; 895 break; 896 default: 897 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 898 return false; 899 } 900 901 return true; 902 } 903 904 /* CREATE, MKDIR, SYMLINK, MKNOD */ 905 bool 906 nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 907 { 908 struct nfsd3_diropres *resp = rqstp->rq_resp; 909 910 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 911 return false; 912 switch (resp->status) { 913 case nfs_ok: 914 if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh)) 915 return false; 916 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 917 return false; 918 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 919 return false; 920 break; 921 default: 922 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 923 return false; 924 } 925 926 return true; 927 } 928 929 /* RENAME */ 930 bool 931 nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 932 { 933 struct nfsd3_renameres *resp = rqstp->rq_resp; 934 935 return svcxdr_encode_nfsstat3(xdr, resp->status) && 936 svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) && 937 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 938 } 939 940 /* LINK */ 941 bool 942 nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 943 { 944 struct nfsd3_linkres *resp = rqstp->rq_resp; 945 946 return svcxdr_encode_nfsstat3(xdr, resp->status) && 947 svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) && 948 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 949 } 950 951 /* READDIR */ 952 bool 953 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 954 { 955 struct nfsd3_readdirres *resp = rqstp->rq_resp; 956 struct xdr_buf *dirlist = &resp->dirlist; 957 958 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 959 return false; 960 switch (resp->status) { 961 case nfs_ok: 962 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 963 return false; 964 if (!svcxdr_encode_cookieverf3(xdr, resp->verf)) 965 return false; 966 svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0, 967 dirlist->len); 968 /* no more entries */ 969 if (xdr_stream_encode_item_absent(xdr) < 0) 970 return false; 971 if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0) 972 return false; 973 break; 974 default: 975 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 976 return false; 977 } 978 979 return true; 980 } 981 982 static __be32 983 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 984 const char *name, int namlen, u64 ino) 985 { 986 struct svc_export *exp; 987 struct dentry *dparent, *dchild; 988 __be32 rv = nfserr_noent; 989 990 dparent = cd->fh.fh_dentry; 991 exp = cd->fh.fh_export; 992 993 if (isdotent(name, namlen)) { 994 if (namlen == 2) { 995 dchild = dget_parent(dparent); 996 /* 997 * Don't return filehandle for ".." if we're at 998 * the filesystem or export root: 999 */ 1000 if (dchild == dparent) 1001 goto out; 1002 if (dparent == exp->ex_path.dentry) 1003 goto out; 1004 } else 1005 dchild = dget(dparent); 1006 } else 1007 dchild = lookup_positive_unlocked(name, dparent, namlen); 1008 if (IS_ERR(dchild)) 1009 return rv; 1010 if (d_mountpoint(dchild)) 1011 goto out; 1012 if (dchild->d_inode->i_ino != ino) 1013 goto out; 1014 rv = fh_compose(fhp, exp, dchild, &cd->fh); 1015 out: 1016 dput(dchild); 1017 return rv; 1018 } 1019 1020 /** 1021 * nfs3svc_encode_cookie3 - Encode a directory offset cookie 1022 * @resp: readdir result context 1023 * @offset: offset cookie to encode 1024 * 1025 * The buffer space for the offset cookie has already been reserved 1026 * by svcxdr_encode_entry3_common(). 1027 */ 1028 void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset) 1029 { 1030 __be64 cookie = cpu_to_be64(offset); 1031 1032 if (!resp->cookie_offset) 1033 return; 1034 write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie, 1035 sizeof(cookie)); 1036 resp->cookie_offset = 0; 1037 } 1038 1039 static bool 1040 svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name, 1041 int namlen, loff_t offset, u64 ino) 1042 { 1043 struct xdr_buf *dirlist = &resp->dirlist; 1044 struct xdr_stream *xdr = &resp->xdr; 1045 1046 if (xdr_stream_encode_item_present(xdr) < 0) 1047 return false; 1048 /* fileid */ 1049 if (xdr_stream_encode_u64(xdr, ino) < 0) 1050 return false; 1051 /* name */ 1052 if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0) 1053 return false; 1054 /* cookie */ 1055 resp->cookie_offset = dirlist->len; 1056 if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0) 1057 return false; 1058 1059 return true; 1060 } 1061 1062 /** 1063 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry 1064 * @data: directory context 1065 * @name: name of the object to be encoded 1066 * @namlen: length of that name, in bytes 1067 * @offset: the offset of the previous entry 1068 * @ino: the fileid of this entry 1069 * @d_type: unused 1070 * 1071 * Return values: 1072 * %0: Entry was successfully encoded. 1073 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1074 * 1075 * On exit, the following fields are updated: 1076 * - resp->xdr 1077 * - resp->common.err 1078 * - resp->cookie_offset 1079 */ 1080 int nfs3svc_encode_entry3(void *data, const char *name, int namlen, 1081 loff_t offset, u64 ino, unsigned int d_type) 1082 { 1083 struct readdir_cd *ccd = data; 1084 struct nfsd3_readdirres *resp = container_of(ccd, 1085 struct nfsd3_readdirres, 1086 common); 1087 unsigned int starting_length = resp->dirlist.len; 1088 1089 /* The offset cookie for the previous entry */ 1090 nfs3svc_encode_cookie3(resp, offset); 1091 1092 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1093 goto out_toosmall; 1094 1095 xdr_commit_encode(&resp->xdr); 1096 resp->common.err = nfs_ok; 1097 return 0; 1098 1099 out_toosmall: 1100 resp->cookie_offset = 0; 1101 resp->common.err = nfserr_toosmall; 1102 resp->dirlist.len = starting_length; 1103 return -EINVAL; 1104 } 1105 1106 static bool 1107 svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name, 1108 int namlen, u64 ino) 1109 { 1110 struct xdr_stream *xdr = &resp->xdr; 1111 struct svc_fh *fhp = &resp->scratch; 1112 bool result; 1113 1114 result = false; 1115 fh_init(fhp, NFS3_FHSIZE); 1116 if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok) 1117 goto out_noattrs; 1118 1119 if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp)) 1120 goto out; 1121 if (!svcxdr_encode_post_op_fh3(xdr, fhp)) 1122 goto out; 1123 result = true; 1124 1125 out: 1126 fh_put(fhp); 1127 return result; 1128 1129 out_noattrs: 1130 if (xdr_stream_encode_item_absent(xdr) < 0) 1131 return false; 1132 if (xdr_stream_encode_item_absent(xdr) < 0) 1133 return false; 1134 return true; 1135 } 1136 1137 /** 1138 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry 1139 * @data: directory context 1140 * @name: name of the object to be encoded 1141 * @namlen: length of that name, in bytes 1142 * @offset: the offset of the previous entry 1143 * @ino: the fileid of this entry 1144 * @d_type: unused 1145 * 1146 * Return values: 1147 * %0: Entry was successfully encoded. 1148 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1149 * 1150 * On exit, the following fields are updated: 1151 * - resp->xdr 1152 * - resp->common.err 1153 * - resp->cookie_offset 1154 */ 1155 int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen, 1156 loff_t offset, u64 ino, unsigned int d_type) 1157 { 1158 struct readdir_cd *ccd = data; 1159 struct nfsd3_readdirres *resp = container_of(ccd, 1160 struct nfsd3_readdirres, 1161 common); 1162 unsigned int starting_length = resp->dirlist.len; 1163 1164 /* The offset cookie for the previous entry */ 1165 nfs3svc_encode_cookie3(resp, offset); 1166 1167 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1168 goto out_toosmall; 1169 if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino)) 1170 goto out_toosmall; 1171 1172 xdr_commit_encode(&resp->xdr); 1173 resp->common.err = nfs_ok; 1174 return 0; 1175 1176 out_toosmall: 1177 resp->cookie_offset = 0; 1178 resp->common.err = nfserr_toosmall; 1179 resp->dirlist.len = starting_length; 1180 return -EINVAL; 1181 } 1182 1183 static bool 1184 svcxdr_encode_fsstat3resok(struct xdr_stream *xdr, 1185 const struct nfsd3_fsstatres *resp) 1186 { 1187 const struct kstatfs *s = &resp->stats; 1188 u64 bs = s->f_bsize; 1189 __be32 *p; 1190 1191 p = xdr_reserve_space(xdr, XDR_UNIT * 13); 1192 if (!p) 1193 return false; 1194 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1195 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1196 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1197 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1198 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1199 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1200 *p = cpu_to_be32(resp->invarsec); /* mean unchanged time */ 1201 1202 return true; 1203 } 1204 1205 /* FSSTAT */ 1206 bool 1207 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1208 { 1209 struct nfsd3_fsstatres *resp = rqstp->rq_resp; 1210 1211 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1212 return false; 1213 switch (resp->status) { 1214 case nfs_ok: 1215 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1216 return false; 1217 if (!svcxdr_encode_fsstat3resok(xdr, resp)) 1218 return false; 1219 break; 1220 default: 1221 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1222 return false; 1223 } 1224 1225 return true; 1226 } 1227 1228 static bool 1229 svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr, 1230 const struct nfsd3_fsinfores *resp) 1231 { 1232 __be32 *p; 1233 1234 p = xdr_reserve_space(xdr, XDR_UNIT * 12); 1235 if (!p) 1236 return false; 1237 *p++ = cpu_to_be32(resp->f_rtmax); 1238 *p++ = cpu_to_be32(resp->f_rtpref); 1239 *p++ = cpu_to_be32(resp->f_rtmult); 1240 *p++ = cpu_to_be32(resp->f_wtmax); 1241 *p++ = cpu_to_be32(resp->f_wtpref); 1242 *p++ = cpu_to_be32(resp->f_wtmult); 1243 *p++ = cpu_to_be32(resp->f_dtpref); 1244 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1245 p = encode_nfstime3(p, &nfs3svc_time_delta); 1246 *p = cpu_to_be32(resp->f_properties); 1247 1248 return true; 1249 } 1250 1251 /* FSINFO */ 1252 bool 1253 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1254 { 1255 struct nfsd3_fsinfores *resp = rqstp->rq_resp; 1256 1257 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1258 return false; 1259 switch (resp->status) { 1260 case nfs_ok: 1261 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1262 return false; 1263 if (!svcxdr_encode_fsinfo3resok(xdr, resp)) 1264 return false; 1265 break; 1266 default: 1267 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1268 return false; 1269 } 1270 1271 return true; 1272 } 1273 1274 static bool 1275 svcxdr_encode_pathconf3resok(struct xdr_stream *xdr, 1276 const struct nfsd3_pathconfres *resp) 1277 { 1278 __be32 *p; 1279 1280 p = xdr_reserve_space(xdr, XDR_UNIT * 6); 1281 if (!p) 1282 return false; 1283 *p++ = cpu_to_be32(resp->p_link_max); 1284 *p++ = cpu_to_be32(resp->p_name_max); 1285 p = xdr_encode_bool(p, resp->p_no_trunc); 1286 p = xdr_encode_bool(p, resp->p_chown_restricted); 1287 p = xdr_encode_bool(p, resp->p_case_insensitive); 1288 xdr_encode_bool(p, resp->p_case_preserving); 1289 1290 return true; 1291 } 1292 1293 /* PATHCONF */ 1294 bool 1295 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1296 { 1297 struct nfsd3_pathconfres *resp = rqstp->rq_resp; 1298 1299 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1300 return false; 1301 switch (resp->status) { 1302 case nfs_ok: 1303 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1304 return false; 1305 if (!svcxdr_encode_pathconf3resok(xdr, resp)) 1306 return false; 1307 break; 1308 default: 1309 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1310 return false; 1311 } 1312 1313 return true; 1314 } 1315 1316 /* COMMIT */ 1317 bool 1318 nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1319 { 1320 struct nfsd3_commitres *resp = rqstp->rq_resp; 1321 1322 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1323 return false; 1324 switch (resp->status) { 1325 case nfs_ok: 1326 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1327 return false; 1328 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 1329 return false; 1330 break; 1331 default: 1332 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1333 return false; 1334 } 1335 1336 return true; 1337 } 1338 1339 /* 1340 * XDR release functions 1341 */ 1342 void 1343 nfs3svc_release_fhandle(struct svc_rqst *rqstp) 1344 { 1345 struct nfsd3_attrstat *resp = rqstp->rq_resp; 1346 1347 fh_put(&resp->fh); 1348 } 1349 1350 void 1351 nfs3svc_release_fhandle2(struct svc_rqst *rqstp) 1352 { 1353 struct nfsd3_fhandle_pair *resp = rqstp->rq_resp; 1354 1355 fh_put(&resp->fh1); 1356 fh_put(&resp->fh2); 1357 } 1358