aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2012-03-02 17:14:31 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-06 10:32:48 -0500
commitcd93710e8d290711ba2e08e1d1a380013aad667d (patch)
tree28f1a04dabfa3eaa64b61ea4491654e9ba70d889 /fs/nfs
parentab19b4813fdbdef8f9c8732d1f7a2a69ae78d00b (diff)
NFS: Fix nfs4_verifier memory alignment
Clean up due to code review. The nfs4_verifier's data field is not guaranteed to be u32-aligned. Casting an array of chars to a u32 * is considered generally hazardous. Fix this by using a __be32 array to generate a verifier's contents, and then byte-copy the contents into the verifier field. The contents of a verifier, for all intents and purposes, are opaque bytes. Only local code that generates a verifier need know the actual content and format. Everyone else compares the full byte array for exact equality. Also, sizeof(nfs4_verifer) is the size of the in-core verifier data structure, but NFS4_VERIFIER_SIZE is the number of octets in an XDR'd verifier. The two are not interchangeable, even if they happen to have the same value. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c32
-rw-r--r--fs/nfs/nfs4xdr.c40
2 files changed, 39 insertions, 33 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e0e35288361c..1ec05222ccbc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -836,13 +836,15 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
836 p->o_arg.dir_bitmask = server->cache_consistency_bitmask; 836 p->o_arg.dir_bitmask = server->cache_consistency_bitmask;
837 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; 837 p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
838 if (attrs != NULL && attrs->ia_valid != 0) { 838 if (attrs != NULL && attrs->ia_valid != 0) {
839 u32 *s; 839 __be32 verf[2];
840 840
841 p->o_arg.u.attrs = &p->attrs; 841 p->o_arg.u.attrs = &p->attrs;
842 memcpy(&p->attrs, attrs, sizeof(p->attrs)); 842 memcpy(&p->attrs, attrs, sizeof(p->attrs));
843 s = (u32 *) p->o_arg.u.verifier.data; 843
844 s[0] = jiffies; 844 verf[0] = jiffies;
845 s[1] = current->pid; 845 verf[1] = current->pid;
846 memcpy(p->o_arg.u.verifier.data, verf,
847 sizeof(p->o_arg.u.verifier.data));
846 } 848 }
847 p->c_arg.fh = &p->o_res.fh; 849 p->c_arg.fh = &p->o_res.fh;
848 p->c_arg.stateid = &p->o_res.stateid; 850 p->c_arg.stateid = &p->o_res.stateid;
@@ -3819,6 +3821,16 @@ wait_on_recovery:
3819 return -EAGAIN; 3821 return -EAGAIN;
3820} 3822}
3821 3823
3824static void nfs4_construct_boot_verifier(struct nfs_client *clp,
3825 nfs4_verifier *bootverf)
3826{
3827 __be32 verf[2];
3828
3829 verf[0] = htonl((u32)clp->cl_boot_time.tv_sec);
3830 verf[1] = htonl((u32)clp->cl_boot_time.tv_nsec);
3831 memcpy(bootverf->data, verf, sizeof(bootverf->data));
3832}
3833
3822int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, 3834int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3823 unsigned short port, struct rpc_cred *cred, 3835 unsigned short port, struct rpc_cred *cred,
3824 struct nfs4_setclientid_res *res) 3836 struct nfs4_setclientid_res *res)
@@ -3835,13 +3847,10 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3835 .rpc_resp = res, 3847 .rpc_resp = res,
3836 .rpc_cred = cred, 3848 .rpc_cred = cred,
3837 }; 3849 };
3838 __be32 *p;
3839 int loop = 0; 3850 int loop = 0;
3840 int status; 3851 int status;
3841 3852
3842 p = (__be32*)sc_verifier.data; 3853 nfs4_construct_boot_verifier(clp, &sc_verifier);
3843 *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
3844 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
3845 3854
3846 for(;;) { 3855 for(;;) {
3847 rcu_read_lock(); 3856 rcu_read_lock();
@@ -4933,6 +4942,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4933{ 4942{
4934 nfs4_verifier verifier; 4943 nfs4_verifier verifier;
4935 struct nfs41_exchange_id_args args = { 4944 struct nfs41_exchange_id_args args = {
4945 .verifier = &verifier,
4936 .client = clp, 4946 .client = clp,
4937 .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, 4947 .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER,
4938 }; 4948 };
@@ -4946,15 +4956,11 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
4946 .rpc_resp = &res, 4956 .rpc_resp = &res,
4947 .rpc_cred = cred, 4957 .rpc_cred = cred,
4948 }; 4958 };
4949 __be32 *p;
4950 4959
4951 dprintk("--> %s\n", __func__); 4960 dprintk("--> %s\n", __func__);
4952 BUG_ON(clp == NULL); 4961 BUG_ON(clp == NULL);
4953 4962
4954 p = (u32 *)verifier.data; 4963 nfs4_construct_boot_verifier(clp, &verifier);
4955 *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
4956 *p = htonl((u32)clp->cl_boot_time.tv_nsec);
4957 args.verifier = &verifier;
4958 4964
4959 args.id_len = scnprintf(args.id, sizeof(args.id), 4965 args.id_len = scnprintf(args.id, sizeof(args.id),
4960 "%s/%s.%s/%u", 4966 "%s/%s.%s/%u",
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e9d4ac06b5d9..62effaf579c4 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1538,7 +1538,7 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1538 FATTR4_WORD1_MOUNTED_ON_FILEID, 1538 FATTR4_WORD1_MOUNTED_ON_FILEID,
1539 }; 1539 };
1540 uint32_t dircount = readdir->count >> 1; 1540 uint32_t dircount = readdir->count >> 1;
1541 __be32 *p; 1541 __be32 *p, verf[2];
1542 1542
1543 if (readdir->plus) { 1543 if (readdir->plus) {
1544 attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE| 1544 attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
@@ -1553,10 +1553,11 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1553 if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) 1553 if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
1554 attrs[0] |= FATTR4_WORD0_FILEID; 1554 attrs[0] |= FATTR4_WORD0_FILEID;
1555 1555
1556 p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); 1556 p = reserve_space(xdr, 12);
1557 *p++ = cpu_to_be32(OP_READDIR); 1557 *p++ = cpu_to_be32(OP_READDIR);
1558 p = xdr_encode_hyper(p, readdir->cookie); 1558 p = xdr_encode_hyper(p, readdir->cookie);
1559 p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE); 1559 encode_nfs4_verifier(xdr, &readdir->verifier);
1560 p = reserve_space(xdr, 20);
1560 *p++ = cpu_to_be32(dircount); 1561 *p++ = cpu_to_be32(dircount);
1561 *p++ = cpu_to_be32(readdir->count); 1562 *p++ = cpu_to_be32(readdir->count);
1562 *p++ = cpu_to_be32(2); 1563 *p++ = cpu_to_be32(2);
@@ -1565,11 +1566,11 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1565 *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); 1566 *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
1566 hdr->nops++; 1567 hdr->nops++;
1567 hdr->replen += decode_readdir_maxsz; 1568 hdr->replen += decode_readdir_maxsz;
1569 memcpy(verf, readdir->verifier.data, sizeof(verf));
1568 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", 1570 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
1569 __func__, 1571 __func__,
1570 (unsigned long long)readdir->cookie, 1572 (unsigned long long)readdir->cookie,
1571 ((u32 *)readdir->verifier.data)[0], 1573 verf[0], verf[1],
1572 ((u32 *)readdir->verifier.data)[1],
1573 attrs[0] & readdir->bitmask[0], 1574 attrs[0] & readdir->bitmask[0],
1574 attrs[1] & readdir->bitmask[1]); 1575 attrs[1] & readdir->bitmask[1]);
1575} 1576}
@@ -1643,9 +1644,9 @@ static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclie
1643{ 1644{
1644 __be32 *p; 1645 __be32 *p;
1645 1646
1646 p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE); 1647 p = reserve_space(xdr, 4);
1647 *p++ = cpu_to_be32(OP_SETCLIENTID); 1648 *p = cpu_to_be32(OP_SETCLIENTID);
1648 xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); 1649 encode_nfs4_verifier(xdr, setclientid->sc_verifier);
1649 1650
1650 encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); 1651 encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
1651 p = reserve_space(xdr, 4); 1652 p = reserve_space(xdr, 4);
@@ -1662,10 +1663,10 @@ static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4
1662{ 1663{
1663 __be32 *p; 1664 __be32 *p;
1664 1665
1665 p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE); 1666 p = reserve_space(xdr, 12);
1666 *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM); 1667 *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM);
1667 p = xdr_encode_hyper(p, arg->clientid); 1668 p = xdr_encode_hyper(p, arg->clientid);
1668 xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE); 1669 encode_nfs4_verifier(xdr, &arg->confirm);
1669 hdr->nops++; 1670 hdr->nops++;
1670 hdr->replen += decode_setclientid_confirm_maxsz; 1671 hdr->replen += decode_setclientid_confirm_maxsz;
1671} 1672}
@@ -1708,9 +1709,9 @@ static void encode_exchange_id(struct xdr_stream *xdr,
1708 char impl_name[NFS4_OPAQUE_LIMIT]; 1709 char impl_name[NFS4_OPAQUE_LIMIT];
1709 int len = 0; 1710 int len = 0;
1710 1711
1711 p = reserve_space(xdr, 4 + sizeof(args->verifier->data)); 1712 p = reserve_space(xdr, 4);
1712 *p++ = cpu_to_be32(OP_EXCHANGE_ID); 1713 *p = cpu_to_be32(OP_EXCHANGE_ID);
1713 xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data)); 1714 encode_nfs4_verifier(xdr, args->verifier);
1714 1715
1715 encode_string(xdr, args->id_len, args->id); 1716 encode_string(xdr, args->id_len, args->id);
1716 1717
@@ -4162,7 +4163,7 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
4162 4163
4163static int decode_verifier(struct xdr_stream *xdr, void *verifier) 4164static int decode_verifier(struct xdr_stream *xdr, void *verifier)
4164{ 4165{
4165 return decode_opaque_fixed(xdr, verifier, 8); 4166 return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
4166} 4167}
4167 4168
4168static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res) 4169static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
@@ -4854,17 +4855,16 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
4854 size_t hdrlen; 4855 size_t hdrlen;
4855 u32 recvd, pglen = rcvbuf->page_len; 4856 u32 recvd, pglen = rcvbuf->page_len;
4856 int status; 4857 int status;
4858 __be32 verf[2];
4857 4859
4858 status = decode_op_hdr(xdr, OP_READDIR); 4860 status = decode_op_hdr(xdr, OP_READDIR);
4859 if (!status) 4861 if (!status)
4860 status = decode_verifier(xdr, readdir->verifier.data); 4862 status = decode_verifier(xdr, readdir->verifier.data);
4861 if (unlikely(status)) 4863 if (unlikely(status))
4862 return status; 4864 return status;
4865 memcpy(verf, readdir->verifier.data, sizeof(verf));
4863 dprintk("%s: verifier = %08x:%08x\n", 4866 dprintk("%s: verifier = %08x:%08x\n",
4864 __func__, 4867 __func__, verf[0], verf[1]);
4865 ((u32 *)readdir->verifier.data)[0],
4866 ((u32 *)readdir->verifier.data)[1]);
4867
4868 4868
4869 hdrlen = (char *) xdr->p - (char *) iov->iov_base; 4869 hdrlen = (char *) xdr->p - (char *) iov->iov_base;
4870 recvd = rcvbuf->len - hdrlen; 4870 recvd = rcvbuf->len - hdrlen;
@@ -5111,7 +5111,7 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
5111 goto out_overflow; 5111 goto out_overflow;
5112 res->count = be32_to_cpup(p++); 5112 res->count = be32_to_cpup(p++);
5113 res->verf->committed = be32_to_cpup(p++); 5113 res->verf->committed = be32_to_cpup(p++);
5114 memcpy(res->verf->verifier, p, 8); 5114 memcpy(res->verf->verifier, p, NFS4_VERIFIER_SIZE);
5115 return 0; 5115 return 0;
5116out_overflow: 5116out_overflow:
5117 print_overflow_msg(__func__, xdr); 5117 print_overflow_msg(__func__, xdr);
@@ -5455,7 +5455,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr,
5455 p += 2; 5455 p += 2;
5456 5456
5457 /* Read verifier */ 5457 /* Read verifier */
5458 p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8); 5458 p = xdr_decode_opaque_fixed(p, verftemp.verifier, NFS4_VERIFIER_SIZE);
5459 5459
5460 res->num_devs = be32_to_cpup(p); 5460 res->num_devs = be32_to_cpup(p);
5461 5461