| .. | .. |
|---|
| 27 | 27 | NF3SOCK, NF3BAD, NF3LNK, NF3BAD, |
|---|
| 28 | 28 | }; |
|---|
| 29 | 29 | |
|---|
| 30 | + |
|---|
| 30 | 31 | /* |
|---|
| 31 | 32 | * XDR functions for basic NFS types |
|---|
| 32 | 33 | */ |
|---|
| 33 | 34 | static __be32 * |
|---|
| 34 | | -encode_time3(__be32 *p, struct timespec *time) |
|---|
| 35 | +encode_time3(__be32 *p, struct timespec64 *time) |
|---|
| 35 | 36 | { |
|---|
| 36 | 37 | *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); |
|---|
| 37 | 38 | return p; |
|---|
| 38 | 39 | } |
|---|
| 39 | 40 | |
|---|
| 40 | 41 | static __be32 * |
|---|
| 41 | | -decode_time3(__be32 *p, struct timespec *time) |
|---|
| 42 | +decode_time3(__be32 *p, struct timespec64 *time) |
|---|
| 42 | 43 | { |
|---|
| 43 | 44 | time->tv_sec = ntohl(*p++); |
|---|
| 44 | 45 | time->tv_nsec = ntohl(*p++); |
|---|
| .. | .. |
|---|
| 96 | 97 | } |
|---|
| 97 | 98 | |
|---|
| 98 | 99 | static __be32 * |
|---|
| 99 | | -decode_sattr3(__be32 *p, struct iattr *iap) |
|---|
| 100 | +decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns) |
|---|
| 100 | 101 | { |
|---|
| 101 | 102 | u32 tmp; |
|---|
| 102 | 103 | |
|---|
| .. | .. |
|---|
| 107 | 108 | iap->ia_mode = ntohl(*p++); |
|---|
| 108 | 109 | } |
|---|
| 109 | 110 | if (*p++) { |
|---|
| 110 | | - iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++)); |
|---|
| 111 | + iap->ia_uid = make_kuid(userns, ntohl(*p++)); |
|---|
| 111 | 112 | if (uid_valid(iap->ia_uid)) |
|---|
| 112 | 113 | iap->ia_valid |= ATTR_UID; |
|---|
| 113 | 114 | } |
|---|
| 114 | 115 | if (*p++) { |
|---|
| 115 | | - iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++)); |
|---|
| 116 | + iap->ia_gid = make_kgid(userns, ntohl(*p++)); |
|---|
| 116 | 117 | if (gid_valid(iap->ia_gid)) |
|---|
| 117 | 118 | iap->ia_valid |= ATTR_GID; |
|---|
| 118 | 119 | } |
|---|
| .. | .. |
|---|
| 165 | 166 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, |
|---|
| 166 | 167 | struct kstat *stat) |
|---|
| 167 | 168 | { |
|---|
| 168 | | - struct timespec ts; |
|---|
| 169 | + struct user_namespace *userns = nfsd_user_namespace(rqstp); |
|---|
| 169 | 170 | *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); |
|---|
| 170 | 171 | *p++ = htonl((u32) (stat->mode & S_IALLUGO)); |
|---|
| 171 | 172 | *p++ = htonl((u32) stat->nlink); |
|---|
| 172 | | - *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); |
|---|
| 173 | | - *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); |
|---|
| 173 | + *p++ = htonl((u32) from_kuid_munged(userns, stat->uid)); |
|---|
| 174 | + *p++ = htonl((u32) from_kgid_munged(userns, stat->gid)); |
|---|
| 174 | 175 | if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { |
|---|
| 175 | 176 | p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); |
|---|
| 176 | 177 | } else { |
|---|
| .. | .. |
|---|
| 181 | 182 | *p++ = htonl((u32) MINOR(stat->rdev)); |
|---|
| 182 | 183 | p = encode_fsid(p, fhp); |
|---|
| 183 | 184 | p = xdr_encode_hyper(p, stat->ino); |
|---|
| 184 | | - ts = timespec64_to_timespec(stat->atime); |
|---|
| 185 | | - p = encode_time3(p, &ts); |
|---|
| 186 | | - ts = timespec64_to_timespec(stat->mtime); |
|---|
| 187 | | - p = encode_time3(p, &ts); |
|---|
| 188 | | - ts = timespec64_to_timespec(stat->ctime); |
|---|
| 189 | | - p = encode_time3(p, &ts); |
|---|
| 185 | + p = encode_time3(p, &stat->atime); |
|---|
| 186 | + p = encode_time3(p, &stat->mtime); |
|---|
| 187 | + p = encode_time3(p, &stat->ctime); |
|---|
| 190 | 188 | |
|---|
| 191 | 189 | return p; |
|---|
| 192 | 190 | } |
|---|
| .. | .. |
|---|
| 275 | 273 | stat.size = inode->i_size; |
|---|
| 276 | 274 | } |
|---|
| 277 | 275 | |
|---|
| 278 | | - fhp->fh_pre_mtime = timespec64_to_timespec(stat.mtime); |
|---|
| 279 | | - fhp->fh_pre_ctime = timespec64_to_timespec(stat.ctime); |
|---|
| 276 | + fhp->fh_pre_mtime = stat.mtime; |
|---|
| 277 | + fhp->fh_pre_ctime = stat.ctime; |
|---|
| 280 | 278 | fhp->fh_pre_size = stat.size; |
|---|
| 281 | 279 | fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); |
|---|
| 282 | 280 | fhp->fh_pre_saved = true; |
|---|
| .. | .. |
|---|
| 307 | 305 | * XDR decode functions |
|---|
| 308 | 306 | */ |
|---|
| 309 | 307 | int |
|---|
| 308 | +nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 309 | +{ |
|---|
| 310 | + return 1; |
|---|
| 311 | +} |
|---|
| 312 | + |
|---|
| 313 | +int |
|---|
| 310 | 314 | nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 311 | 315 | { |
|---|
| 312 | 316 | struct nfsd_fhandle *args = rqstp->rq_argp; |
|---|
| .. | .. |
|---|
| 325 | 329 | p = decode_fh(p, &args->fh); |
|---|
| 326 | 330 | if (!p) |
|---|
| 327 | 331 | return 0; |
|---|
| 328 | | - p = decode_sattr3(p, &args->attrs); |
|---|
| 332 | + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); |
|---|
| 329 | 333 | |
|---|
| 330 | 334 | if ((args->check_guard = ntohl(*p++)) != 0) { |
|---|
| 331 | | - struct timespec time; |
|---|
| 335 | + struct timespec64 time; |
|---|
| 332 | 336 | p = decode_time3(p, &time); |
|---|
| 333 | 337 | args->guardtime = time.tv_sec; |
|---|
| 334 | 338 | } |
|---|
| .. | .. |
|---|
| 455 | 459 | switch (args->createmode = ntohl(*p++)) { |
|---|
| 456 | 460 | case NFS3_CREATE_UNCHECKED: |
|---|
| 457 | 461 | case NFS3_CREATE_GUARDED: |
|---|
| 458 | | - p = decode_sattr3(p, &args->attrs); |
|---|
| 462 | + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); |
|---|
| 459 | 463 | break; |
|---|
| 460 | 464 | case NFS3_CREATE_EXCLUSIVE: |
|---|
| 461 | 465 | args->verf = p; |
|---|
| .. | .. |
|---|
| 476 | 480 | if (!(p = decode_fh(p, &args->fh)) || |
|---|
| 477 | 481 | !(p = decode_filename(p, &args->name, &args->len))) |
|---|
| 478 | 482 | return 0; |
|---|
| 479 | | - p = decode_sattr3(p, &args->attrs); |
|---|
| 483 | + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); |
|---|
| 480 | 484 | |
|---|
| 481 | 485 | return xdr_argsize_check(rqstp, p); |
|---|
| 482 | 486 | } |
|---|
| .. | .. |
|---|
| 491 | 495 | if (!(p = decode_fh(p, &args->ffh)) || |
|---|
| 492 | 496 | !(p = decode_filename(p, &args->fname, &args->flen))) |
|---|
| 493 | 497 | return 0; |
|---|
| 494 | | - p = decode_sattr3(p, &args->attrs); |
|---|
| 498 | + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); |
|---|
| 495 | 499 | |
|---|
| 496 | 500 | args->tlen = ntohl(*p++); |
|---|
| 497 | 501 | |
|---|
| .. | .. |
|---|
| 519 | 523 | |
|---|
| 520 | 524 | if (args->ftype == NF3BLK || args->ftype == NF3CHR |
|---|
| 521 | 525 | || args->ftype == NF3SOCK || args->ftype == NF3FIFO) |
|---|
| 522 | | - p = decode_sattr3(p, &args->attrs); |
|---|
| 526 | + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); |
|---|
| 523 | 527 | |
|---|
| 524 | 528 | if (args->ftype == NF3BLK || args->ftype == NF3CHR) { |
|---|
| 525 | 529 | args->major = ntohl(*p++); |
|---|
| .. | .. |
|---|
| 573 | 577 | nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 574 | 578 | { |
|---|
| 575 | 579 | struct nfsd3_readdirargs *args = rqstp->rq_argp; |
|---|
| 580 | + int len; |
|---|
| 581 | + u32 max_blocksize = svc_max_payload(rqstp); |
|---|
| 582 | + |
|---|
| 576 | 583 | p = decode_fh(p, &args->fh); |
|---|
| 577 | 584 | if (!p) |
|---|
| 578 | 585 | return 0; |
|---|
| .. | .. |
|---|
| 580 | 587 | args->verf = p; p += 2; |
|---|
| 581 | 588 | args->dircount = ~0; |
|---|
| 582 | 589 | args->count = ntohl(*p++); |
|---|
| 583 | | - args->count = min_t(u32, args->count, PAGE_SIZE); |
|---|
| 584 | | - args->buffer = page_address(*(rqstp->rq_next_page++)); |
|---|
| 590 | + len = args->count = min_t(u32, args->count, max_blocksize); |
|---|
| 591 | + |
|---|
| 592 | + while (len > 0) { |
|---|
| 593 | + struct page *p = *(rqstp->rq_next_page++); |
|---|
| 594 | + if (!args->buffer) |
|---|
| 595 | + args->buffer = page_address(p); |
|---|
| 596 | + len -= PAGE_SIZE; |
|---|
| 597 | + } |
|---|
| 585 | 598 | |
|---|
| 586 | 599 | return xdr_argsize_check(rqstp, p); |
|---|
| 587 | 600 | } |
|---|
| .. | .. |
|---|
| 628 | 641 | /* |
|---|
| 629 | 642 | * XDR encode functions |
|---|
| 630 | 643 | */ |
|---|
| 631 | | -/* |
|---|
| 632 | | - * There must be an encoding function for void results so svc_process |
|---|
| 633 | | - * will work properly. |
|---|
| 634 | | - */ |
|---|
| 644 | + |
|---|
| 635 | 645 | int |
|---|
| 636 | 646 | nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 637 | 647 | { |
|---|
| .. | .. |
|---|
| 644 | 654 | { |
|---|
| 645 | 655 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
|---|
| 646 | 656 | |
|---|
| 657 | + *p++ = resp->status; |
|---|
| 647 | 658 | if (resp->status == 0) { |
|---|
| 648 | 659 | lease_get_mtime(d_inode(resp->fh.fh_dentry), |
|---|
| 649 | 660 | &resp->stat.mtime); |
|---|
| .. | .. |
|---|
| 658 | 669 | { |
|---|
| 659 | 670 | struct nfsd3_attrstat *resp = rqstp->rq_resp; |
|---|
| 660 | 671 | |
|---|
| 672 | + *p++ = resp->status; |
|---|
| 661 | 673 | p = encode_wcc_data(rqstp, p, &resp->fh); |
|---|
| 662 | 674 | return xdr_ressize_check(rqstp, p); |
|---|
| 663 | 675 | } |
|---|
| .. | .. |
|---|
| 668 | 680 | { |
|---|
| 669 | 681 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
|---|
| 670 | 682 | |
|---|
| 683 | + *p++ = resp->status; |
|---|
| 671 | 684 | if (resp->status == 0) { |
|---|
| 672 | 685 | p = encode_fh(p, &resp->fh); |
|---|
| 673 | 686 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| .. | .. |
|---|
| 682 | 695 | { |
|---|
| 683 | 696 | struct nfsd3_accessres *resp = rqstp->rq_resp; |
|---|
| 684 | 697 | |
|---|
| 698 | + *p++ = resp->status; |
|---|
| 685 | 699 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| 686 | 700 | if (resp->status == 0) |
|---|
| 687 | 701 | *p++ = htonl(resp->access); |
|---|
| .. | .. |
|---|
| 694 | 708 | { |
|---|
| 695 | 709 | struct nfsd3_readlinkres *resp = rqstp->rq_resp; |
|---|
| 696 | 710 | |
|---|
| 711 | + *p++ = resp->status; |
|---|
| 697 | 712 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| 698 | 713 | if (resp->status == 0) { |
|---|
| 699 | 714 | *p++ = htonl(resp->len); |
|---|
| .. | .. |
|---|
| 716 | 731 | { |
|---|
| 717 | 732 | struct nfsd3_readres *resp = rqstp->rq_resp; |
|---|
| 718 | 733 | |
|---|
| 734 | + *p++ = resp->status; |
|---|
| 719 | 735 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| 720 | 736 | if (resp->status == 0) { |
|---|
| 721 | 737 | *p++ = htonl(resp->count); |
|---|
| .. | .. |
|---|
| 740 | 756 | nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 741 | 757 | { |
|---|
| 742 | 758 | struct nfsd3_writeres *resp = rqstp->rq_resp; |
|---|
| 743 | | - struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
|---|
| 744 | 759 | |
|---|
| 760 | + *p++ = resp->status; |
|---|
| 745 | 761 | p = encode_wcc_data(rqstp, p, &resp->fh); |
|---|
| 746 | 762 | if (resp->status == 0) { |
|---|
| 747 | 763 | *p++ = htonl(resp->count); |
|---|
| 748 | 764 | *p++ = htonl(resp->committed); |
|---|
| 749 | | - /* unique identifier, y2038 overflow can be ignored */ |
|---|
| 750 | | - *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); |
|---|
| 751 | | - *p++ = htonl(nn->nfssvc_boot.tv_nsec); |
|---|
| 765 | + *p++ = resp->verf[0]; |
|---|
| 766 | + *p++ = resp->verf[1]; |
|---|
| 752 | 767 | } |
|---|
| 753 | 768 | return xdr_ressize_check(rqstp, p); |
|---|
| 754 | 769 | } |
|---|
| .. | .. |
|---|
| 759 | 774 | { |
|---|
| 760 | 775 | struct nfsd3_diropres *resp = rqstp->rq_resp; |
|---|
| 761 | 776 | |
|---|
| 777 | + *p++ = resp->status; |
|---|
| 762 | 778 | if (resp->status == 0) { |
|---|
| 763 | 779 | *p++ = xdr_one; |
|---|
| 764 | 780 | p = encode_fh(p, &resp->fh); |
|---|
| .. | .. |
|---|
| 774 | 790 | { |
|---|
| 775 | 791 | struct nfsd3_renameres *resp = rqstp->rq_resp; |
|---|
| 776 | 792 | |
|---|
| 793 | + *p++ = resp->status; |
|---|
| 777 | 794 | p = encode_wcc_data(rqstp, p, &resp->ffh); |
|---|
| 778 | 795 | p = encode_wcc_data(rqstp, p, &resp->tfh); |
|---|
| 779 | 796 | return xdr_ressize_check(rqstp, p); |
|---|
| .. | .. |
|---|
| 785 | 802 | { |
|---|
| 786 | 803 | struct nfsd3_linkres *resp = rqstp->rq_resp; |
|---|
| 787 | 804 | |
|---|
| 805 | + *p++ = resp->status; |
|---|
| 788 | 806 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| 789 | 807 | p = encode_wcc_data(rqstp, p, &resp->tfh); |
|---|
| 790 | 808 | return xdr_ressize_check(rqstp, p); |
|---|
| .. | .. |
|---|
| 796 | 814 | { |
|---|
| 797 | 815 | struct nfsd3_readdirres *resp = rqstp->rq_resp; |
|---|
| 798 | 816 | |
|---|
| 817 | + *p++ = resp->status; |
|---|
| 799 | 818 | p = encode_post_op_attr(rqstp, p, &resp->fh); |
|---|
| 800 | 819 | |
|---|
| 801 | 820 | if (resp->status == 0) { |
|---|
| .. | .. |
|---|
| 855 | 874 | } else |
|---|
| 856 | 875 | dchild = dget(dparent); |
|---|
| 857 | 876 | } else |
|---|
| 858 | | - dchild = lookup_one_len_unlocked(name, dparent, namlen); |
|---|
| 877 | + dchild = lookup_positive_unlocked(name, dparent, namlen); |
|---|
| 859 | 878 | if (IS_ERR(dchild)) |
|---|
| 860 | 879 | return rv; |
|---|
| 861 | 880 | if (d_mountpoint(dchild)) |
|---|
| 862 | | - goto out; |
|---|
| 863 | | - if (d_really_is_negative(dchild)) |
|---|
| 864 | 881 | goto out; |
|---|
| 865 | 882 | if (dchild->d_inode->i_ino != ino) |
|---|
| 866 | 883 | goto out; |
|---|
| .. | .. |
|---|
| 1055 | 1072 | struct kstatfs *s = &resp->stats; |
|---|
| 1056 | 1073 | u64 bs = s->f_bsize; |
|---|
| 1057 | 1074 | |
|---|
| 1075 | + *p++ = resp->status; |
|---|
| 1058 | 1076 | *p++ = xdr_zero; /* no post_op_attr */ |
|---|
| 1059 | 1077 | |
|---|
| 1060 | 1078 | if (resp->status == 0) { |
|---|
| .. | .. |
|---|
| 1075 | 1093 | { |
|---|
| 1076 | 1094 | struct nfsd3_fsinfores *resp = rqstp->rq_resp; |
|---|
| 1077 | 1095 | |
|---|
| 1096 | + *p++ = resp->status; |
|---|
| 1078 | 1097 | *p++ = xdr_zero; /* no post_op_attr */ |
|---|
| 1079 | 1098 | |
|---|
| 1080 | 1099 | if (resp->status == 0) { |
|---|
| .. | .. |
|---|
| 1100 | 1119 | { |
|---|
| 1101 | 1120 | struct nfsd3_pathconfres *resp = rqstp->rq_resp; |
|---|
| 1102 | 1121 | |
|---|
| 1122 | + *p++ = resp->status; |
|---|
| 1103 | 1123 | *p++ = xdr_zero; /* no post_op_attr */ |
|---|
| 1104 | 1124 | |
|---|
| 1105 | 1125 | if (resp->status == 0) { |
|---|
| .. | .. |
|---|
| 1119 | 1139 | nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) |
|---|
| 1120 | 1140 | { |
|---|
| 1121 | 1141 | struct nfsd3_commitres *resp = rqstp->rq_resp; |
|---|
| 1122 | | - struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
|---|
| 1123 | 1142 | |
|---|
| 1143 | + *p++ = resp->status; |
|---|
| 1124 | 1144 | p = encode_wcc_data(rqstp, p, &resp->fh); |
|---|
| 1125 | 1145 | /* Write verifier */ |
|---|
| 1126 | 1146 | if (resp->status == 0) { |
|---|
| 1127 | | - /* unique identifier, y2038 overflow can be ignored */ |
|---|
| 1128 | | - *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); |
|---|
| 1129 | | - *p++ = htonl(nn->nfssvc_boot.tv_nsec); |
|---|
| 1147 | + *p++ = resp->verf[0]; |
|---|
| 1148 | + *p++ = resp->verf[1]; |
|---|
| 1130 | 1149 | } |
|---|
| 1131 | 1150 | return xdr_ressize_check(rqstp, p); |
|---|
| 1132 | 1151 | } |
|---|