⬢ DragonFlyBSD Kernel Audit
DF-5829 / fix.diff
← back to finding ↓ download raw
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -987,13 +987,23 @@
 	 * If cleaning the entire object do a pass to mark the pages read-only.
 	 * If everything worked out ok, clear OBJ_WRITEABLE and
 	 * OBJ_MIGHTBEDIRTY.
+	 *
+	 * NOTE: The PG_CLEANCHK marking pass must always run over the
+	 *	 requested range, not just for wholescan, because pass2 and
+	 *	 vm_object_page_collect_flush() ignore any page that does not
+	 *	 have PG_CLEANCHK set.  Restricting pass1 to wholescan made
+	 *	 every partial-range clean a silent no-op (e.g. msync() of a
+	 *	 sub-range, or of a mapping smaller than the object - on
+	 *	 filesystems whose vnode objects are sized beyond EOF by
+	 *	 nvnode_pager_setsize(), such as hammer2, that is every
+	 *	 msync() range expressible on the file).
 	 */
-	if (wholescan) {
-		info.error = 0;
-		info.count = 0;
-		vm_page_rb_tree_RB_SCAN(&object->rb_memq, rb_vm_page_scancmp,
-					vm_object_page_clean_pass1, &info);
-		if (info.error == 0) {
+	info.error = 0;
+	info.count = 0;
+	vm_page_rb_tree_RB_SCAN(&object->rb_memq, rb_vm_page_scancmp,
+				vm_object_page_clean_pass1, &info);
+	{
+		if (wholescan && info.error == 0) {
 			vm_object_clear_flag(object,
 					     OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
 			if (object->type == OBJT_VNODE &&