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 #define NFSDDBG_FACILITY NFSDDBG_XDR 18 19 20 /* 21 * Mapping of S_IF* types to NFS file types 22 */ 23 static u32 nfs3_ftypes[] = { 24 NF3NON, NF3FIFO, NF3CHR, NF3BAD, 25 NF3DIR, NF3BAD, NF3BLK, NF3BAD, 26 NF3REG, NF3BAD, NF3LNK, NF3BAD, 27 NF3SOCK, NF3BAD, NF3LNK, NF3BAD, 28 }; 29 30 31 /* 32 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6) 33 */ 34 35 static __be32 * 36 encode_time3(__be32 *p, struct timespec64 *time) 37 { 38 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); 39 return p; 40 } 41 42 static bool 43 svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep) 44 { 45 __be32 *p; 46 47 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 48 if (!p) 49 return false; 50 timep->tv_sec = be32_to_cpup(p++); 51 timep->tv_nsec = be32_to_cpup(p); 52 53 return true; 54 } 55 56 /** 57 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle 58 * @xdr: XDR stream positioned at an undecoded NFSv3 FH 59 * @fhp: OUT: filled-in server file handle 60 * 61 * Return values: 62 * %false: The encoded file handle was not valid 63 * %true: @fhp has been initialized 64 */ 65 bool 66 svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp) 67 { 68 __be32 *p; 69 u32 size; 70 71 if (xdr_stream_decode_u32(xdr, &size) < 0) 72 return false; 73 if (size == 0 || size > NFS3_FHSIZE) 74 return false; 75 p = xdr_inline_decode(xdr, size); 76 if (!p) 77 return false; 78 fh_init(fhp, NFS3_FHSIZE); 79 fhp->fh_handle.fh_size = size; 80 memcpy(&fhp->fh_handle.fh_base, p, size); 81 82 return true; 83 } 84 85 static __be32 * 86 encode_fh(__be32 *p, struct svc_fh *fhp) 87 { 88 unsigned int size = fhp->fh_handle.fh_size; 89 *p++ = htonl(size); 90 if (size) p[XDR_QUADLEN(size)-1]=0; 91 memcpy(p, &fhp->fh_handle.fh_base, size); 92 return p + XDR_QUADLEN(size); 93 } 94 95 static bool 96 svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len) 97 { 98 u32 size, i; 99 __be32 *p; 100 char *c; 101 102 if (xdr_stream_decode_u32(xdr, &size) < 0) 103 return false; 104 if (size == 0 || size > NFS3_MAXNAMLEN) 105 return false; 106 p = xdr_inline_decode(xdr, size); 107 if (!p) 108 return false; 109 110 *len = size; 111 *name = (char *)p; 112 for (i = 0, c = *name; i < size; i++, c++) { 113 if (*c == '\0' || *c == '/') 114 return false; 115 } 116 117 return true; 118 } 119 120 static bool 121 svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp, 122 char **name, unsigned int *len) 123 { 124 return svcxdr_decode_nfs_fh3(xdr, fhp) && 125 svcxdr_decode_filename3(xdr, name, len); 126 } 127 128 static bool 129 svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 130 struct iattr *iap) 131 { 132 u32 set_it; 133 134 iap->ia_valid = 0; 135 136 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 137 return false; 138 if (set_it) { 139 u32 mode; 140 141 if (xdr_stream_decode_u32(xdr, &mode) < 0) 142 return false; 143 iap->ia_valid |= ATTR_MODE; 144 iap->ia_mode = mode; 145 } 146 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 147 return false; 148 if (set_it) { 149 u32 uid; 150 151 if (xdr_stream_decode_u32(xdr, &uid) < 0) 152 return false; 153 iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid); 154 if (uid_valid(iap->ia_uid)) 155 iap->ia_valid |= ATTR_UID; 156 } 157 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 158 return false; 159 if (set_it) { 160 u32 gid; 161 162 if (xdr_stream_decode_u32(xdr, &gid) < 0) 163 return false; 164 iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid); 165 if (gid_valid(iap->ia_gid)) 166 iap->ia_valid |= ATTR_GID; 167 } 168 if (xdr_stream_decode_bool(xdr, &set_it) < 0) 169 return false; 170 if (set_it) { 171 u64 newsize; 172 173 if (xdr_stream_decode_u64(xdr, &newsize) < 0) 174 return false; 175 iap->ia_valid |= ATTR_SIZE; 176 iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX); 177 } 178 if (xdr_stream_decode_u32(xdr, &set_it) < 0) 179 return false; 180 switch (set_it) { 181 case DONT_CHANGE: 182 break; 183 case SET_TO_SERVER_TIME: 184 iap->ia_valid |= ATTR_ATIME; 185 break; 186 case SET_TO_CLIENT_TIME: 187 if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime)) 188 return false; 189 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 190 break; 191 default: 192 return false; 193 } 194 if (xdr_stream_decode_u32(xdr, &set_it) < 0) 195 return false; 196 switch (set_it) { 197 case DONT_CHANGE: 198 break; 199 case SET_TO_SERVER_TIME: 200 iap->ia_valid |= ATTR_MTIME; 201 break; 202 case SET_TO_CLIENT_TIME: 203 if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime)) 204 return false; 205 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 206 break; 207 default: 208 return false; 209 } 210 211 return true; 212 } 213 214 static bool 215 svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args) 216 { 217 __be32 *p; 218 u32 check; 219 220 if (xdr_stream_decode_bool(xdr, &check) < 0) 221 return false; 222 if (check) { 223 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 224 if (!p) 225 return false; 226 args->check_guard = 1; 227 args->guardtime = be32_to_cpup(p); 228 } else 229 args->check_guard = 0; 230 231 return true; 232 } 233 234 static bool 235 svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args) 236 { 237 __be32 *p; 238 239 p = xdr_inline_decode(xdr, XDR_UNIT * 2); 240 if (!p) 241 return false; 242 args->major = be32_to_cpup(p++); 243 args->minor = be32_to_cpup(p); 244 245 return true; 246 } 247 248 static bool 249 svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr, 250 struct nfsd3_mknodargs *args) 251 { 252 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 253 svcxdr_decode_specdata3(xdr, args); 254 } 255 256 static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp) 257 { 258 u64 f; 259 switch(fsid_source(fhp)) { 260 default: 261 case FSIDSOURCE_DEV: 262 p = xdr_encode_hyper(p, (u64)huge_encode_dev 263 (fhp->fh_dentry->d_sb->s_dev)); 264 break; 265 case FSIDSOURCE_FSID: 266 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); 267 break; 268 case FSIDSOURCE_UUID: 269 f = ((u64*)fhp->fh_export->ex_uuid)[0]; 270 f ^= ((u64*)fhp->fh_export->ex_uuid)[1]; 271 p = xdr_encode_hyper(p, f); 272 break; 273 } 274 return p; 275 } 276 277 static __be32 * 278 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 279 struct kstat *stat) 280 { 281 struct user_namespace *userns = nfsd_user_namespace(rqstp); 282 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 283 *p++ = htonl((u32) (stat->mode & S_IALLUGO)); 284 *p++ = htonl((u32) stat->nlink); 285 *p++ = htonl((u32) from_kuid_munged(userns, stat->uid)); 286 *p++ = htonl((u32) from_kgid_munged(userns, stat->gid)); 287 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { 288 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); 289 } else { 290 p = xdr_encode_hyper(p, (u64) stat->size); 291 } 292 p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); 293 *p++ = htonl((u32) MAJOR(stat->rdev)); 294 *p++ = htonl((u32) MINOR(stat->rdev)); 295 p = encode_fsid(p, fhp); 296 p = xdr_encode_hyper(p, stat->ino); 297 p = encode_time3(p, &stat->atime); 298 p = encode_time3(p, &stat->mtime); 299 p = encode_time3(p, &stat->ctime); 300 301 return p; 302 } 303 304 static __be32 * 305 encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 306 { 307 /* Attributes to follow */ 308 *p++ = xdr_one; 309 return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr); 310 } 311 312 /* 313 * Encode post-operation attributes. 314 * The inode may be NULL if the call failed because of a stale file 315 * handle. In this case, no attributes are returned. 316 */ 317 static __be32 * 318 encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 319 { 320 struct dentry *dentry = fhp->fh_dentry; 321 if (!fhp->fh_no_wcc && dentry && d_really_is_positive(dentry)) { 322 __be32 err; 323 struct kstat stat; 324 325 err = fh_getattr(fhp, &stat); 326 if (!err) { 327 *p++ = xdr_one; /* attributes follow */ 328 lease_get_mtime(d_inode(dentry), &stat.mtime); 329 return encode_fattr3(rqstp, p, fhp, &stat); 330 } 331 } 332 *p++ = xdr_zero; 333 return p; 334 } 335 336 /* Helper for NFSv3 ACLs */ 337 __be32 * 338 nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 339 { 340 return encode_post_op_attr(rqstp, p, fhp); 341 } 342 343 /* 344 * Enocde weak cache consistency data 345 */ 346 static __be32 * 347 encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 348 { 349 struct dentry *dentry = fhp->fh_dentry; 350 351 if (dentry && d_really_is_positive(dentry) && fhp->fh_post_saved) { 352 if (fhp->fh_pre_saved) { 353 *p++ = xdr_one; 354 p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size); 355 p = encode_time3(p, &fhp->fh_pre_mtime); 356 p = encode_time3(p, &fhp->fh_pre_ctime); 357 } else { 358 *p++ = xdr_zero; 359 } 360 return encode_saved_post_attr(rqstp, p, fhp); 361 } 362 /* no pre- or post-attrs */ 363 *p++ = xdr_zero; 364 return encode_post_op_attr(rqstp, p, fhp); 365 } 366 367 static bool fs_supports_change_attribute(struct super_block *sb) 368 { 369 return sb->s_flags & SB_I_VERSION || sb->s_export_op->fetch_iversion; 370 } 371 372 /* 373 * Fill in the pre_op attr for the wcc data 374 */ 375 void fill_pre_wcc(struct svc_fh *fhp) 376 { 377 struct inode *inode; 378 struct kstat stat; 379 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); 380 381 if (fhp->fh_no_wcc || fhp->fh_pre_saved) 382 return; 383 inode = d_inode(fhp->fh_dentry); 384 if (fs_supports_change_attribute(inode->i_sb) || !v4) { 385 __be32 err = fh_getattr(fhp, &stat); 386 387 if (err) { 388 /* Grab the times from inode anyway */ 389 stat.mtime = inode->i_mtime; 390 stat.ctime = inode->i_ctime; 391 stat.size = inode->i_size; 392 } 393 fhp->fh_pre_mtime = stat.mtime; 394 fhp->fh_pre_ctime = stat.ctime; 395 fhp->fh_pre_size = stat.size; 396 } 397 if (v4) 398 fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); 399 400 fhp->fh_pre_saved = true; 401 } 402 403 /* 404 * Fill in the post_op attr for the wcc data 405 */ 406 void fill_post_wcc(struct svc_fh *fhp) 407 { 408 bool v4 = (fhp->fh_maxsize == NFS4_FHSIZE); 409 struct inode *inode = d_inode(fhp->fh_dentry); 410 411 if (fhp->fh_no_wcc) 412 return; 413 414 if (fhp->fh_post_saved) 415 printk("nfsd: inode locked twice during operation.\n"); 416 417 fhp->fh_post_saved = true; 418 419 if (fs_supports_change_attribute(inode->i_sb) || !v4) { 420 __be32 err = fh_getattr(fhp, &fhp->fh_post_attr); 421 422 if (err) { 423 fhp->fh_post_saved = false; 424 fhp->fh_post_attr.ctime = inode->i_ctime; 425 } 426 } 427 if (v4) 428 fhp->fh_post_change = 429 nfsd4_change_attribute(&fhp->fh_post_attr, inode); 430 } 431 432 /* 433 * XDR decode functions 434 */ 435 436 int 437 nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p) 438 { 439 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 440 struct nfsd_fhandle *args = rqstp->rq_argp; 441 442 return svcxdr_decode_nfs_fh3(xdr, &args->fh); 443 } 444 445 int 446 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p) 447 { 448 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 449 struct nfsd3_sattrargs *args = rqstp->rq_argp; 450 451 return svcxdr_decode_nfs_fh3(xdr, &args->fh) && 452 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) && 453 svcxdr_decode_sattrguard3(xdr, args); 454 } 455 456 int 457 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p) 458 { 459 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 460 struct nfsd3_diropargs *args = rqstp->rq_argp; 461 462 return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len); 463 } 464 465 int 466 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p) 467 { 468 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 469 struct nfsd3_accessargs *args = rqstp->rq_argp; 470 471 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 472 return 0; 473 if (xdr_stream_decode_u32(xdr, &args->access) < 0) 474 return 0; 475 476 return 1; 477 } 478 479 int 480 nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p) 481 { 482 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 483 struct nfsd3_readargs *args = rqstp->rq_argp; 484 485 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 486 return 0; 487 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 488 return 0; 489 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 490 return 0; 491 492 return 1; 493 } 494 495 int 496 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) 497 { 498 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 499 struct nfsd3_writeargs *args = rqstp->rq_argp; 500 u32 max_blocksize = svc_max_payload(rqstp); 501 struct kvec *head = rqstp->rq_arg.head; 502 struct kvec *tail = rqstp->rq_arg.tail; 503 size_t remaining; 504 505 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 506 return 0; 507 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 508 return 0; 509 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 510 return 0; 511 if (xdr_stream_decode_u32(xdr, &args->stable) < 0) 512 return 0; 513 514 /* opaque data */ 515 if (xdr_stream_decode_u32(xdr, &args->len) < 0) 516 return 0; 517 518 /* request sanity */ 519 if (args->count != args->len) 520 return 0; 521 remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; 522 remaining -= xdr_stream_pos(xdr); 523 if (remaining < xdr_align_size(args->len)) 524 return 0; 525 if (args->count > max_blocksize) { 526 args->count = max_blocksize; 527 args->len = max_blocksize; 528 } 529 530 args->first.iov_base = xdr->p; 531 args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); 532 533 return 1; 534 } 535 536 int 537 nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p) 538 { 539 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 540 struct nfsd3_createargs *args = rqstp->rq_argp; 541 542 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 543 return 0; 544 if (xdr_stream_decode_u32(xdr, &args->createmode) < 0) 545 return 0; 546 switch (args->createmode) { 547 case NFS3_CREATE_UNCHECKED: 548 case NFS3_CREATE_GUARDED: 549 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 550 case NFS3_CREATE_EXCLUSIVE: 551 args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE); 552 if (!args->verf) 553 return 0; 554 break; 555 default: 556 return 0; 557 } 558 return 1; 559 } 560 561 int 562 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p) 563 { 564 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 565 struct nfsd3_createargs *args = rqstp->rq_argp; 566 567 return svcxdr_decode_diropargs3(xdr, &args->fh, 568 &args->name, &args->len) && 569 svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 570 } 571 572 int 573 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p) 574 { 575 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 576 struct nfsd3_symlinkargs *args = rqstp->rq_argp; 577 struct kvec *head = rqstp->rq_arg.head; 578 struct kvec *tail = rqstp->rq_arg.tail; 579 size_t remaining; 580 581 if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen)) 582 return 0; 583 if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs)) 584 return 0; 585 if (xdr_stream_decode_u32(xdr, &args->tlen) < 0) 586 return 0; 587 588 /* request sanity */ 589 remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; 590 remaining -= xdr_stream_pos(xdr); 591 if (remaining < xdr_align_size(args->tlen)) 592 return 0; 593 594 args->first.iov_base = xdr->p; 595 args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); 596 597 return 1; 598 } 599 600 int 601 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p) 602 { 603 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 604 struct nfsd3_mknodargs *args = rqstp->rq_argp; 605 606 if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len)) 607 return 0; 608 if (xdr_stream_decode_u32(xdr, &args->ftype) < 0) 609 return 0; 610 switch (args->ftype) { 611 case NF3CHR: 612 case NF3BLK: 613 return svcxdr_decode_devicedata3(rqstp, xdr, args); 614 case NF3SOCK: 615 case NF3FIFO: 616 return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs); 617 case NF3REG: 618 case NF3DIR: 619 case NF3LNK: 620 /* Valid XDR but illegal file types */ 621 break; 622 default: 623 return 0; 624 } 625 626 return 1; 627 } 628 629 int 630 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p) 631 { 632 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 633 struct nfsd3_renameargs *args = rqstp->rq_argp; 634 635 return svcxdr_decode_diropargs3(xdr, &args->ffh, 636 &args->fname, &args->flen) && 637 svcxdr_decode_diropargs3(xdr, &args->tfh, 638 &args->tname, &args->tlen); 639 } 640 641 int 642 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p) 643 { 644 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 645 struct nfsd3_linkargs *args = rqstp->rq_argp; 646 647 return svcxdr_decode_nfs_fh3(xdr, &args->ffh) && 648 svcxdr_decode_diropargs3(xdr, &args->tfh, 649 &args->tname, &args->tlen); 650 } 651 652 int 653 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) 654 { 655 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 656 struct nfsd3_readdirargs *args = rqstp->rq_argp; 657 658 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 659 return 0; 660 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 661 return 0; 662 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 663 if (!args->verf) 664 return 0; 665 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 666 return 0; 667 668 return 1; 669 } 670 671 int 672 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p) 673 { 674 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 675 struct nfsd3_readdirargs *args = rqstp->rq_argp; 676 u32 dircount; 677 678 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 679 return 0; 680 if (xdr_stream_decode_u64(xdr, &args->cookie) < 0) 681 return 0; 682 args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE); 683 if (!args->verf) 684 return 0; 685 /* dircount is ignored */ 686 if (xdr_stream_decode_u32(xdr, &dircount) < 0) 687 return 0; 688 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 689 return 0; 690 691 return 1; 692 } 693 694 int 695 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p) 696 { 697 struct xdr_stream *xdr = &rqstp->rq_arg_stream; 698 struct nfsd3_commitargs *args = rqstp->rq_argp; 699 700 if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) 701 return 0; 702 if (xdr_stream_decode_u64(xdr, &args->offset) < 0) 703 return 0; 704 if (xdr_stream_decode_u32(xdr, &args->count) < 0) 705 return 0; 706 707 return 1; 708 } 709 710 /* 711 * XDR encode functions 712 */ 713 714 /* GETATTR */ 715 int 716 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) 717 { 718 struct nfsd3_attrstat *resp = rqstp->rq_resp; 719 720 *p++ = resp->status; 721 if (resp->status == 0) { 722 lease_get_mtime(d_inode(resp->fh.fh_dentry), 723 &resp->stat.mtime); 724 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); 725 } 726 return xdr_ressize_check(rqstp, p); 727 } 728 729 /* SETATTR, REMOVE, RMDIR */ 730 int 731 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p) 732 { 733 struct nfsd3_attrstat *resp = rqstp->rq_resp; 734 735 *p++ = resp->status; 736 p = encode_wcc_data(rqstp, p, &resp->fh); 737 return xdr_ressize_check(rqstp, p); 738 } 739 740 /* LOOKUP */ 741 int 742 nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) 743 { 744 struct nfsd3_diropres *resp = rqstp->rq_resp; 745 746 *p++ = resp->status; 747 if (resp->status == 0) { 748 p = encode_fh(p, &resp->fh); 749 p = encode_post_op_attr(rqstp, p, &resp->fh); 750 } 751 p = encode_post_op_attr(rqstp, p, &resp->dirfh); 752 return xdr_ressize_check(rqstp, p); 753 } 754 755 /* ACCESS */ 756 int 757 nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p) 758 { 759 struct nfsd3_accessres *resp = rqstp->rq_resp; 760 761 *p++ = resp->status; 762 p = encode_post_op_attr(rqstp, p, &resp->fh); 763 if (resp->status == 0) 764 *p++ = htonl(resp->access); 765 return xdr_ressize_check(rqstp, p); 766 } 767 768 /* READLINK */ 769 int 770 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) 771 { 772 struct nfsd3_readlinkres *resp = rqstp->rq_resp; 773 struct kvec *head = rqstp->rq_res.head; 774 775 *p++ = resp->status; 776 p = encode_post_op_attr(rqstp, p, &resp->fh); 777 if (resp->status == 0) { 778 *p++ = htonl(resp->len); 779 xdr_ressize_check(rqstp, p); 780 rqstp->rq_res.page_len = resp->len; 781 if (resp->len & 3) { 782 /* need to pad the tail */ 783 rqstp->rq_res.tail[0].iov_base = p; 784 *p = 0; 785 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); 786 } 787 if (svc_encode_result_payload(rqstp, head->iov_len, resp->len)) 788 return 0; 789 return 1; 790 } else 791 return xdr_ressize_check(rqstp, p); 792 } 793 794 /* READ */ 795 int 796 nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p) 797 { 798 struct nfsd3_readres *resp = rqstp->rq_resp; 799 struct kvec *head = rqstp->rq_res.head; 800 801 *p++ = resp->status; 802 p = encode_post_op_attr(rqstp, p, &resp->fh); 803 if (resp->status == 0) { 804 *p++ = htonl(resp->count); 805 *p++ = htonl(resp->eof); 806 *p++ = htonl(resp->count); /* xdr opaque count */ 807 xdr_ressize_check(rqstp, p); 808 /* now update rqstp->rq_res to reflect data as well */ 809 rqstp->rq_res.page_len = resp->count; 810 if (resp->count & 3) { 811 /* need to pad the tail */ 812 rqstp->rq_res.tail[0].iov_base = p; 813 *p = 0; 814 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); 815 } 816 if (svc_encode_result_payload(rqstp, head->iov_len, 817 resp->count)) 818 return 0; 819 return 1; 820 } else 821 return xdr_ressize_check(rqstp, p); 822 } 823 824 /* WRITE */ 825 int 826 nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) 827 { 828 struct nfsd3_writeres *resp = rqstp->rq_resp; 829 830 *p++ = resp->status; 831 p = encode_wcc_data(rqstp, p, &resp->fh); 832 if (resp->status == 0) { 833 *p++ = htonl(resp->count); 834 *p++ = htonl(resp->committed); 835 *p++ = resp->verf[0]; 836 *p++ = resp->verf[1]; 837 } 838 return xdr_ressize_check(rqstp, p); 839 } 840 841 /* CREATE, MKDIR, SYMLINK, MKNOD */ 842 int 843 nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p) 844 { 845 struct nfsd3_diropres *resp = rqstp->rq_resp; 846 847 *p++ = resp->status; 848 if (resp->status == 0) { 849 *p++ = xdr_one; 850 p = encode_fh(p, &resp->fh); 851 p = encode_post_op_attr(rqstp, p, &resp->fh); 852 } 853 p = encode_wcc_data(rqstp, p, &resp->dirfh); 854 return xdr_ressize_check(rqstp, p); 855 } 856 857 /* RENAME */ 858 int 859 nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p) 860 { 861 struct nfsd3_renameres *resp = rqstp->rq_resp; 862 863 *p++ = resp->status; 864 p = encode_wcc_data(rqstp, p, &resp->ffh); 865 p = encode_wcc_data(rqstp, p, &resp->tfh); 866 return xdr_ressize_check(rqstp, p); 867 } 868 869 /* LINK */ 870 int 871 nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p) 872 { 873 struct nfsd3_linkres *resp = rqstp->rq_resp; 874 875 *p++ = resp->status; 876 p = encode_post_op_attr(rqstp, p, &resp->fh); 877 p = encode_wcc_data(rqstp, p, &resp->tfh); 878 return xdr_ressize_check(rqstp, p); 879 } 880 881 /* READDIR */ 882 int 883 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) 884 { 885 struct nfsd3_readdirres *resp = rqstp->rq_resp; 886 887 *p++ = resp->status; 888 p = encode_post_op_attr(rqstp, p, &resp->fh); 889 890 if (resp->status == 0) { 891 /* stupid readdir cookie */ 892 memcpy(p, resp->verf, 8); p += 2; 893 xdr_ressize_check(rqstp, p); 894 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE) 895 return 1; /*No room for trailer */ 896 rqstp->rq_res.page_len = (resp->count) << 2; 897 898 /* add the 'tail' to the end of the 'head' page - page 0. */ 899 rqstp->rq_res.tail[0].iov_base = p; 900 *p++ = 0; /* no more entries */ 901 *p++ = htonl(resp->common.err == nfserr_eof); 902 rqstp->rq_res.tail[0].iov_len = 2<<2; 903 return 1; 904 } else 905 return xdr_ressize_check(rqstp, p); 906 } 907 908 static __be32 * 909 encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 910 int namlen, u64 ino) 911 { 912 *p++ = xdr_one; /* mark entry present */ 913 p = xdr_encode_hyper(p, ino); /* file id */ 914 p = xdr_encode_array(p, name, namlen);/* name length & name */ 915 916 cd->offset = p; /* remember pointer */ 917 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */ 918 919 return p; 920 } 921 922 static __be32 923 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 924 const char *name, int namlen, u64 ino) 925 { 926 struct svc_export *exp; 927 struct dentry *dparent, *dchild; 928 __be32 rv = nfserr_noent; 929 930 dparent = cd->fh.fh_dentry; 931 exp = cd->fh.fh_export; 932 933 if (isdotent(name, namlen)) { 934 if (namlen == 2) { 935 dchild = dget_parent(dparent); 936 /* 937 * Don't return filehandle for ".." if we're at 938 * the filesystem or export root: 939 */ 940 if (dchild == dparent) 941 goto out; 942 if (dparent == exp->ex_path.dentry) 943 goto out; 944 } else 945 dchild = dget(dparent); 946 } else 947 dchild = lookup_positive_unlocked(name, dparent, namlen); 948 if (IS_ERR(dchild)) 949 return rv; 950 if (d_mountpoint(dchild)) 951 goto out; 952 if (dchild->d_inode->i_ino != ino) 953 goto out; 954 rv = fh_compose(fhp, exp, dchild, &cd->fh); 955 out: 956 dput(dchild); 957 return rv; 958 } 959 960 static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, u64 ino) 961 { 962 struct svc_fh *fh = &cd->scratch; 963 __be32 err; 964 965 fh_init(fh, NFS3_FHSIZE); 966 err = compose_entry_fh(cd, fh, name, namlen, ino); 967 if (err) { 968 *p++ = 0; 969 *p++ = 0; 970 goto out; 971 } 972 p = encode_post_op_attr(cd->rqstp, p, fh); 973 *p++ = xdr_one; /* yes, a file handle follows */ 974 p = encode_fh(p, fh); 975 out: 976 fh_put(fh); 977 return p; 978 } 979 980 /* 981 * Encode a directory entry. This one works for both normal readdir 982 * and readdirplus. 983 * The normal readdir reply requires 2 (fileid) + 1 (stringlen) 984 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen. 985 * 986 * The readdirplus baggage is 1+21 words for post_op_attr, plus the 987 * file handle. 988 */ 989 990 #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1) 991 #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) 992 static int 993 encode_entry(struct readdir_cd *ccd, const char *name, int namlen, 994 loff_t offset, u64 ino, unsigned int d_type, int plus) 995 { 996 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, 997 common); 998 __be32 *p = cd->buffer; 999 caddr_t curr_page_addr = NULL; 1000 struct page ** page; 1001 int slen; /* string (name) length */ 1002 int elen; /* estimated entry length in words */ 1003 int num_entry_words = 0; /* actual number of words */ 1004 1005 if (cd->offset) { 1006 u64 offset64 = offset; 1007 1008 if (unlikely(cd->offset1)) { 1009 /* we ended up with offset on a page boundary */ 1010 *cd->offset = htonl(offset64 >> 32); 1011 *cd->offset1 = htonl(offset64 & 0xffffffff); 1012 cd->offset1 = NULL; 1013 } else { 1014 xdr_encode_hyper(cd->offset, offset64); 1015 } 1016 cd->offset = NULL; 1017 } 1018 1019 /* 1020 dprintk("encode_entry(%.*s @%ld%s)\n", 1021 namlen, name, (long) offset, plus? " plus" : ""); 1022 */ 1023 1024 /* truncate filename if too long */ 1025 namlen = min(namlen, NFS3_MAXNAMLEN); 1026 1027 slen = XDR_QUADLEN(namlen); 1028 elen = slen + NFS3_ENTRY_BAGGAGE 1029 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0); 1030 1031 if (cd->buflen < elen) { 1032 cd->common.err = nfserr_toosmall; 1033 return -EINVAL; 1034 } 1035 1036 /* determine which page in rq_respages[] we are currently filling */ 1037 for (page = cd->rqstp->rq_respages + 1; 1038 page < cd->rqstp->rq_next_page; page++) { 1039 curr_page_addr = page_address(*page); 1040 1041 if (((caddr_t)cd->buffer >= curr_page_addr) && 1042 ((caddr_t)cd->buffer < curr_page_addr + PAGE_SIZE)) 1043 break; 1044 } 1045 1046 if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) { 1047 /* encode entry in current page */ 1048 1049 p = encode_entry_baggage(cd, p, name, namlen, ino); 1050 1051 if (plus) 1052 p = encode_entryplus_baggage(cd, p, name, namlen, ino); 1053 num_entry_words = p - cd->buffer; 1054 } else if (*(page+1) != NULL) { 1055 /* temporarily encode entry into next page, then move back to 1056 * current and next page in rq_respages[] */ 1057 __be32 *p1, *tmp; 1058 int len1, len2; 1059 1060 /* grab next page for temporary storage of entry */ 1061 p1 = tmp = page_address(*(page+1)); 1062 1063 p1 = encode_entry_baggage(cd, p1, name, namlen, ino); 1064 1065 if (plus) 1066 p1 = encode_entryplus_baggage(cd, p1, name, namlen, ino); 1067 1068 /* determine entry word length and lengths to go in pages */ 1069 num_entry_words = p1 - tmp; 1070 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer; 1071 if ((num_entry_words << 2) < len1) { 1072 /* the actual number of words in the entry is less 1073 * than elen and can still fit in the current page 1074 */ 1075 memmove(p, tmp, num_entry_words << 2); 1076 p += num_entry_words; 1077 1078 /* update offset */ 1079 cd->offset = cd->buffer + (cd->offset - tmp); 1080 } else { 1081 unsigned int offset_r = (cd->offset - tmp) << 2; 1082 1083 /* update pointer to offset location. 1084 * This is a 64bit quantity, so we need to 1085 * deal with 3 cases: 1086 * - entirely in first page 1087 * - entirely in second page 1088 * - 4 bytes in each page 1089 */ 1090 if (offset_r + 8 <= len1) { 1091 cd->offset = p + (cd->offset - tmp); 1092 } else if (offset_r >= len1) { 1093 cd->offset -= len1 >> 2; 1094 } else { 1095 /* sitting on the fence */ 1096 BUG_ON(offset_r != len1 - 4); 1097 cd->offset = p + (cd->offset - tmp); 1098 cd->offset1 = tmp; 1099 } 1100 1101 len2 = (num_entry_words << 2) - len1; 1102 1103 /* move from temp page to current and next pages */ 1104 memmove(p, tmp, len1); 1105 memmove(tmp, (caddr_t)tmp+len1, len2); 1106 1107 p = tmp + (len2 >> 2); 1108 } 1109 } 1110 else { 1111 cd->common.err = nfserr_toosmall; 1112 return -EINVAL; 1113 } 1114 1115 cd->buflen -= num_entry_words; 1116 cd->buffer = p; 1117 cd->common.err = nfs_ok; 1118 return 0; 1119 1120 } 1121 1122 int 1123 nfs3svc_encode_entry(void *cd, const char *name, 1124 int namlen, loff_t offset, u64 ino, unsigned int d_type) 1125 { 1126 return encode_entry(cd, name, namlen, offset, ino, d_type, 0); 1127 } 1128 1129 int 1130 nfs3svc_encode_entry_plus(void *cd, const char *name, 1131 int namlen, loff_t offset, u64 ino, 1132 unsigned int d_type) 1133 { 1134 return encode_entry(cd, name, namlen, offset, ino, d_type, 1); 1135 } 1136 1137 /* FSSTAT */ 1138 int 1139 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p) 1140 { 1141 struct nfsd3_fsstatres *resp = rqstp->rq_resp; 1142 struct kstatfs *s = &resp->stats; 1143 u64 bs = s->f_bsize; 1144 1145 *p++ = resp->status; 1146 *p++ = xdr_zero; /* no post_op_attr */ 1147 1148 if (resp->status == 0) { 1149 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1150 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1151 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1152 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1153 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1154 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1155 *p++ = htonl(resp->invarsec); /* mean unchanged time */ 1156 } 1157 return xdr_ressize_check(rqstp, p); 1158 } 1159 1160 /* FSINFO */ 1161 int 1162 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p) 1163 { 1164 struct nfsd3_fsinfores *resp = rqstp->rq_resp; 1165 1166 *p++ = resp->status; 1167 *p++ = xdr_zero; /* no post_op_attr */ 1168 1169 if (resp->status == 0) { 1170 *p++ = htonl(resp->f_rtmax); 1171 *p++ = htonl(resp->f_rtpref); 1172 *p++ = htonl(resp->f_rtmult); 1173 *p++ = htonl(resp->f_wtmax); 1174 *p++ = htonl(resp->f_wtpref); 1175 *p++ = htonl(resp->f_wtmult); 1176 *p++ = htonl(resp->f_dtpref); 1177 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1178 *p++ = xdr_one; 1179 *p++ = xdr_zero; 1180 *p++ = htonl(resp->f_properties); 1181 } 1182 1183 return xdr_ressize_check(rqstp, p); 1184 } 1185 1186 /* PATHCONF */ 1187 int 1188 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p) 1189 { 1190 struct nfsd3_pathconfres *resp = rqstp->rq_resp; 1191 1192 *p++ = resp->status; 1193 *p++ = xdr_zero; /* no post_op_attr */ 1194 1195 if (resp->status == 0) { 1196 *p++ = htonl(resp->p_link_max); 1197 *p++ = htonl(resp->p_name_max); 1198 *p++ = htonl(resp->p_no_trunc); 1199 *p++ = htonl(resp->p_chown_restricted); 1200 *p++ = htonl(resp->p_case_insensitive); 1201 *p++ = htonl(resp->p_case_preserving); 1202 } 1203 1204 return xdr_ressize_check(rqstp, p); 1205 } 1206 1207 /* COMMIT */ 1208 int 1209 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) 1210 { 1211 struct nfsd3_commitres *resp = rqstp->rq_resp; 1212 1213 *p++ = resp->status; 1214 p = encode_wcc_data(rqstp, p, &resp->fh); 1215 /* Write verifier */ 1216 if (resp->status == 0) { 1217 *p++ = resp->verf[0]; 1218 *p++ = resp->verf[1]; 1219 } 1220 return xdr_ressize_check(rqstp, p); 1221 } 1222 1223 /* 1224 * XDR release functions 1225 */ 1226 void 1227 nfs3svc_release_fhandle(struct svc_rqst *rqstp) 1228 { 1229 struct nfsd3_attrstat *resp = rqstp->rq_resp; 1230 1231 fh_put(&resp->fh); 1232 } 1233 1234 void 1235 nfs3svc_release_fhandle2(struct svc_rqst *rqstp) 1236 { 1237 struct nfsd3_fhandle_pair *resp = rqstp->rq_resp; 1238 1239 fh_put(&resp->fh1); 1240 fh_put(&resp->fh2); 1241 } 1242