diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-03-06 19:11:03 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-03-07 11:44:53 -0500 |
commit | 32b007b4e19b50ff4d27ea8b69cd6d744cfec86b (patch) | |
tree | ada73d6c52a6e9b37cbdc95d086485fdf338561a /fs/nfsd | |
parent | 2c9c8f36c34e1defcaa7e4c298651998b47f5282 (diff) | |
download | kernel_samsung_crespo-32b007b4e19b50ff4d27ea8b69cd6d744cfec86b.zip kernel_samsung_crespo-32b007b4e19b50ff4d27ea8b69cd6d744cfec86b.tar.gz kernel_samsung_crespo-32b007b4e19b50ff4d27ea8b69cd6d744cfec86b.tar.bz2 |
nfsd4: fix bad pointer on failure to find delegation
In case of a nonempty list, the return on error here is obviously bogus;
it ends up being a pointer to the list head instead of to any valid
delegation on the list.
In particular, if nfsd4_delegreturn() hits this case, and you're quite unlucky,
then renew_client may oops, and it may take an embarassingly long time to
figure out why. Facepalm.
BUG: unable to handle kernel NULL pointer dereference at 0000000000000090
IP: [<ffffffff81292965>] nfsd4_delegreturn+0x125/0x200
...
Cc: stable@kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 54b60bf..7b566ec 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2445,15 +2445,16 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) static struct nfs4_delegation * find_delegation_file(struct nfs4_file *fp, stateid_t *stid) { - struct nfs4_delegation *dp = NULL; + struct nfs4_delegation *dp; spin_lock(&recall_lock); - list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { - if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) - break; - } + list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) + if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) { + spin_unlock(&recall_lock); + return dp; + } spin_unlock(&recall_lock); - return dp; + return NULL; } int share_access_to_flags(u32 share_access) |