The clear_remove() and clear_inodedeps() call vn_start_write(NULL, &mp,

V_NOWAIT) on the non-busied mount point. Unmount might free ufs-specific
mp data, causing ffs_vgetf() to access freed memory.

Busy mountpoint before dropping softdep lk.

Noted and reviewed by:	tegge
Tested by:	pho
MFC after:	1 week
This commit is contained in:
kib 2009-09-06 11:46:51 +00:00
parent 14578a3276
commit 2e1ddcb566

View File

@ -5977,12 +5977,19 @@ clear_remove(td)
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
FREE_LOCK(&lk);
if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
FFSV_FORCEINSMQ))) {
/*
* Let unmount clear deps
*/
error = vfs_busy(mp, MBF_NOWAIT);
if (error != 0)
goto finish_write;
error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
FFSV_FORCEINSMQ);
vfs_unbusy(mp);
if (error != 0) {
softdep_error("clear_remove: vget", error);
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
return;
goto finish_write;
}
if ((error = ffs_syncvnode(vp, MNT_NOWAIT)))
softdep_error("clear_remove: fsync", error);
@ -5991,6 +5998,7 @@ clear_remove(td)
drain_output(vp);
BO_UNLOCK(bo);
vput(vp);
finish_write:
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
return;
@ -6050,13 +6058,21 @@ clear_inodedeps(td)
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
FREE_LOCK(&lk);
if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
FFSV_FORCEINSMQ)) != 0) {
softdep_error("clear_inodedeps: vget", error);
error = vfs_busy(mp, MBF_NOWAIT); /* Let unmount clear deps */
if (error != 0) {
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
return;
}
if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
FFSV_FORCEINSMQ)) != 0) {
softdep_error("clear_inodedeps: vget", error);
vfs_unbusy(mp);
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
return;
}
vfs_unbusy(mp);
if (ino == lastino) {
if ((error = ffs_syncvnode(vp, MNT_WAIT)))
softdep_error("clear_inodedeps: fsync1", error);