summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-09-12 09:31:39 -0400
committerJ. Bruce Fields <bfields@redhat.com>2013-10-29 17:43:52 -0400
commit49e7372063a220651b4f12fa46113559533cafee (patch)
tree5646b5f1a30977b5e31313d47973695662245b9c /fs
parent956c4fee446c568ad102625da931e259f22c67ee (diff)
downloadlinux-stable-49e7372063a220651b4f12fa46113559533cafee.tar.gz
linux-stable-49e7372063a220651b4f12fa46113559533cafee.tar.bz2
linux-stable-49e7372063a220651b4f12fa46113559533cafee.zip
nfsd: fh_update should error out in unexpected cases
The reporter saw a NULL dereference when a filesystem's ->mknod returned success but left the dentry negative, and then nfsd tried to dereference d_inode (in this case because the CREATE was followed by a GETATTR in the same nfsv4 compound). fh_update already checks for this and another broken case, but for some reason it returns success and leaves nfsd trying to soldier on. If it failed we'd avoid the crash. There's only so much we can do with a buggy filesystem, but it's easy enough to bail out here, so let's do that. Reported-by: Antti Tönkyrä <daedalus@pingtimeout.net> Tested-by: Antti Tönkyrä <daedalus@pingtimeout.net> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfsfh.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 3d0e15ae6f72..3c37b160dcad 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -598,22 +598,20 @@ fh_update(struct svc_fh *fhp)
_fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
} else {
if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT)
- goto out;
+ return 0;
_fh_update(fhp, fhp->fh_export, dentry);
if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID)
return nfserr_opnotsupp;
}
-out:
return 0;
-
out_bad:
printk(KERN_ERR "fh_update: fh not verified!\n");
- goto out;
+ return nfserr_serverfault;
out_negative:
printk(KERN_ERR "fh_update: %pd2 still negative!\n",
dentry);
- goto out;
+ return nfserr_serverfault;
}
/*