[PATCH 2/5] pstore: Allow for arbitrary compression algorithm

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


Since there is no longer a need for figuring out worst-case compression
size, there is no reason to limit the compression algorithm choice.
Greatly simplifies Kconfig.

Cc: Tony Luck <tony.luck@xxxxxxxxx>
Cc: "Guilherme G. Piccoli" <gpiccoli@xxxxxxxxxx>
Cc: Nick Terrell <terrelln@xxxxxx>
Cc: linux-hardening@xxxxxxxxxxxxxxx
Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
---
fs/pstore/Kconfig | 122 ++++++++++++-------------------------------
fs/pstore/platform.c | 39 ++++++--------
2 files changed, 47 insertions(+), 114 deletions(-)

diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
index 8adabde685f1..a95b3981cb0e 100644
--- a/fs/pstore/Kconfig
+++ b/fs/pstore/Kconfig
@@ -22,99 +22,41 @@ config PSTORE_DEFAULT_KMSG_BYTES
Defines default size of pstore kernel log storage.
Can be enlarged if needed, not recommended to shrink it.

-config PSTORE_DEFLATE_COMPRESS
- tristate "DEFLATE (ZLIB) compression"
- default y
- depends on PSTORE
- select CRYPTO_DEFLATE
- help
- This option enables DEFLATE (also known as ZLIB) compression
- algorithm support.
-
-config PSTORE_LZO_COMPRESS
- tristate "LZO compression"
- depends on PSTORE
- select CRYPTO_LZO
- help
- This option enables LZO compression algorithm support.
-
-config PSTORE_LZ4_COMPRESS
- tristate "LZ4 compression"
- depends on PSTORE
- select CRYPTO_LZ4
- help
- This option enables LZ4 compression algorithm support.
-
-config PSTORE_LZ4HC_COMPRESS
- tristate "LZ4HC compression"
- depends on PSTORE
- select CRYPTO_LZ4HC
- help
- This option enables LZ4HC (high compression) mode algorithm.
-
-config PSTORE_842_COMPRESS
- bool "842 compression"
- depends on PSTORE
- select CRYPTO_842
- help
- This option enables 842 compression algorithm support.
-
-config PSTORE_ZSTD_COMPRESS
- bool "zstd compression"
- depends on PSTORE
- select CRYPTO_ZSTD
- help
- This option enables zstd compression algorithm support.
-
-config PSTORE_COMPRESS
- def_bool y
- depends on PSTORE
- depends on PSTORE_DEFLATE_COMPRESS || PSTORE_LZO_COMPRESS || \
- PSTORE_LZ4_COMPRESS || PSTORE_LZ4HC_COMPRESS || \
- PSTORE_842_COMPRESS || PSTORE_ZSTD_COMPRESS
-
choice
- prompt "Default pstore compression algorithm"
- depends on PSTORE_COMPRESS
- help
- This option chooses the default active compression algorithm.
- This change be changed at boot with "pstore.compress=..." on
- the kernel command line.
-
- Currently, pstore has support for 6 compression algorithms:
- deflate, lzo, lz4, lz4hc, 842 and zstd.
-
- The default compression algorithm is deflate.
-
- config PSTORE_DEFLATE_COMPRESS_DEFAULT
- bool "deflate" if PSTORE_DEFLATE_COMPRESS
-
- config PSTORE_LZO_COMPRESS_DEFAULT
- bool "lzo" if PSTORE_LZO_COMPRESS
-
- config PSTORE_LZ4_COMPRESS_DEFAULT
- bool "lz4" if PSTORE_LZ4_COMPRESS
-
- config PSTORE_LZ4HC_COMPRESS_DEFAULT
- bool "lz4hc" if PSTORE_LZ4HC_COMPRESS
-
- config PSTORE_842_COMPRESS_DEFAULT
- bool "842" if PSTORE_842_COMPRESS
-
- config PSTORE_ZSTD_COMPRESS_DEFAULT
- bool "zstd" if PSTORE_ZSTD_COMPRESS
-
+ prompt "Panic dump compression"
+ depends on PSTORE
+ default PSTORE_COMPRESS_CRYPTO
+ help
+ Choose whether and how to compress the panic dump output. This
+ is usually only needed for very storage-constrained backends.
+
+ config PSTORE_COMPRESS_CRYPTO
+ bool "Use an arbitrary compression algorithm via the Crypto API"
+ help
+ If the default compression algorithm from PSTORE_COMPRESS
+ is not desired, an arbitrary one can be chosen if it is
+ available to from the Crypto API. Note that this may reserve
+ non-trivial amounts of per-CPU memory.
+
+ config PSTORE_COMPRESS_NONE
+ bool "Do not compress panic dumps"
+ help
+ Do not compress the panic dump output. This leave the
+ output easily readable in memory, if non-pstore forensics
+ tools want to examine the contents easily.
endchoice

-config PSTORE_COMPRESS_DEFAULT
- string
- depends on PSTORE_COMPRESS
- default "deflate" if PSTORE_DEFLATE_COMPRESS_DEFAULT
- default "lzo" if PSTORE_LZO_COMPRESS_DEFAULT
- default "lz4" if PSTORE_LZ4_COMPRESS_DEFAULT
- default "lz4hc" if PSTORE_LZ4HC_COMPRESS_DEFAULT
- default "842" if PSTORE_842_COMPRESS_DEFAULT
- default "zstd" if PSTORE_ZSTD_COMPRESS_DEFAULT
+config PSTORE_COMPRESS_CRYPTO_DEFAULT
+ string "Crypto API compression algorithm"
+ depends on PSTORE_COMPRESS_CRYPTO
+ default "zstd"
+ help
+ This option chooses the default active compression algorithm,
+ and can be changed at boot with "pstore.compress=..." on the
+ kernel command line. The chosen compression algorithm needs to
+ be available to the crypto subsystem for it to be usable by
+ pstore. For example, "zstd" needs CONFIG_CRYPTO_ZSTD, "deflate"
+ needs CONFIG_CRYPTO_DEFLATE, etc.

config PSTORE_CONSOLE
bool "Log kernel console messages"
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index ef0bc3ae161b..1f01c4b904fc 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -16,15 +16,6 @@
#include <linux/console.h>
#include <linux/module.h>
#include <linux/pstore.h>
-#if IS_ENABLED(CONFIG_PSTORE_LZO_COMPRESS)
-#include <linux/lzo.h>
-#endif
-#if IS_ENABLED(CONFIG_PSTORE_LZ4_COMPRESS) || IS_ENABLED(CONFIG_PSTORE_LZ4HC_COMPRESS)
-#include <linux/lz4.h>
-#endif
-#if IS_ENABLED(CONFIG_PSTORE_ZSTD_COMPRESS)
-#include <linux/zstd.h>
-#endif
#include <linux/crypto.h>
#include <linux/string.h>
#include <linux/timer.h>
@@ -80,9 +71,9 @@ static char *backend;
module_param(backend, charp, 0444);
MODULE_PARM_DESC(backend, "specific backend to use");

-static char *compress =
-#ifdef CONFIG_PSTORE_COMPRESS_DEFAULT
- CONFIG_PSTORE_COMPRESS_DEFAULT;
+static char *compress __ro_after_init =
+#ifdef CONFIG_PSTORE_COMPRESS_CRYPTO_DEFAULT
+ CONFIG_PSTORE_COMPRESS_CRYPTO_DEFAULT;
#else
NULL;
#endif
@@ -166,18 +157,18 @@ static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
static int pstore_compress(const void *in, void *out,
unsigned int inlen, unsigned int outlen)
{
- int ret;
+ if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_CRYPTO)) {
+ int ret;

- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS))
- return -EINVAL;
-
- ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
- if (ret) {
- pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
- return ret;
+ ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
+ if (ret) {
+ pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
+ return ret;
+ }
+ return outlen;
}

- return outlen;
+ return -EINVAL;
}

static void allocate_buf_for_compression(void)
@@ -187,7 +178,7 @@ static void allocate_buf_for_compression(void)
char *buf;

/* Skip if not built-in or compression backend not selected yet. */
- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !compress)
+ if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !compress)
return;

/* Skip if no pstore backend yet or compression init already done. */
@@ -226,7 +217,7 @@ static void allocate_buf_for_compression(void)

static void free_buf_for_compression(void)
{
- if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) {
+ if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_CRYPTO) && tfm) {
crypto_free_comp(tfm);
tfm = NULL;
}
@@ -578,7 +569,7 @@ static void decompress_record(struct pstore_record *record)
int unzipped_len;
char *unzipped, *workspace;

- if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed)
+ if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !record->compressed)
return;

/* Only PSTORE_TYPE_DMESG support compression. */
--
2.34.1