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 u32 check; 299 300 if (xdr_stream_decode_bool(xdr, &check) < 0) 301 return false; 302 if (check) { 303 if (!svcxdr_decode_nfstime3(xdr, &args->guardtime)) 304 return false; 305 args->check_guard = 1; 306 } else 307 args->check_guard = 0; 308 309 return true; 310 } 311 312 static bool 313 svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args) 314 { 315 __be32 *p; 316 317 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 318 if (!p) 319 return false; 320 args->major = be32_to_cpup(p++); 321 args->minor = be32_to_cpup(p); 322 323 return true; 324 } 325 326 static bool 327 svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 328 struct nfsd3_mknodargs *args) 329 { 330 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 331 svcxdr_decode_specdata3(xdr, args); 332 } 333 334 static bool 335 svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 336 const struct svc_fh *fhp, const struct kstat *stat) 337 { 338 struct user_namespace *userns = nfsd_user_namespace(rqstp); 339 __be32 *p; 340 u64 fsid; 341 342 p = xdr_reserve_space(xdr, XDR_UNIT * 21); 343 if (!p) 344 return false; 345 346 *p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 347 *p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO)); 348 *p++ = cpu_to_be32((u32)stat->nlink); 349 *p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid)); 350 *p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid)); 351 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) 352 p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN); 353 else 354 p = xdr_encode_hyper(p, (u64)stat->size); 355 356 /* used */ 357 p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); 358 359 /* rdev */ 360 *p++ = cpu_to_be32((u32)MAJOR(stat->rdev)); 361 *p++ = cpu_to_be32((u32)MINOR(stat->rdev)); 362 363 switch(fsid_source(fhp)) { 364 case FSIDSOURCE_FSID: 365 fsid = (u64)fhp->fh_export->ex_fsid; 366 break; 367 case FSIDSOURCE_UUID: 368 fsid = ((u64 *)fhp->fh_export->ex_uuid)[0]; 369 fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1]; 370 break; 371 default: 372 fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev); 373 } 374 p = xdr_encode_hyper(p, fsid); 375 376 /* fileid */ 377 p = xdr_encode_hyper(p, stat->ino); 378 379 p = encode_nfstime3(p, &stat->atime); 380 p = encode_nfstime3(p, &stat->mtime); 381 encode_nfstime3(p, &stat->ctime); 382 383 return true; 384 } 385 386 static bool 387 svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp) 388 { 389 __be32 *p; 390 391 p = xdr_reserve_space(xdr, XDR_UNIT * 6); 392 if (!p) 393 return false; 394 p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size); 395 p = encode_nfstime3(p, &fhp->fh_pre_mtime); 396 encode_nfstime3(p, &fhp->fh_pre_ctime); 397 398 return true; 399 } 400 401 static bool 402 svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp) 403 { 404 if (!fhp->fh_pre_saved) { 405 if (xdr_stream_encode_item_absent(xdr) < 0) 406 return false; 407 return true; 408 } 409 410 if (xdr_stream_encode_item_present(xdr) < 0) 411 return false; 412 return svcxdr_encode_wcc_attr(xdr, fhp); 413 } 414 415 /** 416 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes 417 * @rqstp: Context of a completed RPC transaction 418 * @xdr: XDR stream 419 * @fhp: File handle to encode 420 * 421 * Return values: 422 * %false: Send buffer space was exhausted 423 * %true: Success 424 */ 425 bool 426 svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr, 427 const struct svc_fh *fhp) 428 { 429 struct dentry *dentry = fhp->fh_dentry; 430 struct kstat stat; 431 432 /* 433 * The inode may be NULL if the call failed because of a 434 * stale file handle. In this case, no attributes are 435 * returned. 436 */ 437 if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry)) 438 goto no_post_op_attrs; 439 if (fh_getattr(fhp, &stat) != nfs_ok) 440 goto no_post_op_attrs; 441 442 if (xdr_stream_encode_item_present(xdr) < 0) 443 return false; 444 lease_get_mtime(d_inode(dentry), &stat.mtime); 445 if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat)) 446 return false; 447 448 return true; 449 450 no_post_op_attrs: 451 return xdr_stream_encode_item_absent(xdr) > 0; 452 } 453 454 /* 455 * Encode weak cache consistency data 456 */ 457 static bool 458 svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr, 459 const struct svc_fh *fhp) 460 { 461 struct dentry *dentry = fhp->fh_dentry; 462 463 if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved) 464 goto neither; 465 466 /* before */ 467 if (!svcxdr_encode_pre_op_attr(xdr, fhp)) 468 return false; 469 470 /* after */ 471 if (xdr_stream_encode_item_present(xdr) < 0) 472 return false; 473 if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr)) 474 return false; 475 476 return true; 477 478 neither: 479 if (xdr_stream_encode_item_absent(xdr) < 0) 480 return false; 481 if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp)) 482 return false; 483 484 return true; 485 } 486 487 /* 488 * XDR decode functions 489 */ 490 491 bool 492 nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 493 { 494 struct nfsd_fhandle *args = rqstp->rq_argp; 495 496 return svcxdr_decode_nfs_fh3(xdr, &args->fh); 497 } 498 499 bool 500 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 501 { 502 struct nfsd3_sattrargs *args = rqstp->rq_argp; 503 504 return svcxdr_decode_nfs_fh3(xdr, &args->fh) && 505 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 506 svcxdr_decode_sattrguard3(xdr, args); 507 } 508 509 bool 510 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 511 { 512 struct nfsd3_diropargs *args = rqstp->rq_argp; 513 514 return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len); 515 } 516 517 bool 518 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 519 { 520 struct nfsd3_accessargs *args = rqstp->rq_argp; 521 522 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 523 return false; 524 if (xdr_stream_decode_u32(xdr, &args->access) < 0) 525 return false; 526 527 return true; 528 } 529 530 bool 531 nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 532 { 533 struct nfsd3_readargs *args = rqstp->rq_argp; 534 535 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 536 return false; 537 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 538 return false; 539 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 540 return false; 541 542 return true; 543 } 544 545 bool 546 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 547 { 548 struct nfsd3_writeargs *args = rqstp->rq_argp; 549 u32 max_blocksize = svc_max_payload(rqstp); 550 551 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 552 return false; 553 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 554 return false; 555 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 556 return false; 557 if (xdr_stream_decode_u32(xdr, &args->stable) < 0) 558 return false; 559 560 /* opaque data */ 561 if (xdr_stream_decode_u32(xdr, &args->len) < 0) 562 return false; 563 564 /* request sanity */ 565 if (args->count != args->len) 566 return false; 567 if (args->count > max_blocksize) { 568 args->count = max_blocksize; 569 args->len = max_blocksize; 570 } 571 572 return xdr_stream_subsegment(xdr, &args->payload, args->count); 573 } 574 575 bool 576 nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 577 { 578 struct nfsd3_createargs *args = rqstp->rq_argp; 579 580 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 581 return false; 582 if (xdr_stream_decode_u32(xdr, &args->createmode) < 0) 583 return false; 584 switch (args->createmode) { 585 case NFS3_CREATE_UNCHECKED: 586 case NFS3_CREATE_GUARDED: 587 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 588 case NFS3_CREATE_EXCLUSIVE: 589 args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE); 590 if (!args->verf) 591 return false; 592 break; 593 default: 594 return false; 595 } 596 return true; 597 } 598 599 bool 600 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 601 { 602 struct nfsd3_createargs *args = rqstp->rq_argp; 603 604 return svcxdr_decode_diropargs3(xdr, &args->fh, 605 &args->name, &args->len) && 606 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 607 } 608 609 bool 610 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 611 { 612 struct nfsd3_symlinkargs *args = rqstp->rq_argp; 613 struct kvec *head = rqstp->rq_arg.head; 614 615 if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen)) 616 return false; 617 if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs)) 618 return false; 619 if (xdr_stream_decode_u32(xdr, &args->tlen) < 0) 620 return false; 621 622 /* symlink_data */ 623 args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); 624 args->first.iov_base = xdr_inline_decode(xdr, args->tlen); 625 return args->first.iov_base != NULL; 626 } 627 628 bool 629 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 630 { 631 struct nfsd3_mknodargs *args = rqstp->rq_argp; 632 633 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 634 return false; 635 if (xdr_stream_decode_u32(xdr, &args->ftype) < 0) 636 return false; 637 switch (args->ftype) { 638 case NF3CHR: 639 case NF3BLK: 640 return svcxdr_decode_devicedata3(rqstp, xdr, args); 641 case NF3SOCK: 642 case NF3FIFO: 643 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 644 case NF3REG: 645 case NF3DIR: 646 case NF3LNK: 647 /* Valid XDR but illegal file types */ 648 break; 649 default: 650 return false; 651 } 652 653 return true; 654 } 655 656 bool 657 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 658 { 659 struct nfsd3_renameargs *args = rqstp->rq_argp; 660 661 return svcxdr_decode_diropargs3(xdr, &args->ffh, 662 &args->fname, &args->flen) && 663 svcxdr_decode_diropargs3(xdr, &args->tfh, 664 &args->tname, &args->tlen); 665 } 666 667 bool 668 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 669 { 670 struct nfsd3_linkargs *args = rqstp->rq_argp; 671 672 return svcxdr_decode_nfs_fh3(xdr, &args->ffh) && 673 svcxdr_decode_diropargs3(xdr, &args->tfh, 674 &args->tname, &args->tlen); 675 } 676 677 bool 678 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 679 { 680 struct nfsd3_readdirargs *args = rqstp->rq_argp; 681 682 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 683 return false; 684 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 685 return false; 686 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 687 if (!args->verf) 688 return false; 689 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 690 return false; 691 692 return true; 693 } 694 695 bool 696 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 697 { 698 struct nfsd3_readdirargs *args = rqstp->rq_argp; 699 u32 dircount; 700 701 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 702 return false; 703 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 704 return false; 705 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 706 if (!args->verf) 707 return false; 708 /* dircount is ignored */ 709 if (xdr_stream_decode_u32(xdr, &dircount) < 0) 710 return false; 711 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 712 return false; 713 714 return true; 715 } 716 717 bool 718 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 719 { 720 struct nfsd3_commitargs *args = rqstp->rq_argp; 721 722 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 723 return false; 724 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 725 return false; 726 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 727 return false; 728 729 return true; 730 } 731 732 /* 733 * XDR encode functions 734 */ 735 736 /* GETATTR */ 737 bool 738 nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 739 { 740 struct nfsd3_attrstat *resp = rqstp->rq_resp; 741 742 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 743 return false; 744 switch (resp->status) { 745 case nfs_ok: 746 lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime); 747 if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat)) 748 return false; 749 break; 750 } 751 752 return true; 753 } 754 755 /* SETATTR, REMOVE, RMDIR */ 756 bool 757 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr) 758 { 759 struct nfsd3_attrstat *resp = rqstp->rq_resp; 760 761 return svcxdr_encode_nfsstat3(xdr, resp->status) && 762 svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh); 763 } 764 765 /* LOOKUP */ 766 bool 767 nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 768 { 769 struct nfsd3_diropres *resp = rqstp->rq_resp; 770 771 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 772 return false; 773 switch (resp->status) { 774 case nfs_ok: 775 if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh)) 776 return false; 777 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 778 return false; 779 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 780 return false; 781 break; 782 default: 783 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh)) 784 return false; 785 } 786 787 return true; 788 } 789 790 /* ACCESS */ 791 bool 792 nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 793 { 794 struct nfsd3_accessres *resp = rqstp->rq_resp; 795 796 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 797 return false; 798 switch (resp->status) { 799 case nfs_ok: 800 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 801 return false; 802 if (xdr_stream_encode_u32(xdr, resp->access) < 0) 803 return false; 804 break; 805 default: 806 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 807 return false; 808 } 809 810 return true; 811 } 812 813 /* READLINK */ 814 bool 815 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 816 { 817 struct nfsd3_readlinkres *resp = rqstp->rq_resp; 818 struct kvec *head = rqstp->rq_res.head; 819 820 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 821 return false; 822 switch (resp->status) { 823 case nfs_ok: 824 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 825 return false; 826 if (xdr_stream_encode_u32(xdr, resp->len) < 0) 827 return false; 828 svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0, 829 resp->len); 830 if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0) 831 return false; 832 break; 833 default: 834 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 835 return false; 836 } 837 838 return true; 839 } 840 841 /* READ */ 842 bool 843 nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 844 { 845 struct nfsd3_readres *resp = rqstp->rq_resp; 846 struct kvec *head = rqstp->rq_res.head; 847 848 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 849 return false; 850 switch (resp->status) { 851 case nfs_ok: 852 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 853 return false; 854 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 855 return false; 856 if (xdr_stream_encode_bool(xdr, resp->eof) < 0) 857 return false; 858 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 859 return false; 860 svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 861 rqstp->rq_res.page_base, 862 resp->count); 863 if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0) 864 return false; 865 break; 866 default: 867 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 868 return false; 869 } 870 871 return true; 872 } 873 874 /* WRITE */ 875 bool 876 nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 877 { 878 struct nfsd3_writeres *resp = rqstp->rq_resp; 879 880 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 881 return false; 882 switch (resp->status) { 883 case nfs_ok: 884 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 885 return false; 886 if (xdr_stream_encode_u32(xdr, resp->count) < 0) 887 return false; 888 if (xdr_stream_encode_u32(xdr, resp->committed) < 0) 889 return false; 890 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 891 return false; 892 break; 893 default: 894 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 895 return false; 896 } 897 898 return true; 899 } 900 901 /* CREATE, MKDIR, SYMLINK, MKNOD */ 902 bool 903 nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 904 { 905 struct nfsd3_diropres *resp = rqstp->rq_resp; 906 907 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 908 return false; 909 switch (resp->status) { 910 case nfs_ok: 911 if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh)) 912 return false; 913 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 914 return false; 915 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 916 return false; 917 break; 918 default: 919 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh)) 920 return false; 921 } 922 923 return true; 924 } 925 926 /* RENAME */ 927 bool 928 nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 929 { 930 struct nfsd3_renameres *resp = rqstp->rq_resp; 931 932 return svcxdr_encode_nfsstat3(xdr, resp->status) && 933 svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) && 934 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 935 } 936 937 /* LINK */ 938 bool 939 nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 940 { 941 struct nfsd3_linkres *resp = rqstp->rq_resp; 942 943 return svcxdr_encode_nfsstat3(xdr, resp->status) && 944 svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) && 945 svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh); 946 } 947 948 /* READDIR */ 949 bool 950 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 951 { 952 struct nfsd3_readdirres *resp = rqstp->rq_resp; 953 struct xdr_buf *dirlist = &resp->dirlist; 954 955 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 956 return false; 957 switch (resp->status) { 958 case nfs_ok: 959 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 960 return false; 961 if (!svcxdr_encode_cookieverf3(xdr, resp->verf)) 962 return false; 963 svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0, 964 dirlist->len); 965 /* no more entries */ 966 if (xdr_stream_encode_item_absent(xdr) < 0) 967 return false; 968 if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0) 969 return false; 970 break; 971 default: 972 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh)) 973 return false; 974 } 975 976 return true; 977 } 978 979 static __be32 980 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 981 const char *name, int namlen, u64 ino) 982 { 983 struct svc_export *exp; 984 struct dentry *dparent, *dchild; 985 __be32 rv = nfserr_noent; 986 987 dparent = cd->fh.fh_dentry; 988 exp = cd->fh.fh_export; 989 990 if (isdotent(name, namlen)) { 991 if (namlen == 2) { 992 dchild = dget_parent(dparent); 993 /* 994 * Don't return filehandle for ".." if we're at 995 * the filesystem or export root: 996 */ 997 if (dchild == dparent) 998 goto out; 999 if (dparent == exp->ex_path.dentry) 1000 goto out; 1001 } else 1002 dchild = dget(dparent); 1003 } else 1004 dchild = lookup_positive_unlocked(name, dparent, namlen); 1005 if (IS_ERR(dchild)) 1006 return rv; 1007 if (d_mountpoint(dchild)) 1008 goto out; 1009 if (dchild->d_inode->i_ino != ino) 1010 goto out; 1011 rv = fh_compose(fhp, exp, dchild, &cd->fh); 1012 out: 1013 dput(dchild); 1014 return rv; 1015 } 1016 1017 /** 1018 * nfs3svc_encode_cookie3 - Encode a directory offset cookie 1019 * @resp: readdir result context 1020 * @offset: offset cookie to encode 1021 * 1022 * The buffer space for the offset cookie has already been reserved 1023 * by svcxdr_encode_entry3_common(). 1024 */ 1025 void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset) 1026 { 1027 __be64 cookie = cpu_to_be64(offset); 1028 1029 if (!resp->cookie_offset) 1030 return; 1031 write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie, 1032 sizeof(cookie)); 1033 resp->cookie_offset = 0; 1034 } 1035 1036 static bool 1037 svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name, 1038 int namlen, loff_t offset, u64 ino) 1039 { 1040 struct xdr_buf *dirlist = &resp->dirlist; 1041 struct xdr_stream *xdr = &resp->xdr; 1042 1043 if (xdr_stream_encode_item_present(xdr) < 0) 1044 return false; 1045 /* fileid */ 1046 if (xdr_stream_encode_u64(xdr, ino) < 0) 1047 return false; 1048 /* name */ 1049 if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0) 1050 return false; 1051 /* cookie */ 1052 resp->cookie_offset = dirlist->len; 1053 if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0) 1054 return false; 1055 1056 return true; 1057 } 1058 1059 /** 1060 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry 1061 * @data: directory context 1062 * @name: name of the object to be encoded 1063 * @namlen: length of that name, in bytes 1064 * @offset: the offset of the previous entry 1065 * @ino: the fileid of this entry 1066 * @d_type: unused 1067 * 1068 * Return values: 1069 * %0: Entry was successfully encoded. 1070 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1071 * 1072 * On exit, the following fields are updated: 1073 * - resp->xdr 1074 * - resp->common.err 1075 * - resp->cookie_offset 1076 */ 1077 int nfs3svc_encode_entry3(void *data, const char *name, int namlen, 1078 loff_t offset, u64 ino, unsigned int d_type) 1079 { 1080 struct readdir_cd *ccd = data; 1081 struct nfsd3_readdirres *resp = container_of(ccd, 1082 struct nfsd3_readdirres, 1083 common); 1084 unsigned int starting_length = resp->dirlist.len; 1085 1086 /* The offset cookie for the previous entry */ 1087 nfs3svc_encode_cookie3(resp, offset); 1088 1089 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1090 goto out_toosmall; 1091 1092 xdr_commit_encode(&resp->xdr); 1093 resp->common.err = nfs_ok; 1094 return 0; 1095 1096 out_toosmall: 1097 resp->cookie_offset = 0; 1098 resp->common.err = nfserr_toosmall; 1099 resp->dirlist.len = starting_length; 1100 return -EINVAL; 1101 } 1102 1103 static bool 1104 svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name, 1105 int namlen, u64 ino) 1106 { 1107 struct xdr_stream *xdr = &resp->xdr; 1108 struct svc_fh *fhp = &resp->scratch; 1109 bool result; 1110 1111 result = false; 1112 fh_init(fhp, NFS3_FHSIZE); 1113 if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok) 1114 goto out_noattrs; 1115 1116 if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp)) 1117 goto out; 1118 if (!svcxdr_encode_post_op_fh3(xdr, fhp)) 1119 goto out; 1120 result = true; 1121 1122 out: 1123 fh_put(fhp); 1124 return result; 1125 1126 out_noattrs: 1127 if (xdr_stream_encode_item_absent(xdr) < 0) 1128 return false; 1129 if (xdr_stream_encode_item_absent(xdr) < 0) 1130 return false; 1131 return true; 1132 } 1133 1134 /** 1135 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry 1136 * @data: directory context 1137 * @name: name of the object to be encoded 1138 * @namlen: length of that name, in bytes 1139 * @offset: the offset of the previous entry 1140 * @ino: the fileid of this entry 1141 * @d_type: unused 1142 * 1143 * Return values: 1144 * %0: Entry was successfully encoded. 1145 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err 1146 * 1147 * On exit, the following fields are updated: 1148 * - resp->xdr 1149 * - resp->common.err 1150 * - resp->cookie_offset 1151 */ 1152 int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen, 1153 loff_t offset, u64 ino, unsigned int d_type) 1154 { 1155 struct readdir_cd *ccd = data; 1156 struct nfsd3_readdirres *resp = container_of(ccd, 1157 struct nfsd3_readdirres, 1158 common); 1159 unsigned int starting_length = resp->dirlist.len; 1160 1161 /* The offset cookie for the previous entry */ 1162 nfs3svc_encode_cookie3(resp, offset); 1163 1164 if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino)) 1165 goto out_toosmall; 1166 if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino)) 1167 goto out_toosmall; 1168 1169 xdr_commit_encode(&resp->xdr); 1170 resp->common.err = nfs_ok; 1171 return 0; 1172 1173 out_toosmall: 1174 resp->cookie_offset = 0; 1175 resp->common.err = nfserr_toosmall; 1176 resp->dirlist.len = starting_length; 1177 return -EINVAL; 1178 } 1179 1180 static bool 1181 svcxdr_encode_fsstat3resok(struct xdr_stream *xdr, 1182 const struct nfsd3_fsstatres *resp) 1183 { 1184 const struct kstatfs *s = &resp->stats; 1185 u64 bs = s->f_bsize; 1186 __be32 *p; 1187 1188 p = xdr_reserve_space(xdr, XDR_UNIT * 13); 1189 if (!p) 1190 return false; 1191 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1192 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1193 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1194 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1195 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1196 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1197 *p = cpu_to_be32(resp->invarsec); /* mean unchanged time */ 1198 1199 return true; 1200 } 1201 1202 /* FSSTAT */ 1203 bool 1204 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1205 { 1206 struct nfsd3_fsstatres *resp = rqstp->rq_resp; 1207 1208 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1209 return false; 1210 switch (resp->status) { 1211 case nfs_ok: 1212 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1213 return false; 1214 if (!svcxdr_encode_fsstat3resok(xdr, resp)) 1215 return false; 1216 break; 1217 default: 1218 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1219 return false; 1220 } 1221 1222 return true; 1223 } 1224 1225 static bool 1226 svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr, 1227 const struct nfsd3_fsinfores *resp) 1228 { 1229 __be32 *p; 1230 1231 p = xdr_reserve_space(xdr, XDR_UNIT * 12); 1232 if (!p) 1233 return false; 1234 *p++ = cpu_to_be32(resp->f_rtmax); 1235 *p++ = cpu_to_be32(resp->f_rtpref); 1236 *p++ = cpu_to_be32(resp->f_rtmult); 1237 *p++ = cpu_to_be32(resp->f_wtmax); 1238 *p++ = cpu_to_be32(resp->f_wtpref); 1239 *p++ = cpu_to_be32(resp->f_wtmult); 1240 *p++ = cpu_to_be32(resp->f_dtpref); 1241 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1242 p = encode_nfstime3(p, &nfs3svc_time_delta); 1243 *p = cpu_to_be32(resp->f_properties); 1244 1245 return true; 1246 } 1247 1248 /* FSINFO */ 1249 bool 1250 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1251 { 1252 struct nfsd3_fsinfores *resp = rqstp->rq_resp; 1253 1254 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1255 return false; 1256 switch (resp->status) { 1257 case nfs_ok: 1258 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1259 return false; 1260 if (!svcxdr_encode_fsinfo3resok(xdr, resp)) 1261 return false; 1262 break; 1263 default: 1264 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1265 return false; 1266 } 1267 1268 return true; 1269 } 1270 1271 static bool 1272 svcxdr_encode_pathconf3resok(struct xdr_stream *xdr, 1273 const struct nfsd3_pathconfres *resp) 1274 { 1275 __be32 *p; 1276 1277 p = xdr_reserve_space(xdr, XDR_UNIT * 6); 1278 if (!p) 1279 return false; 1280 *p++ = cpu_to_be32(resp->p_link_max); 1281 *p++ = cpu_to_be32(resp->p_name_max); 1282 p = xdr_encode_bool(p, resp->p_no_trunc); 1283 p = xdr_encode_bool(p, resp->p_chown_restricted); 1284 p = xdr_encode_bool(p, resp->p_case_insensitive); 1285 xdr_encode_bool(p, resp->p_case_preserving); 1286 1287 return true; 1288 } 1289 1290 /* PATHCONF */ 1291 bool 1292 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1293 { 1294 struct nfsd3_pathconfres *resp = rqstp->rq_resp; 1295 1296 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1297 return false; 1298 switch (resp->status) { 1299 case nfs_ok: 1300 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1301 return false; 1302 if (!svcxdr_encode_pathconf3resok(xdr, resp)) 1303 return false; 1304 break; 1305 default: 1306 if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh)) 1307 return false; 1308 } 1309 1310 return true; 1311 } 1312 1313 /* COMMIT */ 1314 bool 1315 nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 1316 { 1317 struct nfsd3_commitres *resp = rqstp->rq_resp; 1318 1319 if (!svcxdr_encode_nfsstat3(xdr, resp->status)) 1320 return false; 1321 switch (resp->status) { 1322 case nfs_ok: 1323 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1324 return false; 1325 if (!svcxdr_encode_writeverf3(xdr, resp->verf)) 1326 return false; 1327 break; 1328 default: 1329 if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh)) 1330 return false; 1331 } 1332 1333 return true; 1334 } 1335 1336 /* 1337 * XDR release functions 1338 */ 1339 void 1340 nfs3svc_release_fhandle(struct svc_rqst *rqstp) 1341 { 1342 struct nfsd3_attrstat *resp = rqstp->rq_resp; 1343 1344 fh_put(&resp->fh); 1345 } 1346 1347 void 1348 nfs3svc_release_fhandle2(struct svc_rqst *rqstp) 1349 { 1350 struct nfsd3_fhandle_pair *resp = rqstp->rq_resp; 1351 1352 fh_put(&resp->fh1); 1353 fh_put(&resp->fh2); 1354 } 1355
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.