summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2001-05-19 19:24:26 +0000
committermckusick <mckusick@FreeBSD.org>2001-05-19 19:24:26 +0000
commitaac9daff0f7d0228f61656dc35d461c5ea62d126 (patch)
tree8049dc1a2a0435819c9c2819d10b6d681fce3f58 /sys
parent3e353602c3ff22078aa79f45fbb06b9594581148 (diff)
downloadFreeBSD-src-aac9daff0f7d0228f61656dc35d461c5ea62d126.zip
FreeBSD-src-aac9daff0f7d0228f61656dc35d461c5ea62d126.tar.gz
Must ensure that all the entries on the pd_pendinghd list have been
committed to disk before clearing them. More specifically, when free_newdirblk is called, we know that the inode claims the new directory block. However, if the associated pagedep is still linked onto the directory buffer dependency chain, then some of the entries on the pd_pendinghd list may not be committed to disk yet. In this case, we will simply note that the inode claims the block and let the pd_pendinghd list be processed when the pagedep is next written. If the pagedep is no longer on the buffer dependency chain, then all the entries on the pd_pending list are committed to disk and we can free them in free_newdirblk. This corrects a window of vulnerability introduced in the code added in version 1.95.
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index efa0966..56cf0cb 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2017,12 +2017,20 @@ free_newdirblk(newdirblk)
panic("free_newdirblk: lock not held");
#endif
/*
- * Free any directory additions that have been committed.
+ * If the pagedep is still linked onto the directory buffer
+ * dependency chain, then some of the entries on the
+ * pd_pendinghd list may not be committed to disk yet. In
+ * this case, we will simply clear the NEWBLOCK flag and
+ * let the pd_pendinghd list be processed when the pagedep
+ * is next written. If the pagedep is no longer on the buffer
+ * dependency chain, then all the entries on the pd_pending
+ * list are committed to disk and we can free them here.
*/
pagedep = newdirblk->db_pagedep;
pagedep->pd_state &= ~NEWBLOCK;
- while ((dap = LIST_FIRST(&pagedep->pd_pendinghd)) != NULL)
- free_diradd(dap);
+ if ((pagedep->pd_state & ONWORKLIST) == 0)
+ while ((dap = LIST_FIRST(&pagedep->pd_pendinghd)) != NULL)
+ free_diradd(dap);
/*
* If no dependencies remain, the pagedep will be freed.
*/
OpenPOWER on IntegriCloud