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:
Jan Beulich committed 2013-10-07 09:42:51 +02:00
1 parent e850049bbc
commit 84f04d8f0d
4 files changed
+157 -1

No files matched your search

+1
View File
@@ -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
+12 -1
View File
@@ -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,
+8
View File
@@ -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);
+136
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.