[PATCH 4/5] pstore: Refactor compression initialization

From: Kees Cook
Date: Mon Oct 17 2022 - 22:09:21 EST


In preparation for calling zstd library compression routines, split the
crypto-specific initialization into a separate init routine.

Cc: Tony Luck <tony.luck@xxxxxxxxx>
Cc: "Guilherme G. Piccoli" <gpiccoli@xxxxxxxxxx>
Cc: linux-hardening@xxxxxxxxxxxxxxx
Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
---
fs/pstore/platform.c | 71 +++++++++++++++++++++++++++-----------------
1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 210a4224edb4..4d883dc2e8a7 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -178,48 +178,29 @@ static int pstore_compress(const void *in, void *out,
return -EINVAL;
}

-static void allocate_buf_for_compression(void)
+static int allocate_crypto_buf(void)
{
struct crypto_comp *ctx;
- int size;
- char *buf;

- /* Skip if not built-in or compression backend not selected yet. */
- if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !compress)
- return;
-
- /* Skip if no pstore backend yet or compression init already done. */
- if (!psinfo || tfm)
- return;
+ /* Skip if compression init already done. */
+ if (tfm)
+ return 0;

if (!crypto_has_comp(compress, 0, 0)) {
pr_err("Unknown compression: %s\n", compress);
- return;
- }
-
- /* Worst-case compression should never be more than uncompressed. */
- size = psinfo->bufsize;
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf) {
- pr_err("Failed %d byte compression buffer allocation for: %s\n",
- size, compress);
- return;
+ return -EINVAL;
}

ctx = crypto_alloc_comp(compress, 0, 0);
if (IS_ERR_OR_NULL(ctx)) {
- kfree(buf);
pr_err("crypto_alloc_comp('%s') failed: %ld\n", compress,
PTR_ERR(ctx));
- return;
+ return -ENOMEM;
}
-
- /* A non-NULL big_oops_buf indicates compression is available. */
tfm = ctx;
- big_oops_buf_sz = size;
- big_oops_buf = buf;

- pr_info("Using crash dump compression: %s\n", compress);
+ pr_info("Using crash dump compression: crypto API %s\n", compress);
+ return 0;
}

static void free_buf_for_compression(void)
@@ -233,6 +214,38 @@ static void free_buf_for_compression(void)
big_oops_buf_sz = 0;
}

+static void allocate_buf_for_compression(void)
+{
+ char *buf;
+ int rc;
+
+ /* Skip if not built-in or compression backend not selected yet. */
+ if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !compress)
+ return;
+
+ /* Skip if no pstore backend yet. */
+ if (!psinfo)
+ return;
+
+ /* Initialize compression routines. */
+ rc = allocate_crypto_buf();
+ if (rc)
+ goto fail;
+
+ /* Create common buffer for compression work. */
+ buf = kmalloc(psinfo->bufsize, GFP_KERNEL);
+ if (!buf)
+ goto fail;
+
+ /* A non-NULL big_oops_buf indicates compression is available. */
+ big_oops_buf_sz = psinfo->bufsize;
+ big_oops_buf = buf;
+ return;
+
+fail:
+ free_buf_for_compression();
+}
+
/*
* Called when compression fails, since the printk buffer
* would be fetched for compression calling it again when
@@ -589,6 +602,7 @@ static void decompress_record(struct pstore_record *record)
{
size_t unzipped_len;
char *unzipped, *workspace;
+ int rc;

if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !record->compressed)
return;
@@ -612,7 +626,8 @@ static void decompress_record(struct pstore_record *record)
if (!workspace)
return;

- if (pstore_decompress_crypto(record, workspace, &unzipped_len) != 0) {
+ rc = pstore_decompress_crypto(record, workspace, &unzipped_len);
+ if (rc) {
kfree(workspace);
return;
}
--
2.34.1