DragonFlyBSD Kernel Audit
DF-2435 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/dm/crypt/dm_target_crypt.c b/sys/dev/disk/dm/crypt/dm_target_crypt.c
--- a/sys/dev/disk/dm/crypt/dm_target_crypt.c
+++ b/sys/dev/disk/dm/crypt/dm_target_crypt.c
@@ -464,8 +464,21 @@
 		len += strlen(argv[i]);
 		len++;
 	}
-	/* len is strlen() of input string +1 */
-	status_str = kmalloc(len, M_DMCRYPT, M_WAITOK);
+	/*
+	 * Use a fixed-size buffer large enough for the worst-case formatted
+	 * status string.  The ksprintf() below formats iv_offset and
+	 * block_offset with %ju, which can expand a negative strtouq input
+	 * (e.g. "-1") to UQUAD_MAX = 18446744073709551615 (20 digits) -- far
+	 * larger than the 2-char input argv string.  Sizing the buffer from
+	 * the input argv lengths underestimates the output and causes a heap
+	 * overflow (CWE-787).  DM_MAX_PARAMS_SIZE (1024) is the same size
+	 * used by dm_target_crypt_table() when copying status_str, so it is
+	 * guaranteed sufficient.
+	 *
+	 * (len is still computed above and stored in priv->params_len for
+	 *  ABI compatibility, though it is currently unused.)
+	 */
+	status_str = kmalloc(DM_MAX_PARAMS_SIZE, M_DMCRYPT, M_WAITOK);
 
 	crypto_alg = strsep(&argv[0], "-");
 	crypto_mode = strsep(&argv[0], "-");