⬢ DragonFlyBSD Kernel Audit
DF-3816 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/raid/mpr/mpr.c
+++ b/sys/dev/raid/mpr/mpr.c
@@ -1901,15 +1901,18 @@ mpr_dump_reqs(SYSCTL_HANDLER_ARGS)
 	sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
 
-	/* Best effort, no locking */
+	/* Best effort, but keep the lists and frame reads consistent: the
+	 * command/chain lists are mutated under sc->mpr_lock everywhere
+	 * else, and frame sizes are device-reported (may be < 128). */
+	mpr_lock(sc);
 	for (i = smid; i < numreqs; i++) {
 		cm = &sc->commands[i];
 		if (cm->cm_state != state)
 			continue;
 		hdr.smid = i;
 		hdr.state = cm->cm_state;
 		hdr.numframes = 1;
 		hdr.deschi = cm->cm_desc.Words.High;
 		hdr.desclo = cm->cm_desc.Words.Low;
 		TAILQ_FOREACH_MUTABLE(chain, &cm->cm_chain_list, chain_link,
 		   chain1)
 			hdr.numframes++;
 		sbuf_bcat(sb, &hdr, sizeof(hdr));
-		sbuf_bcat(sb, cm->cm_req, 128);
+		sbuf_bcat(sb, cm->cm_req, min(sc->reqframesz, 128));
 		TAILQ_FOREACH_MUTABLE(chain, &cm->cm_chain_list, chain_link,
 		    chain1)
-			sbuf_bcat(sb, chain->chain, 128);
+			sbuf_bcat(sb, chain->chain, min(sc->chain_frame_size, 128));
 	}
+	mpr_unlock(sc);
 
 	error = sbuf_finish(sb);