summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2004-10-19 18:25:26 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-19 18:25:26 -0700
commit7b7e07a026a089e49bba8f1fc7f06da2180c24a2 (patch)
tree651d8027da6e62bf16bbd27cc8e7842028041bb4
parentd1c3bc1b288bdd65403fce876d0b242587293b9b (diff)
[PATCH] nfsd4: fix race in xdr encoding of lock_denied response.
We take a reference on the stateowner, and copy the clientid, instead of just hoping no one destroys the stateowner before we reference it in nfsd4_encode_lock_denied. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/nfsd/nfs4state.c5
-rw-r--r--fs/nfsd/nfs4xdr.c3
-rw-r--r--include/linux/nfsd/xdr4.h1
3 files changed, 7 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index fcf49fe08460..440695e625cb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1949,8 +1949,11 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
unsigned int hval = lockownerid_hashval(sop->so_id);
deny->ld_sop = NULL;
- if (nfs4_verify_lock_stateowner(sop, hval))
+ if (nfs4_verify_lock_stateowner(sop, hval)) {
+ kref_get(&sop->so_ref);
deny->ld_sop = sop;
+ deny->ld_clientid = sop->so_client->cl_clientid;
+ }
deny->ld_start = fl->fl_start;
deny->ld_length = ~(u64)0;
if (fl->fl_end != ~(u64)0)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 67cbaa9cb050..76cd74eddbeb 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1994,9 +1994,10 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
WRITE64(ld->ld_length);
WRITE32(ld->ld_type);
if (ld->ld_sop) {
- WRITEMEM(&ld->ld_sop->so_client->cl_clientid, 8);
+ WRITEMEM(&ld->ld_clientid, 8);
WRITE32(ld->ld_sop->so_owner.len);
WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
+ kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
} else { /* non - nfsv4 lock in conflict, no clientid nor owner */
WRITE64((u64)0); /* clientid */
WRITE32(0); /* length of owner name */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index bf94561ca623..d629b5e55d90 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -116,6 +116,7 @@ struct nfsd4_link {
};
struct nfsd4_lock_denied {
+ clientid_t ld_clientid;
struct nfs4_stateowner *ld_sop;
u64 ld_start;
u64 ld_length;