libpayload: cbfs: Require input size and output size for cbfs_decompress

Currently, cbfs_decompress() calls ulzma() and ulz4f() for LZMA/LZ4
decompression. These two functions don't accept input/output size as
parameters. We can make cbfs_decompress more robust by calling ulzman()
and ulz4fn() instead. This could prevent us from overflowing destination
buffer.

BUG=none
BRANCH=none
TEST=boot into kernel on Kukui with COMPRESSED_PAYLOAD_LZMA /
     COMPRESSED_PAYLOAD_LZ4.

Change-Id: Ibe617825bd000ed618791d8e3c5f65bbbd5f7e33
Signed-off-by: You-Cheng Syu <youcheng@google.com>
Reviewed-on: https://review.coreboot.org/c/31606
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
You-Cheng Syu 2019-02-27 15:29:15 +08:00 committed by Patrick Georgi
parent 08087a3e8a
commit 5ec1d24974
3 changed files with 17 additions and 10 deletions

View File

@ -253,8 +253,9 @@ struct cbfs_media {
void *cbfs_get_file_content(struct cbfs_media *media, const char *name, void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
int type, size_t *sz); int type, size_t *sz);
/* returns decompressed size on success, 0 on failure */ /* Returns decompressed size on success, 0 on failure. */
int cbfs_decompress(int algo, void *src, void *dst, int len); size_t cbfs_decompress(int algo, const void *src, size_t srcn, void *dst,
size_t dstn);
/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS /* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS
* on failure */ * on failure */

View File

@ -114,8 +114,9 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
final_size = cbfs_decompress(stage->compression, final_size = cbfs_decompress(stage->compression,
((unsigned char *) stage) + ((unsigned char *) stage) +
sizeof(struct cbfs_stage), sizeof(struct cbfs_stage),
stage->len,
(void *) (uintptr_t) stage->load, (void *) (uintptr_t) stage->load,
stage->len); stage->memlen);
if (!final_size) { if (!final_size) {
entry = -1; entry = -1;
goto out; goto out;

View File

@ -48,6 +48,7 @@
* *
*/ */
#include <libpayload.h>
#include <cbfs.h> #include <cbfs.h>
#include <string.h> #include <string.h>
#include <sysinfo.h> #include <sysinfo.h>
@ -256,7 +257,8 @@ void *cbfs_get_contents(struct cbfs_handle *handle, size_t *size, size_t limit)
return NULL; return NULL;
ret = malloc(*size); ret = malloc(*size);
if (ret != NULL && !cbfs_decompress(algo, data, ret, *size)) { if (ret != NULL &&
!cbfs_decompress(algo, data, on_media_size, ret, *size)) {
free(ret); free(ret);
ret = NULL; ret = NULL;
} }
@ -321,24 +323,27 @@ void *cbfs_get_attr(struct cbfs_handle *handle, uint32_t tag)
return NULL; return NULL;
} }
int cbfs_decompress(int algo, void *src, void *dst, int len) size_t cbfs_decompress(int algo, const void *src, size_t srcn, void *dst,
size_t dstn)
{ {
size_t len;
switch (algo) { switch (algo) {
case CBFS_COMPRESS_NONE: case CBFS_COMPRESS_NONE:
len = MIN(srcn, dstn);
memcpy(dst, src, len); memcpy(dst, src, len);
return len; return len;
#ifdef CBFS_CORE_WITH_LZMA #ifdef CBFS_CORE_WITH_LZMA
case CBFS_COMPRESS_LZMA: case CBFS_COMPRESS_LZMA:
return ulzma(src, dst); return ulzman(src, srcn, dst, dstn);
#endif #endif
#ifdef CBFS_CORE_WITH_LZ4 #ifdef CBFS_CORE_WITH_LZ4
case CBFS_COMPRESS_LZ4: case CBFS_COMPRESS_LZ4:
return ulz4f(src, dst); return ulz4fn(src, srcn, dst, dstn);
#endif #endif
default: default:
ERROR("tried to decompress %d bytes with algorithm #%x," ERROR("tried to decompress %zu bytes with algorithm "
"but that algorithm id is unsupported.\n", len, "#%x, but that algorithm id is unsupported.\n",
algo); srcn, algo);
return 0; return 0;
} }
} }