proc: fix NULL dereference when reading /proc/<pid>/auxv
[cascardo/linux.git] / fs / nfsd / nfs4xdr.c
index 0aa0236..c2d2895 100644 (file)
@@ -1693,6 +1693,30 @@ nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
        DECODE_TAIL;
 }
 
+static __be32
+nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
+{
+       DECODE_HEAD;
+       unsigned int tmp;
+
+       status = nfsd4_decode_stateid(argp, &copy->cp_src_stateid);
+       if (status)
+               return status;
+       status = nfsd4_decode_stateid(argp, &copy->cp_dst_stateid);
+       if (status)
+               return status;
+
+       READ_BUF(8 + 8 + 8 + 4 + 4 + 4);
+       p = xdr_decode_hyper(p, &copy->cp_src_pos);
+       p = xdr_decode_hyper(p, &copy->cp_dst_pos);
+       p = xdr_decode_hyper(p, &copy->cp_count);
+       copy->cp_consecutive = be32_to_cpup(p++);
+       copy->cp_synchronous = be32_to_cpup(p++);
+       tmp = be32_to_cpup(p); /* Source server list not supported */
+
+       DECODE_TAIL;
+}
+
 static __be32
 nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
 {
@@ -1793,7 +1817,7 @@ static nfsd4_dec nfsd4_dec_ops[] = {
 
        /* new operations for NFSv4.2 */
        [OP_ALLOCATE]           = (nfsd4_dec)nfsd4_decode_fallocate,
-       [OP_COPY]               = (nfsd4_dec)nfsd4_decode_notsupp,
+       [OP_COPY]               = (nfsd4_dec)nfsd4_decode_copy,
        [OP_COPY_NOTIFY]        = (nfsd4_dec)nfsd4_decode_notsupp,
        [OP_DEALLOCATE]         = (nfsd4_dec)nfsd4_decode_fallocate,
        [OP_IO_ADVISE]          = (nfsd4_dec)nfsd4_decode_notsupp,
@@ -4062,7 +4086,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
        u32 starting_len = xdr->buf->len, needed_len;
        __be32 *p;
 
-       dprintk("%s: err %d\n", __func__, nfserr);
+       dprintk("%s: err %d\n", __func__, be32_to_cpu(nfserr));
        if (nfserr)
                goto out;
 
@@ -4201,6 +4225,41 @@ nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
 }
 #endif /* CONFIG_NFSD_PNFS */
 
+static __be32
+nfsd42_encode_write_res(struct nfsd4_compoundres *resp, struct nfsd42_write_res *write)
+{
+       __be32 *p;
+
+       p = xdr_reserve_space(&resp->xdr, 4 + 8 + 4 + NFS4_VERIFIER_SIZE);
+       if (!p)
+               return nfserr_resource;
+
+       *p++ = cpu_to_be32(0);
+       p = xdr_encode_hyper(p, write->wr_bytes_written);
+       *p++ = cpu_to_be32(write->wr_stable_how);
+       p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
+                                   NFS4_VERIFIER_SIZE);
+       return nfs_ok;
+}
+
+static __be32
+nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
+                 struct nfsd4_copy *copy)
+{
+       __be32 *p;
+
+       if (!nfserr) {
+               nfserr = nfsd42_encode_write_res(resp, &copy->cp_res);
+               if (nfserr)
+                       return nfserr;
+
+               p = xdr_reserve_space(&resp->xdr, 4 + 4);
+               *p++ = cpu_to_be32(copy->cp_consecutive);
+               *p++ = cpu_to_be32(copy->cp_synchronous);
+       }
+       return nfserr;
+}
+
 static __be32
 nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
                  struct nfsd4_seek *seek)
@@ -4300,7 +4359,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
 
        /* NFSv4.2 operations */
        [OP_ALLOCATE]           = (nfsd4_enc)nfsd4_encode_noop,
-       [OP_COPY]               = (nfsd4_enc)nfsd4_encode_noop,
+       [OP_COPY]               = (nfsd4_enc)nfsd4_encode_copy,
        [OP_COPY_NOTIFY]        = (nfsd4_enc)nfsd4_encode_noop,
        [OP_DEALLOCATE]         = (nfsd4_enc)nfsd4_encode_noop,
        [OP_IO_ADVISE]          = (nfsd4_enc)nfsd4_encode_noop,