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], "-");