nfsd: let nfsd_symlink assume null-terminated data
[firefly-linux-kernel-4.4.55.git] / fs / nfsd / nfs4proc.c
index f053c5a9ebf162c4c35313fb257a8a20201e7a54..7aa83bf34fa980a8bbdda261881afca2a64aaf9b 100644 (file)
@@ -177,7 +177,7 @@ fh_dup2(struct svc_fh *dst, struct svc_fh *src)
        fh_put(dst);
        dget(src->fh_dentry);
        if (src->fh_export)
-               cache_get(&src->fh_export->h);
+               exp_get(src->fh_export);
        *dst = *src;
 }
 
@@ -581,8 +581,12 @@ static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
        __be32 verf[2];
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
-       verf[0] = (__be32)nn->nfssvc_boot.tv_sec;
-       verf[1] = (__be32)nn->nfssvc_boot.tv_usec;
+       /*
+        * This is opaque to client, so no need to byte-swap. Use
+        * __force to keep sparse happy
+        */
+       verf[0] = (__force __be32)nn->nfssvc_boot.tv_sec;
+       verf[1] = (__force __be32)nn->nfssvc_boot.tv_usec;
        memcpy(verifier->data, verf, sizeof(verifier->data));
 }
 
@@ -617,18 +621,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        switch (create->cr_type) {
        case NF4LNK:
-               /* ugh! we have to null-terminate the linktext, or
-                * vfs_symlink() will choke.  it is always safe to
-                * null-terminate by brute force, since at worst we
-                * will overwrite the first byte of the create namelen
-                * in the XDR buffer, which has already been extracted
-                * during XDR decode.
-                */
-               create->cr_linkname[create->cr_linklen] = 0;
-
                status = nfsd_symlink(rqstp, &cstate->current_fh,
                                      create->cr_name, create->cr_namelen,
-                                     create->cr_linkname, create->cr_linklen,
+                                     create->cr_linkname,
                                      &resfh, &create->cr_iattr);
                break;
 
@@ -918,8 +913,8 @@ nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstat
        default:
                return nfserr_inval;
        }
-       exp_get(cstate->current_fh.fh_export);
-       sin->sin_exp = cstate->current_fh.fh_export;
+
+       sin->sin_exp = exp_get(cstate->current_fh.fh_export);
        fh_put(&cstate->current_fh);
        return nfs_ok;
 }
@@ -1264,7 +1259,7 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp,
        /* Tail and page_len should be zero at this point: */
        buf->len = buf->head[0].iov_len;
        xdr->scratch.iov_len = 0;
-       xdr->page_ptr = buf->pages;
+       xdr->page_ptr = buf->pages - 1;
        buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages)
                - rqstp->rq_auth_slack;
 }
@@ -1298,7 +1293,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
         * Don't use the deferral mechanism for NFSv4; compounds make it
         * too hard to avoid non-idempotency problems.
         */
-       rqstp->rq_usedeferral = 0;
+       rqstp->rq_usedeferral = false;
 
        /*
         * According to RFC3010, this takes precedence over all other errors.
@@ -1417,7 +1412,7 @@ encode_op:
        BUG_ON(cstate->replay_owner);
 out:
        /* Reset deferral mechanism for RPC deferrals */
-       rqstp->rq_usedeferral = 1;
+       rqstp->rq_usedeferral = true;
        dprintk("nfsv4 compound returned %d\n", ntohl(status));
        return status;
 }
@@ -1529,21 +1524,17 @@ static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
        u32 maxcount = 0, rlen = 0;
 
        maxcount = svc_max_payload(rqstp);
-       rlen = op->u.read.rd_length;
-
-       if (rlen > maxcount)
-               rlen = maxcount;
+       rlen = min(op->u.read.rd_length, maxcount);
 
        return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
 }
 
 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
 {
-       u32 maxcount = svc_max_payload(rqstp);
-       u32 rlen = op->u.readdir.rd_maxcount;
+       u32 maxcount = 0, rlen = 0;
 
-       if (rlen > maxcount)
-               rlen = maxcount;
+       maxcount = svc_max_payload(rqstp);
+       rlen = min(op->u.readdir.rd_maxcount, maxcount);
 
        return (op_encode_hdr_size + op_encode_verifier_maxsz +
                XDR_QUADLEN(rlen)) * sizeof(__be32);