In preparation for adding direct library calls for zstd, refactor
routines to use normalized compress/decompression type widths of size_t.
Cc: Tony Luck <tony.luck@intel.com>
Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
Cc: linux-hardening@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
fs/pstore/platform.c | 47 ++++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 15 deletions(-)
@@ -155,17 +155,24 @@ 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)
+ size_t inlen, size_t *outlen)
{
if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_CRYPTO)) {
+ unsigned int crypto_outlen;
int ret;
- ret = crypto_comp_compress(tfm, in, inlen, out, &outlen);
+ if (inlen > UINT_MAX || *outlen > UINT_MAX)
+ return -EINVAL;
+
+ crypto_outlen = *outlen;
+ ret = crypto_comp_compress(tfm, in, inlen, out, &crypto_outlen);
if (ret) {
pr_err("crypto_comp_compress failed, ret = %d!\n", ret);
return ret;
}
- return outlen;
+
+ *outlen = crypto_outlen;
+ return 0;
}
return -EINVAL;
@@ -297,7 +304,6 @@ static void pstore_dump(struct kmsg_dumper *dumper,
char *dst;
size_t dst_size;
int header_size;
- int zipped_len = -1;
size_t dump_size;
struct pstore_record record;
@@ -327,11 +333,11 @@ static void pstore_dump(struct kmsg_dumper *dumper,
break;
if (big_oops_buf) {
- zipped_len = pstore_compress(dst, psinfo->buf,
- header_size + dump_size,
- psinfo->bufsize);
+ size_t zipped_len = psinfo->bufsize;
- if (zipped_len > 0) {
+ if (pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ &zipped_len) == 0) {
record.compressed = true;
record.size = zipped_len;
} else {
@@ -563,10 +569,25 @@ void pstore_unregister(struct pstore_info *psi)
}
EXPORT_SYMBOL_GPL(pstore_unregister);
-static void decompress_record(struct pstore_record *record)
+static int pstore_decompress_crypto(struct pstore_record *record, char *workspace, size_t *outlen)
{
+ unsigned int crypto_outlen = *outlen;
int ret;
- int unzipped_len;
+
+ ret = crypto_comp_decompress(tfm, record->buf, record->size,
+ workspace, &crypto_outlen);
+ if (ret) {
+ pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
+ return 0;
+ }
+
+ *outlen = crypto_outlen;
+ return 0;
+}
+
+static void decompress_record(struct pstore_record *record)
+{
+ size_t unzipped_len;
char *unzipped, *workspace;
if (IS_ENABLED(CONFIG_PSTORE_COMPRESS_NONE) || !record->compressed)
@@ -591,11 +612,7 @@ static void decompress_record(struct pstore_record *record)
if (!workspace)
return;
- /* After decompression "unzipped_len" is almost certainly smaller. */
- ret = crypto_comp_decompress(tfm, record->buf, record->size,
- workspace, &unzipped_len);
- if (ret) {
- pr_err("crypto_comp_decompress failed, ret = %d!\n", ret);
+ if (pstore_decompress_crypto(record, workspace, &unzipped_len) != 0) {
kfree(workspace);
return;
}