mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libxc: add LZ4 decompression support
Since there's no shared or static library to link against, this simply re-uses the hypervisor side code. However, I only audited the code added here for possible security issues, not the referenced code in the hypervisor tree. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
e850049bbc
commit
84f04d8f0d
4 files changed
+157
-1
No files matched your search
@@ -63,6 +63,7 @@ $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
|
||||
GUEST_SRCS-y += xc_dom_core.c xc_dom_boot.c
|
||||
GUEST_SRCS-y += xc_dom_elfloader.c
|
||||
GUEST_SRCS-$(CONFIG_X86) += xc_dom_bzimageloader.c
|
||||
GUEST_SRCS-$(CONFIG_X86) += xc_dom_decompress_lz4.c
|
||||
GUEST_SRCS-$(CONFIG_ARM) += xc_dom_armzimageloader.c
|
||||
GUEST_SRCS-y += xc_dom_binloader.c
|
||||
GUEST_SRCS-y += xc_dom_compat_linux.c
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "xg_private.h"
|
||||
#include "xc_dom.h"
|
||||
#include "xc_dom_decompress.h"
|
||||
|
||||
#ifndef __MINIOS__
|
||||
|
||||
@@ -733,6 +733,17 @@ static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else if ( check_magic(dom, "\x02\x21", 2) )
|
||||
{
|
||||
ret = xc_try_lz4_decode(dom, &dom->kernel_blob, &dom->kernel_size);
|
||||
if ( ret < 0 )
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
"%s unable to LZ4 decompress kernel\n",
|
||||
__FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xc_dom_panic(dom->xch, XC_INVALID_KERNEL,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __MINIOS__
|
||||
# include "xc_dom.h"
|
||||
#else
|
||||
# include "xc_dom_decompress_unsafe.h"
|
||||
#endif
|
||||
|
||||
int xc_try_lz4_decode(struct xc_dom_image *dom, void **blob, size_t *size);
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xg_private.h"
|
||||
#include "xc_dom_decompress.h"
|
||||
|
||||
#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#define likely(a) a
|
||||
#define unlikely(a) a
|
||||
|
||||
static inline uint_fast16_t le16_to_cpup(const unsigned char *buf)
|
||||
{
|
||||
return buf[0] | (buf[1] << 8);
|
||||
}
|
||||
|
||||
static inline uint_fast32_t le32_to_cpup(const unsigned char *buf)
|
||||
{
|
||||
return le16_to_cpup(buf) | ((uint32_t)le16_to_cpup(buf + 2) << 16);
|
||||
}
|
||||
|
||||
#include "../../xen/include/xen/lz4.h"
|
||||
#include "../../xen/common/decompress.h"
|
||||
|
||||
#ifndef __MINIOS__
|
||||
|
||||
#include "../../xen/common/lz4/decompress.c"
|
||||
|
||||
#define ARCHIVE_MAGICNUMBER 0x184C2102
|
||||
|
||||
int xc_try_lz4_decode(
|
||||
struct xc_dom_image *dom, void **blob, size_t *psize)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned char *inp = *blob, *output, *outp;
|
||||
ssize_t size = *psize - 4;
|
||||
size_t out_len, dest_len, chunksize;
|
||||
const char *msg;
|
||||
|
||||
if (size < 4) {
|
||||
msg = "input too small";
|
||||
goto exit_0;
|
||||
}
|
||||
|
||||
out_len = get_unaligned_le32(inp + size);
|
||||
if (xc_dom_kernel_check_size(dom, out_len)) {
|
||||
msg = "Decompressed image too large";
|
||||
goto exit_0;
|
||||
}
|
||||
|
||||
output = malloc(out_len);
|
||||
if (!output) {
|
||||
msg = "Could not allocate output buffer";
|
||||
goto exit_0;
|
||||
}
|
||||
outp = output;
|
||||
|
||||
chunksize = get_unaligned_le32(inp);
|
||||
if (chunksize == ARCHIVE_MAGICNUMBER) {
|
||||
inp += 4;
|
||||
size -= 4;
|
||||
} else {
|
||||
msg = "invalid header";
|
||||
goto exit_2;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (size < 4) {
|
||||
msg = "missing data";
|
||||
goto exit_2;
|
||||
}
|
||||
chunksize = get_unaligned_le32(inp);
|
||||
if (chunksize == ARCHIVE_MAGICNUMBER) {
|
||||
inp += 4;
|
||||
size -= 4;
|
||||
continue;
|
||||
}
|
||||
inp += 4;
|
||||
size -= 4;
|
||||
if (chunksize > size) {
|
||||
msg = "insufficient input data";
|
||||
goto exit_2;
|
||||
}
|
||||
|
||||
dest_len = out_len - (outp - output);
|
||||
ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp,
|
||||
&dest_len);
|
||||
if (ret < 0) {
|
||||
msg = "decoding failed";
|
||||
goto exit_2;
|
||||
}
|
||||
|
||||
outp += dest_len;
|
||||
size -= chunksize;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
*blob = output;
|
||||
*psize = out_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
msg = "data corrupted";
|
||||
goto exit_2;
|
||||
}
|
||||
|
||||
inp += chunksize;
|
||||
}
|
||||
|
||||
exit_2:
|
||||
free(output);
|
||||
exit_0:
|
||||
DOMPRINTF("LZ4 decompression error: %s\n", msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* __MINIOS__ */
|
||||
|
||||
#include "../../xen/common/unlz4.c"
|
||||
|
||||
int xc_try_lz4_decode(
|
||||
struct xc_dom_image *dom, void **blob, size_t *size)
|
||||
{
|
||||
return xc_dom_decompress_unsafe(unlz4, dom, blob, size);
|
||||
}
|
||||
|
||||
#endif
|
||||