Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+27 -7
+27 -7
fs/pstore/platform.c
··· 98 98 99 99 static void *compress_workspace; 100 100 101 + /* 102 + * Compression is only used for dmesg output, which consists of low-entropy 103 + * ASCII text, and so we can assume worst-case 60%. 104 + */ 105 + #define DMESG_COMP_PERCENT 60 106 + 101 107 static char *big_oops_buf; 108 + static size_t max_compressed_size; 102 109 103 110 void pstore_set_kmsg_bytes(int bytes) 104 111 { ··· 203 196 204 197 static void allocate_buf_for_compression(void) 205 198 { 199 + size_t compressed_size; 206 200 char *buf; 207 201 208 202 /* Skip if not built-in or compression disabled. */ ··· 224 216 * uncompressed record size, since any record that would be expanded by 225 217 * compression is just stored uncompressed. 226 218 */ 227 - buf = kvzalloc(psinfo->bufsize, GFP_KERNEL); 219 + compressed_size = (psinfo->bufsize * 100) / DMESG_COMP_PERCENT; 220 + buf = kvzalloc(compressed_size, GFP_KERNEL); 228 221 if (!buf) { 229 222 pr_err("Failed %zu byte compression buffer allocation for: %s\n", 230 223 psinfo->bufsize, compress); ··· 242 233 243 234 /* A non-NULL big_oops_buf indicates compression is available. */ 244 235 big_oops_buf = buf; 236 + max_compressed_size = compressed_size; 245 237 246 238 pr_info("Using crash dump compression: %s\n", compress); 247 239 } ··· 256 246 257 247 kvfree(big_oops_buf); 258 248 big_oops_buf = NULL; 249 + max_compressed_size = 0; 259 250 } 260 251 261 252 void pstore_record_init(struct pstore_record *record, ··· 316 305 record.buf = psinfo->buf; 317 306 318 307 dst = big_oops_buf ?: psinfo->buf; 319 - dst_size = psinfo->bufsize; 308 + dst_size = max_compressed_size ?: psinfo->bufsize; 320 309 321 310 /* Write dump header. */ 322 311 header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why, ··· 337 326 record.compressed = true; 338 327 record.size = zipped_len; 339 328 } else { 340 - record.size = header_size + dump_size; 341 - memcpy(psinfo->buf, dst, record.size); 329 + /* 330 + * Compression failed, so the buffer is most 331 + * likely filled with binary data that does not 332 + * compress as well as ASCII text. Copy as much 333 + * of the uncompressed data as possible into 334 + * the pstore record, and discard the rest. 335 + */ 336 + record.size = psinfo->bufsize; 337 + memcpy(psinfo->buf, dst, psinfo->bufsize); 342 338 } 343 339 } else { 344 340 record.size = header_size + dump_size; ··· 578 560 int ret; 579 561 int unzipped_len; 580 562 char *unzipped, *workspace; 563 + size_t max_uncompressed_size; 581 564 582 565 if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed) 583 566 return; ··· 602 583 } 603 584 604 585 /* Allocate enough space to hold max decompression and ECC. */ 605 - workspace = kvzalloc(psinfo->bufsize + record->ecc_notice_size, 586 + max_uncompressed_size = 3 * psinfo->bufsize; 587 + workspace = kvzalloc(max_uncompressed_size + record->ecc_notice_size, 606 588 GFP_KERNEL); 607 589 if (!workspace) 608 590 return; ··· 611 591 zstream->next_in = record->buf; 612 592 zstream->avail_in = record->size; 613 593 zstream->next_out = workspace; 614 - zstream->avail_out = psinfo->bufsize; 594 + zstream->avail_out = max_uncompressed_size; 615 595 616 596 ret = zlib_inflate(zstream, Z_FINISH); 617 597 if (ret != Z_STREAM_END) { 618 - pr_err("zlib_inflate() failed, ret = %d!\n", ret); 598 + pr_err_ratelimited("zlib_inflate() failed, ret = %d!\n", ret); 619 599 kvfree(workspace); 620 600 return; 621 601 }