DragonFlyBSD Kernel Audit
DF-2663 / fixB_on_A.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer2/hammer2_ondisk.c
+++ b/sys/vfs/hammer2/hammer2_ondisk.c
@@ -306,14 +306,24 @@
 				 * volume, never the guest root fs */
 				dioerr = ENXIO;
 			}
-			if (dioerr == 0) {
+			if (dioerr != 0) {
+				/*
+				 * The volume's media size could not be
+				 * determined (probe race, d_slice == NULL,
+				 * raw fallback fail).  This must not
+				 * silently disable the containment check.
+				 */
+				hprintf("%s's media size could not be "
+					"determined, refusing to mount\n",
+					path);
+				return EINVAL;
+			}
 			if (vol->size > part.media_size) {
 				hprintf("%s's size 0x%016jx exceeds device size "
 					"0x%016jx\n", path, (intmax_t)vol->size,
 					part.media_size);
 				return EINVAL;
 			}
-			}
 		}
 		if (vol->size == 0) {
 			hprintf("%s has size of 0\n", path);
--- a/sys/vfs/hammer2/hammer2_io.c
+++ b/sys/vfs/hammer2/hammer2_io.c
@@ -353,6 +353,21 @@
 		dio->bp->b_flags &= ~B_AGE;
 		/* dio->bp->b_debug_info2 = dio; */
 	}
+
+	/*
+	 * A short read completes WITHOUT B_ERROR under several media-EOF
+	 * semantics: dscheck() clamps a straddling transfer to the device
+	 * end (reducing b_bcount); a read starting exactly at EOF completes
+	 * with B_INVAL and full b_resid; a vnode-backed device whose
+	 * backing file shrank returns a 0-byte VOP_READ with uio_resid
+	 * untouched.  In all those cases part (or all) of the buffer is
+	 * uninitialized kernel memory which must not be consumed as
+	 * filesystem data.
+	 */
+	if (error == 0 && dio->bp &&
+	    (dio->bp->b_resid != 0 || dio->bp->b_bcount != dio->psize)) {
+		error = EIO;
+	}
 	dio->error = error;
 
 	/*