diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-03-02 17:14:31 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-06 10:32:48 -0500 |
commit | cd93710e8d290711ba2e08e1d1a380013aad667d (patch) | |
tree | 28f1a04dabfa3eaa64b61ea4491654e9ba70d889 /fs/nfs/nfs4proc.c | |
parent | ab19b4813fdbdef8f9c8732d1f7a2a69ae78d00b (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/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 32 |
1 files changed, 19 insertions, 13 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 | ||
3824 | static 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 | |||
3822 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | 3834 | int 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", |