]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
libxc: Add unsafe decompressors
authorBastian Blank <bastian@waldi.eu.org>
Thu, 18 Apr 2013 11:49:54 +0000 (12:49 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Mon, 22 Apr 2013 11:46:30 +0000 (12:46 +0100)
Add decompressors based on hypervisor code.  This are used in mini-os by
pv-grub.

This enables pv-grub to boot kernels compressed with e.g. xz, which are
becoming more common.

Signed-off-by: Bastian Blank <waldi@debian.org>
Adjusted to use terminology "unsafe" rather than "trusted" to indicate
that the user had better sanitise the data (or not care, as in stub
domains) as suggested by Tim Deegan. This was effectively a sed script.

Minimise the changes to hypervisor code by moving the "compat layer" into the
relevant libxc source files (which include the Xen ones).

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
14 files changed:
stubdom/Makefile
tools/libxc/Makefile
tools/libxc/xc_dom_bzimageloader.c
tools/libxc/xc_dom_decompress_unsafe.c [new file with mode: 0644]
tools/libxc/xc_dom_decompress_unsafe.h [new file with mode: 0644]
tools/libxc/xc_dom_decompress_unsafe_bzip2.c [new file with mode: 0644]
tools/libxc/xc_dom_decompress_unsafe_lzma.c [new file with mode: 0644]
tools/libxc/xc_dom_decompress_unsafe_lzo1x.c [new file with mode: 0644]
tools/libxc/xc_dom_decompress_unsafe_xz.c [new file with mode: 0644]
xen/common/decompress.h
xen/common/lzo.c
xen/common/unlzma.c
xen/common/unlzo.c
xen/common/xz/private.h

index 427e4d66e8e089e6841cbff8f737b91417f04254..a2ac04483363878f885d99b63a8e1b15668416ac 100644 (file)
@@ -331,7 +331,7 @@ $(TARGETS_MINIOS): mini-os-%:
 .PHONY: libxc
 libxc: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a libxc-$(XEN_TARGET_ARCH)/libxenguest.a
 libxc-$(XEN_TARGET_ARCH)/libxenctrl.a: cross-zlib
-       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= -C libxc-$(XEN_TARGET_ARCH)
+       CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) DESTDIR= CONFIG_LIBXC_MINIOS=y -C libxc-$(XEN_TARGET_ARCH)
 
  libxc-$(XEN_TARGET_ARCH)/libxenguest.a: libxc-$(XEN_TARGET_ARCH)/libxenctrl.a
 
index d44abf92c64c248c830adaa21154d8e2b52a0f81..640e333d9c843a7bc8137c95c533a75437ece0a9 100644 (file)
@@ -68,6 +68,14 @@ GUEST_SRCS-$(CONFIG_X86)     += xc_hvm_build_x86.c
 GUEST_SRCS-$(CONFIG_ARM)     += xc_dom_arm.c
 GUEST_SRCS-$(CONFIG_ARM)     += xc_hvm_build_arm.c
 
+ifeq ($(CONFIG_LIBXC_MINIOS),y)
+GUEST_SRCS-y                 += xc_dom_decompress_unsafe.c
+GUEST_SRCS-y                 += xc_dom_decompress_unsafe_bzip2.c
+GUEST_SRCS-y                 += xc_dom_decompress_unsafe_lzma.c
+GUEST_SRCS-y                 += xc_dom_decompress_unsafe_lzo1x.c
+GUEST_SRCS-y                 += xc_dom_decompress_unsafe_xz.c
+endif
+
 OSDEP_SRCS-y                 += xenctrl_osdep_ENOSYS.c
 
 -include $(XEN_TARGET_ARCH)/Makefile
index 6daa78ce2ac73ce931d141cb53741666bca04711..3870c6d5f5b152669efd8a7b25767bd3c5601c8e 100644 (file)
@@ -35,6 +35,8 @@
 #include "xg_private.h"
 #include "xc_dom.h"
 
+#ifndef __MINIOS__
+
 #if defined(HAVE_BZLIB)
 
 #include <bzlib.h>
@@ -562,6 +564,15 @@ static int xc_try_lzo1x_decode(
 
 #endif
 
+#else /* __MINIOS__ */
+
+int xc_try_bzip2_decode(struct xc_dom_image *dom, void **blob, size_t *size);
+int xc_try_lzma_decode(struct xc_dom_image *dom, void **blob, size_t *size);
+int xc_try_lzo1x_decode(struct xc_dom_image *dom, void **blob, size_t *size);
+int xc_try_xz_decode(struct xc_dom_image *dom, void **blob, size_t *size);
+
+#endif /* !__MINIOS__ */
+
 struct setup_header {
     uint8_t  _pad0[0x1f1];  /* skip uninteresting stuff */
     uint8_t  setup_sects;
diff --git a/tools/libxc/xc_dom_decompress_unsafe.c b/tools/libxc/xc_dom_decompress_unsafe.c
new file mode 100644 (file)
index 0000000..164e355
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xc_dom_decompress_unsafe.h"
+
+static struct xc_dom_image *unsafe_dom;
+static unsigned char *output_blob;
+static unsigned int output_size;
+
+static void unsafe_error(const char *msg)
+{
+    xc_dom_panic(unsafe_dom->xch, XC_INVALID_KERNEL, "%s", msg);
+}
+
+static int unsafe_flush(void *src, unsigned int size)
+{
+    void *n = realloc(output_blob, output_size + size);
+    if (!n)
+        return -1;
+    output_blob = n;
+
+    memcpy(&output_blob[output_size], src, size);
+    output_size += size;
+    return size;
+}
+
+int xc_dom_decompress_unsafe(
+    decompress_fn fn, struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    int ret;
+
+    unsafe_dom = dom;
+    output_blob = NULL;
+    output_size = 0;
+
+    ret = fn(dom->kernel_blob, dom->kernel_size, NULL, unsafe_flush, NULL, NULL, unsafe_error);
+
+    if (ret)
+        free(output_blob);
+    else {
+        *blob = output_blob;
+        *size = output_size;
+    }
+
+    return ret;
+}
diff --git a/tools/libxc/xc_dom_decompress_unsafe.h b/tools/libxc/xc_dom_decompress_unsafe.h
new file mode 100644 (file)
index 0000000..64f6886
--- /dev/null
@@ -0,0 +1,20 @@
+#include "xc_dom.h"
+
+typedef int decompress_fn(unsigned char *inbuf, unsigned int len,
+                          int (*fill)(void*, unsigned int),
+                          int (*flush)(void*, unsigned int),
+                          unsigned char *outbuf, unsigned int *posp,
+                          void (*error)(const char *x));
+
+int xc_dom_decompress_unsafe(
+    decompress_fn fn, struct xc_dom_image *dom, void **blob, size_t *size)
+    __attribute__((visibility("internal")));
+
+int xc_try_bzip2_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+    __attribute__((visibility("internal")));
+int xc_try_lzma_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+    __attribute__((visibility("internal")));
+int xc_try_lzo1x_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+    __attribute__((visibility("internal")));
+int xc_try_xz_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+    __attribute__((visibility("internal")));
diff --git a/tools/libxc/xc_dom_decompress_unsafe_bzip2.c b/tools/libxc/xc_dom_decompress_unsafe_bzip2.c
new file mode 100644 (file)
index 0000000..4dcabe4
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xc_dom_decompress_unsafe.h"
+
+#include "../../xen/common/bunzip2.c"
+
+int xc_try_bzip2_decode(
+    struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    return xc_dom_decompress_unsafe(bunzip2, dom, blob, size);
+}
diff --git a/tools/libxc/xc_dom_decompress_unsafe_lzma.c b/tools/libxc/xc_dom_decompress_unsafe_lzma.c
new file mode 100644 (file)
index 0000000..4ee8cdb
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xc_dom_decompress_unsafe.h"
+
+#include "../../xen/common/unlzma.c"
+
+int xc_try_lzma_decode(
+    struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    return xc_dom_decompress_unsafe(unlzma, dom, blob, size);
+}
diff --git a/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c b/tools/libxc/xc_dom_decompress_unsafe_lzo1x.c
new file mode 100644 (file)
index 0000000..57c73e3
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <endian.h>
+#include <stdint.h>
+
+#include "xg_private.h"
+#include "xc_dom_decompress_unsafe.h"
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef uint16_t u16;
+
+#define likely(a) a
+#define noinline
+#define unlikely(a) a
+
+static inline u16 be16_to_cpup(const u16 *p)
+{
+       u16 v = *p;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       return (((v & 0x00ffU) << 8) |
+                ((v & 0xff00U) >> 8));
+#else
+       return v;
+#endif
+}
+
+static inline u32 be32_to_cpup(const u32 *p)
+{
+       u32 v = *p;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       return (((v & 0x000000ffUL) << 24) |
+                ((v & 0x0000ff00UL) <<  8) |
+                ((v & 0x00ff0000UL) >>  8) |
+                ((v & 0xff000000UL) >> 24));
+#else
+       return v;
+#endif
+}
+
+#include "../../xen/common/lzo.c"
+#include "../../xen/common/unlzo.c"
+
+int xc_try_lzo1x_decode(
+    struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    return xc_dom_decompress_unsafe(unlzo, dom, blob, size);
+}
diff --git a/tools/libxc/xc_dom_decompress_unsafe_xz.c b/tools/libxc/xc_dom_decompress_unsafe_xz.c
new file mode 100644 (file)
index 0000000..2a32d40
--- /dev/null
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <endian.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "xg_private.h"
+#include "xc_dom_decompress_unsafe.h"
+
+// TODO
+#define XZ_DEC_X86
+
+typedef char bool_t;
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint32_t __le32;
+
+static inline u32 cpu_to_le32(const u32 v)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+       return (((v & 0x000000ffUL) << 24) |
+               ((v & 0x0000ff00UL) <<  8) |
+               ((v & 0x00ff0000UL) >>  8) |
+               ((v & 0xff000000UL) >> 24));
+#else
+       return v;
+#endif
+}
+
+static inline u32 le32_to_cpup(const u32 *p)
+{
+       return cpu_to_le32(*p);
+}
+
+#define min(x,y) ({ \
+        const typeof(x) _x = (x);       \
+        const typeof(y) _y = (y);       \
+        (void) (&_x == &_y);            \
+        _x < _y ? _x : _y; })
+
+#define min_t(type,x,y) \
+        ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#define max_t(type,x,y) \
+        ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+
+#define __force
+#define always_inline
+
+#include "../../xen/common/unxz.c"
+
+int xc_try_xz_decode(
+    struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    return xc_dom_decompress_unsafe(unxz, dom, blob, size);
+}
index bd62b5dc748d24cf38a3f4a96b3c07725aa171f7..61e83e518aa55c13f21fb7acd9ff8c74f60411ff 100644 (file)
@@ -1,3 +1,5 @@
+#ifdef __XEN__
+
 #include <xen/config.h>
 #include <xen/cache.h>
 #include <xen/decompress.h>
 
 #define large_malloc xmalloc_bytes
 #define large_free xfree
+
+#else
+
+#define STATIC static
+#define INIT
+#define INITDATA
+
+#define large_malloc malloc
+#define large_free free
+
+#endif
index eeb200b281f7ef0e5c95bdc324a00e21d26d2246..f1213d2dbee3c0e6dbc367bb51141fe30d303e9d 100644 (file)
  *  Richard Purdie <rpurdie@openedhand.com>
  */
 
+#ifdef __XEN__
 #include <xen/types.h>
+#endif
+
 #include <xen/lzo.h>
 #define get_unaligned(_p) (*(_p))
 #define put_unaligned(_val,_p) (*(_p)=_val)
index 719fd0d5c859b3af9f5177e76e70e75a746ee811..4d043308f97e0f301f5d0fd2ed78bbf01a1dc713 100644 (file)
@@ -54,7 +54,9 @@ static long long INIT read_int(unsigned char *ptr, int size)
  * Copyright (c) 1999-2005  Igor Pavlov
  */
 
+#ifdef __XEN__
 #include <xen/compiler.h>
+#endif
 
 #define LZMA_IOBUF_SIZE        0x10000
 
index 57d16f3ccae340818012c1dd67208a0f566bc0ca..fc794b05382e7a0e27ea1e76c4a6b84afdbfd735 100644 (file)
 
 #include "decompress.h"
 #include <xen/lzo.h>
+
+#ifdef __XEN__
 #include <asm/byteorder.h>
+#endif
 
 #if 1 /* ndef CONFIG_??? */
 static inline u16 INIT get_unaligned_be16(void *p)
index 369bcb3d4adb55b428e35d215e8eae20ea57a642..7ea24892297fc1c5702e851f23f18296ed7c34ee 100644 (file)
 #ifndef XZ_PRIVATE_H
 #define XZ_PRIVATE_H
 
+#ifdef __XEN__
 #include <xen/kernel.h>
 #include <asm/byteorder.h>
+#endif
+
 #define get_le32(p) le32_to_cpup((const uint32_t *)(p))
 
 #if 1 /* ndef CONFIG_??? */