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

pstore: Add decompression support to pstore

Based on the flag 'compressed' set or not, pstore will decompress the
data returning a plain text file. If decompression fails for a particular
record it will have the compressed data in the file which can be
decompressed with 'openssl' command line tool.

Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Aruna Balakrishnaiah and committed by
Tony Luck
adb42f5e 9a4e1398

+51 -2
+51 -2
fs/pstore/platform.c
··· 162 162 return ret; 163 163 } 164 164 165 + /* Derived from logfs_uncompress */ 166 + static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) 167 + { 168 + int err, ret; 169 + 170 + ret = -EIO; 171 + err = zlib_inflateInit(&stream); 172 + if (err != Z_OK) 173 + goto error; 174 + 175 + stream.next_in = in; 176 + stream.avail_in = inlen; 177 + stream.total_in = 0; 178 + stream.next_out = out; 179 + stream.avail_out = outlen; 180 + stream.total_out = 0; 181 + 182 + err = zlib_inflate(&stream, Z_FINISH); 183 + if (err != Z_STREAM_END) 184 + goto error; 185 + 186 + err = zlib_inflateEnd(&stream); 187 + if (err != Z_OK) 188 + goto error; 189 + 190 + ret = stream.total_out; 191 + error: 192 + return ret; 193 + } 194 + 165 195 static void allocate_buf_for_compression(void) 166 196 { 167 197 size_t size; ··· 459 429 struct timespec time; 460 430 int failed = 0, rc; 461 431 bool compressed; 432 + int unzipped_len = -1; 462 433 463 434 if (!psi) 464 435 return; ··· 470 439 471 440 while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, 472 441 psi)) > 0) { 442 + if (compressed && (type == PSTORE_TYPE_DMESG)) { 443 + if (big_oops_buf) 444 + unzipped_len = pstore_decompress(buf, 445 + big_oops_buf, size, 446 + big_oops_buf_sz); 447 + 448 + if (unzipped_len > 0) { 449 + buf = big_oops_buf; 450 + size = unzipped_len; 451 + } else { 452 + pr_err("pstore: decompression failed;" 453 + "returned %d\n", unzipped_len); 454 + } 455 + } 473 456 rc = pstore_mkfile(type, psi->name, id, count, buf, 474 457 (size_t)size, time, psi); 475 - kfree(buf); 476 - buf = NULL; 458 + if (unzipped_len < 0) { 459 + /* Free buffer other than big oops */ 460 + kfree(buf); 461 + buf = NULL; 462 + } else 463 + unzipped_len = -1; 477 464 if (rc && (rc != -EEXIST || !quiet)) 478 465 failed++; 479 466 }