From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/fs/nfsd/nfs3xdr.c | 97 +++++++++++++++++++++++++++++------------------- 1 files changed, 58 insertions(+), 39 deletions(-) diff --git a/kernel/fs/nfsd/nfs3xdr.c b/kernel/fs/nfsd/nfs3xdr.c index b90bea1..716566d 100644 --- a/kernel/fs/nfsd/nfs3xdr.c +++ b/kernel/fs/nfsd/nfs3xdr.c @@ -27,18 +27,19 @@ NF3SOCK, NF3BAD, NF3LNK, NF3BAD, }; + /* * XDR functions for basic NFS types */ static __be32 * -encode_time3(__be32 *p, struct timespec *time) +encode_time3(__be32 *p, struct timespec64 *time) { *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); return p; } static __be32 * -decode_time3(__be32 *p, struct timespec *time) +decode_time3(__be32 *p, struct timespec64 *time) { time->tv_sec = ntohl(*p++); time->tv_nsec = ntohl(*p++); @@ -96,7 +97,7 @@ } static __be32 * -decode_sattr3(__be32 *p, struct iattr *iap) +decode_sattr3(__be32 *p, struct iattr *iap, struct user_namespace *userns) { u32 tmp; @@ -107,12 +108,12 @@ iap->ia_mode = ntohl(*p++); } if (*p++) { - iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++)); + iap->ia_uid = make_kuid(userns, ntohl(*p++)); if (uid_valid(iap->ia_uid)) iap->ia_valid |= ATTR_UID; } if (*p++) { - iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++)); + iap->ia_gid = make_kgid(userns, ntohl(*p++)); if (gid_valid(iap->ia_gid)) iap->ia_valid |= ATTR_GID; } @@ -165,12 +166,12 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat) { - struct timespec ts; + struct user_namespace *userns = nfsd_user_namespace(rqstp); *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); *p++ = htonl((u32) (stat->mode & S_IALLUGO)); *p++ = htonl((u32) stat->nlink); - *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); - *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); + *p++ = htonl((u32) from_kuid_munged(userns, stat->uid)); + *p++ = htonl((u32) from_kgid_munged(userns, stat->gid)); if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); } else { @@ -181,12 +182,9 @@ *p++ = htonl((u32) MINOR(stat->rdev)); p = encode_fsid(p, fhp); p = xdr_encode_hyper(p, stat->ino); - ts = timespec64_to_timespec(stat->atime); - p = encode_time3(p, &ts); - ts = timespec64_to_timespec(stat->mtime); - p = encode_time3(p, &ts); - ts = timespec64_to_timespec(stat->ctime); - p = encode_time3(p, &ts); + p = encode_time3(p, &stat->atime); + p = encode_time3(p, &stat->mtime); + p = encode_time3(p, &stat->ctime); return p; } @@ -275,8 +273,8 @@ stat.size = inode->i_size; } - fhp->fh_pre_mtime = timespec64_to_timespec(stat.mtime); - fhp->fh_pre_ctime = timespec64_to_timespec(stat.ctime); + fhp->fh_pre_mtime = stat.mtime; + fhp->fh_pre_ctime = stat.ctime; fhp->fh_pre_size = stat.size; fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); fhp->fh_pre_saved = true; @@ -307,6 +305,12 @@ * XDR decode functions */ int +nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) +{ + return 1; +} + +int nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) { struct nfsd_fhandle *args = rqstp->rq_argp; @@ -325,10 +329,10 @@ p = decode_fh(p, &args->fh); if (!p) return 0; - p = decode_sattr3(p, &args->attrs); + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); if ((args->check_guard = ntohl(*p++)) != 0) { - struct timespec time; + struct timespec64 time; p = decode_time3(p, &time); args->guardtime = time.tv_sec; } @@ -455,7 +459,7 @@ switch (args->createmode = ntohl(*p++)) { case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_GUARDED: - p = decode_sattr3(p, &args->attrs); + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); break; case NFS3_CREATE_EXCLUSIVE: args->verf = p; @@ -476,7 +480,7 @@ if (!(p = decode_fh(p, &args->fh)) || !(p = decode_filename(p, &args->name, &args->len))) return 0; - p = decode_sattr3(p, &args->attrs); + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); return xdr_argsize_check(rqstp, p); } @@ -491,7 +495,7 @@ if (!(p = decode_fh(p, &args->ffh)) || !(p = decode_filename(p, &args->fname, &args->flen))) return 0; - p = decode_sattr3(p, &args->attrs); + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); args->tlen = ntohl(*p++); @@ -519,7 +523,7 @@ if (args->ftype == NF3BLK || args->ftype == NF3CHR || args->ftype == NF3SOCK || args->ftype == NF3FIFO) - p = decode_sattr3(p, &args->attrs); + p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); if (args->ftype == NF3BLK || args->ftype == NF3CHR) { args->major = ntohl(*p++); @@ -573,6 +577,9 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_readdirargs *args = rqstp->rq_argp; + int len; + u32 max_blocksize = svc_max_payload(rqstp); + p = decode_fh(p, &args->fh); if (!p) return 0; @@ -580,8 +587,14 @@ args->verf = p; p += 2; args->dircount = ~0; args->count = ntohl(*p++); - args->count = min_t(u32, args->count, PAGE_SIZE); - args->buffer = page_address(*(rqstp->rq_next_page++)); + len = args->count = min_t(u32, args->count, max_blocksize); + + while (len > 0) { + struct page *p = *(rqstp->rq_next_page++); + if (!args->buffer) + args->buffer = page_address(p); + len -= PAGE_SIZE; + } return xdr_argsize_check(rqstp, p); } @@ -628,10 +641,7 @@ /* * XDR encode functions */ -/* - * There must be an encoding function for void results so svc_process - * will work properly. - */ + int nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) { @@ -644,6 +654,7 @@ { struct nfsd3_attrstat *resp = rqstp->rq_resp; + *p++ = resp->status; if (resp->status == 0) { lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime); @@ -658,6 +669,7 @@ { struct nfsd3_attrstat *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_wcc_data(rqstp, p, &resp->fh); return xdr_ressize_check(rqstp, p); } @@ -668,6 +680,7 @@ { struct nfsd3_diropres *resp = rqstp->rq_resp; + *p++ = resp->status; if (resp->status == 0) { p = encode_fh(p, &resp->fh); p = encode_post_op_attr(rqstp, p, &resp->fh); @@ -682,6 +695,7 @@ { struct nfsd3_accessres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) *p++ = htonl(resp->access); @@ -694,6 +708,7 @@ { struct nfsd3_readlinkres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->len); @@ -716,6 +731,7 @@ { struct nfsd3_readres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->count); @@ -740,15 +756,14 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_writeres *resp = rqstp->rq_resp; - struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + *p++ = resp->status; p = encode_wcc_data(rqstp, p, &resp->fh); if (resp->status == 0) { *p++ = htonl(resp->count); *p++ = htonl(resp->committed); - /* unique identifier, y2038 overflow can be ignored */ - *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); - *p++ = htonl(nn->nfssvc_boot.tv_nsec); + *p++ = resp->verf[0]; + *p++ = resp->verf[1]; } return xdr_ressize_check(rqstp, p); } @@ -759,6 +774,7 @@ { struct nfsd3_diropres *resp = rqstp->rq_resp; + *p++ = resp->status; if (resp->status == 0) { *p++ = xdr_one; p = encode_fh(p, &resp->fh); @@ -774,6 +790,7 @@ { struct nfsd3_renameres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_wcc_data(rqstp, p, &resp->ffh); p = encode_wcc_data(rqstp, p, &resp->tfh); return xdr_ressize_check(rqstp, p); @@ -785,6 +802,7 @@ { struct nfsd3_linkres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_post_op_attr(rqstp, p, &resp->fh); p = encode_wcc_data(rqstp, p, &resp->tfh); return xdr_ressize_check(rqstp, p); @@ -796,6 +814,7 @@ { struct nfsd3_readdirres *resp = rqstp->rq_resp; + *p++ = resp->status; p = encode_post_op_attr(rqstp, p, &resp->fh); if (resp->status == 0) { @@ -855,12 +874,10 @@ } else dchild = dget(dparent); } else - dchild = lookup_one_len_unlocked(name, dparent, namlen); + dchild = lookup_positive_unlocked(name, dparent, namlen); if (IS_ERR(dchild)) return rv; if (d_mountpoint(dchild)) - goto out; - if (d_really_is_negative(dchild)) goto out; if (dchild->d_inode->i_ino != ino) goto out; @@ -1055,6 +1072,7 @@ struct kstatfs *s = &resp->stats; u64 bs = s->f_bsize; + *p++ = resp->status; *p++ = xdr_zero; /* no post_op_attr */ if (resp->status == 0) { @@ -1075,6 +1093,7 @@ { struct nfsd3_fsinfores *resp = rqstp->rq_resp; + *p++ = resp->status; *p++ = xdr_zero; /* no post_op_attr */ if (resp->status == 0) { @@ -1100,6 +1119,7 @@ { struct nfsd3_pathconfres *resp = rqstp->rq_resp; + *p++ = resp->status; *p++ = xdr_zero; /* no post_op_attr */ if (resp->status == 0) { @@ -1119,14 +1139,13 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p) { struct nfsd3_commitres *resp = rqstp->rq_resp; - struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + *p++ = resp->status; p = encode_wcc_data(rqstp, p, &resp->fh); /* Write verifier */ if (resp->status == 0) { - /* unique identifier, y2038 overflow can be ignored */ - *p++ = htonl((u32)nn->nfssvc_boot.tv_sec); - *p++ = htonl(nn->nfssvc_boot.tv_nsec); + *p++ = resp->verf[0]; + *p++ = resp->verf[1]; } return xdr_ressize_check(rqstp, p); } -- Gitblit v1.6.2