svn commit: r322757 - head/sys/ufs/ffs
Konstantin Belousov
kib at FreeBSD.org
Mon Aug 21 16:23:46 UTC 2017
Author: kib
Date: Mon Aug 21 16:23:44 2017
New Revision: 322757
URL: https://svnweb.freebsd.org/changeset/base/322757
Log:
Avoid dereferencing potentially freed workitem in
softdep_count_dependencies().
Buffer's b_dep list is protected by the SU mount lock. Owning the
buffer lock is not enough to guarantee the stability of the list.
Calculation of the UFS mount owning the workitems from the buffer must
be much more careful to not dereference the work item which might be
freed meantime. To get to ump, use the pointers chain which does not
involve workitems at all.
Reported and tested by: pho
Reviewed by: mckusick
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Modified:
head/sys/ufs/ffs/ffs_softdep.c
Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c Mon Aug 21 16:16:02 2017 (r322756)
+++ head/sys/ufs/ffs/ffs_softdep.c Mon Aug 21 16:23:44 2017 (r322757)
@@ -13919,12 +13919,36 @@ softdep_count_dependencies(bp, wantcount)
struct newblk *newblk;
struct mkdir *mkdir;
struct diradd *dap;
+ struct vnode *vp;
+ struct mount *mp;
int i, retval;
retval = 0;
- if ((wk = LIST_FIRST(&bp->b_dep)) == NULL)
+ if (LIST_EMPTY(&bp->b_dep))
return (0);
- ump = VFSTOUFS(wk->wk_mp);
+ vp = bp->b_vp;
+
+ /*
+ * The ump mount point is stable after we get a correct
+ * pointer, since bp is locked and this prevents unmount from
+ * proceed. But to get to it, we cannot dereference bp->b_dep
+ * head wk_mp, because we do not yet own SU ump lock and
+ * workitem might be freed while dereferenced.
+ */
+retry:
+ if (vp->v_type == VCHR) {
+ VOP_LOCK(vp, LK_RETRY | LK_EXCLUSIVE);
+ mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL;
+ VOP_UNLOCK(vp, 0);
+ if (mp == NULL)
+ goto retry;
+ } else if (vp->v_type == VREG) {
+ mp = vp->v_mount;
+ } else {
+ return (0);
+ }
+ ump = VFSTOUFS(mp);
+
ACQUIRE_LOCK(ump);
LIST_FOREACH(wk, &bp->b_dep, wk_list) {
switch (wk->wk_type) {
More information about the svn-src-all
mailing list