mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
enforce exact decompressed length for lz4, gzip, and zstd
Decompressors must expand a ZFS block to exactly the expected number of bytes. Treat decompression to an unexpected length as failure, so truncated or short output is not accepted as valid decompression. This makes our handling of decompress return values consistent with the decompression functions' APIs. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Alek Pinchuk <[email protected]> Closes #18599
This commit is contained in:
1 parent
eafa39fbc3
commit
c90dc28089
3 files changed
+26
-6
No files matched your search
+6
-2
@@ -96,13 +96,17 @@ zfs_gzip_decompress_buf(void *s_start, void *d_start, size_t s_len,
|
||||
/* check if hardware accelerator can be used */
|
||||
if (qat_dc_use_accel(d_len)) {
|
||||
if (qat_compress(QAT_DECOMPRESS, s_start, s_len,
|
||||
d_start, d_len, &dstlen) == CPA_STATUS_SUCCESS)
|
||||
return (0);
|
||||
d_start, d_len, &dstlen) == CPA_STATUS_SUCCESS) {
|
||||
if ((size_t)dstlen == d_len)
|
||||
return (0);
|
||||
}
|
||||
/* if hardware de-compress fail, do it again with software */
|
||||
}
|
||||
|
||||
if (uncompress_func(d_start, &dstlen, s_start, s_len) != Z_OK)
|
||||
return (-1);
|
||||
if ((size_t)dstlen != d_len)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
+11
-4
@@ -88,17 +88,24 @@ zfs_lz4_decompress_buf(void *s_start, void *d_start, size_t s_len,
|
||||
(void) n;
|
||||
const char *src = s_start;
|
||||
uint32_t bufsiz = BE_IN32(src);
|
||||
int decoded;
|
||||
|
||||
/* invalid compressed buffer size encoded at start */
|
||||
if (bufsiz + sizeof (bufsiz) > s_len)
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* Returns 0 on success (decompression function returned non-negative)
|
||||
* and non-zero on failure (decompression function returned negative).
|
||||
* LZ4_uncompress_unknownOutputSize returns the number of bytes decoded
|
||||
* on success, or a negative value on failure. An OpenZFS block must
|
||||
* expand to exactly d_len bytes
|
||||
*/
|
||||
return (LZ4_uncompress_unknownOutputSize(&src[sizeof (bufsiz)],
|
||||
d_start, bufsiz, d_len) < 0);
|
||||
decoded = LZ4_uncompress_unknownOutputSize(&src[sizeof (bufsiz)],
|
||||
d_start, bufsiz, d_len);
|
||||
if (decoded < 0)
|
||||
return (1);
|
||||
if (d_len != (size_t)decoded)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
ZFS_COMPRESS_WRAP_DECL(zfs_lz4_compress)
|
||||
|
||||
@@ -682,6 +682,15 @@ zfs_zstd_decompress_level_buf(void *s_start, void *d_start, size_t s_len,
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* An OpenZFS compressed block must expand to exactly d_len bytes.
|
||||
* ZSTD_decompressDCtx returns the decompressed size on success.
|
||||
*/
|
||||
if (result != d_len) {
|
||||
ZSTDSTAT_BUMP(zstd_stat_dec_fail);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (level) {
|
||||
*level = curlevel;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user