pstore fix for v6.6-rc1
- Adjust sizes of buffers just avoid uncompress failures (Ard Biesheuvel) -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEEpcP2jyKd1g9yPm4TiXL039xtwCYFAmTyLIIWHGtlZXNjb29r QGNocm9taXVtLm9yZwAKCRCJcvTf3G3AJrdjD/9Vl4t3OmP4ahaYVaRXAC3iTCdr ZB2idXOdGnpDDUywthjEKHUvco9eyHr0ApjnXjRRctRByf+nBN0DnTbokF8Uv+93 Bb4/Aqi5y8yioRMTyZ6zt4ZgYpjwiB0fknpOW2NGSVP0CpgDEE33zRU0x64drMbT XOcOQ41o75NN39BrZ7ccp5jKor/XIYz063/zpqYE78HwTJ9Op9+SQettIgZfdk2/ imTNMpSiqpbMxbTnS5cldhPgpr93kRoItr6CceF/7+bd8azWJsUEe7XXcAmK9RJN InO6XxnySv3eML94kVMBpTdWuXwM3O4BxHRBz1lunQZfD1kES/B74UJ2iF0IfpFe gT6kgGy3rgIuY7rkmcFHjzIZ7zV0tynlfppTWSf/Y1lzZNBFdtX0pXBNweDEDD53 LA7DrKbusRSMx9srIJnVFiGYSndaaTyViPYD1esVxppv2+wS6DWAHGpxLfYmBA2A i5geEblp3W25zAtpg6G1Uu2sTY8f1X54V3W74D9AkalnoMDSyqVz67QS/q+wsYyf jQZ+JgTuJBHOCYzgfRlnuQpkiGlz6EKoNlgJ59H8ls6sAygPYS0gKmdnRGDrjF9R cSmjVBebBcOV0FiGIoRlh03FoQyTG81DXvXpro6IeqKk4miV9PQtmCeMtIwZ9/cq rVxyOHK2u+Q9S0230A== =rf8u -----END PGP SIGNATURE----- Merge tag 'pstore-v6.6-rc1-fix' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux Pull pstore fix from Kees Cook: - Adjust sizes of buffers just avoid uncompress failures (Ard Biesheuvel) * tag 'pstore-v6.6-rc1-fix' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: pstore: Base compression input buffer size on estimated compressed size
This commit is contained in:
commit
82c5561b57
@ -98,7 +98,14 @@ MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");
|
||||
|
||||
static void *compress_workspace;
|
||||
|
||||
/*
|
||||
* Compression is only used for dmesg output, which consists of low-entropy
|
||||
* ASCII text, and so we can assume worst-case 60%.
|
||||
*/
|
||||
#define DMESG_COMP_PERCENT 60
|
||||
|
||||
static char *big_oops_buf;
|
||||
static size_t max_compressed_size;
|
||||
|
||||
void pstore_set_kmsg_bytes(int bytes)
|
||||
{
|
||||
@ -196,6 +203,7 @@ static int pstore_compress(const void *in, void *out,
|
||||
|
||||
static void allocate_buf_for_compression(void)
|
||||
{
|
||||
size_t compressed_size;
|
||||
char *buf;
|
||||
|
||||
/* Skip if not built-in or compression disabled. */
|
||||
@ -216,7 +224,8 @@ static void allocate_buf_for_compression(void)
|
||||
* uncompressed record size, since any record that would be expanded by
|
||||
* compression is just stored uncompressed.
|
||||
*/
|
||||
buf = kvzalloc(psinfo->bufsize, GFP_KERNEL);
|
||||
compressed_size = (psinfo->bufsize * 100) / DMESG_COMP_PERCENT;
|
||||
buf = kvzalloc(compressed_size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
pr_err("Failed %zu byte compression buffer allocation for: %s\n",
|
||||
psinfo->bufsize, compress);
|
||||
@ -233,6 +242,7 @@ static void allocate_buf_for_compression(void)
|
||||
|
||||
/* A non-NULL big_oops_buf indicates compression is available. */
|
||||
big_oops_buf = buf;
|
||||
max_compressed_size = compressed_size;
|
||||
|
||||
pr_info("Using crash dump compression: %s\n", compress);
|
||||
}
|
||||
@ -246,6 +256,7 @@ static void free_buf_for_compression(void)
|
||||
|
||||
kvfree(big_oops_buf);
|
||||
big_oops_buf = NULL;
|
||||
max_compressed_size = 0;
|
||||
}
|
||||
|
||||
void pstore_record_init(struct pstore_record *record,
|
||||
@ -305,7 +316,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
|
||||
record.buf = psinfo->buf;
|
||||
|
||||
dst = big_oops_buf ?: psinfo->buf;
|
||||
dst_size = psinfo->bufsize;
|
||||
dst_size = max_compressed_size ?: psinfo->bufsize;
|
||||
|
||||
/* Write dump header. */
|
||||
header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
|
||||
@ -326,8 +337,15 @@ static void pstore_dump(struct kmsg_dumper *dumper,
|
||||
record.compressed = true;
|
||||
record.size = zipped_len;
|
||||
} else {
|
||||
record.size = header_size + dump_size;
|
||||
memcpy(psinfo->buf, dst, record.size);
|
||||
/*
|
||||
* Compression failed, so the buffer is most
|
||||
* likely filled with binary data that does not
|
||||
* compress as well as ASCII text. Copy as much
|
||||
* of the uncompressed data as possible into
|
||||
* the pstore record, and discard the rest.
|
||||
*/
|
||||
record.size = psinfo->bufsize;
|
||||
memcpy(psinfo->buf, dst, psinfo->bufsize);
|
||||
}
|
||||
} else {
|
||||
record.size = header_size + dump_size;
|
||||
@ -560,6 +578,7 @@ static void decompress_record(struct pstore_record *record,
|
||||
int ret;
|
||||
int unzipped_len;
|
||||
char *unzipped, *workspace;
|
||||
size_t max_uncompressed_size;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)
|
||||
return;
|
||||
@ -583,7 +602,8 @@ static void decompress_record(struct pstore_record *record,
|
||||
}
|
||||
|
||||
/* Allocate enough space to hold max decompression and ECC. */
|
||||
workspace = kvzalloc(psinfo->bufsize + record->ecc_notice_size,
|
||||
max_uncompressed_size = 3 * psinfo->bufsize;
|
||||
workspace = kvzalloc(max_uncompressed_size + record->ecc_notice_size,
|
||||
GFP_KERNEL);
|
||||
if (!workspace)
|
||||
return;
|
||||
@ -591,11 +611,11 @@ static void decompress_record(struct pstore_record *record,
|
||||
zstream->next_in = record->buf;
|
||||
zstream->avail_in = record->size;
|
||||
zstream->next_out = workspace;
|
||||
zstream->avail_out = psinfo->bufsize;
|
||||
zstream->avail_out = max_uncompressed_size;
|
||||
|
||||
ret = zlib_inflate(zstream, Z_FINISH);
|
||||
if (ret != Z_STREAM_END) {
|
||||
pr_err("zlib_inflate() failed, ret = %d!\n", ret);
|
||||
pr_err_ratelimited("zlib_inflate() failed, ret = %d!\n", ret);
|
||||
kvfree(workspace);
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user