Date: Mon, 21 Aug 2017 16:23:44 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r322757 - head/sys/ufs/ffs Message-ID: <201708211623.v7LGNiuc094838@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201708211623.v7LGNiuc094838>