mirror of
https://github.com/openzfs/zfs.git
synced 2026-06-01 15:38:57 +02:00
enforce exact decompressed length for lz4, gzip, and zstd
checkstyle / checkstyle (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
smatch / smatch (push) Has been cancelled
zfs-arm / ZFS ARM build (push) Has been cancelled
zfs-qemu / Setup (push) Has been cancelled
zloop / zloop (push) Has been cancelled
zfs-qemu / qemu-x86 (push) Has been cancelled
zfs-qemu / Cleanup (push) Has been cancelled
checkstyle / checkstyle (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
smatch / smatch (push) Has been cancelled
zfs-arm / ZFS ARM build (push) Has been cancelled
zfs-qemu / Setup (push) Has been cancelled
zloop / zloop (push) Has been cancelled
zfs-qemu / qemu-x86 (push) Has been cancelled
zfs-qemu / Cleanup (push) Has been cancelled
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 <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Alek Pinchuk <Alek.Pinchuk@connectwise.com> Closes #18599
This commit is contained in:
+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