x86/xen_hello_world.xsplice: Test payload for patching 'xen_extra_version'.

This change demonstrates how to generate an xSplice ELF payload.

The idea here is that we want to patch in the hypervisor
the 'xen_version_extra' function with an function that will
return 'Hello World'. The 'xl info | grep extraversion'
will reflect the new value after the patching.

To generate this ELF payload file we need:
 - C code of the new code (xen_hello_world_func.c).
 - C code generating the .xsplice.funcs structure
   (xen_hello_world.c)
 - The address of the old code (xen_extra_version). We
   retrieve it by  using 'nm --defined' on xen-syms.
 - The size of the new and old code for which we use
   nm --defined -S on our code and xen-syms respectively.

There are two C files and one header files generated
during build. One could make this one C file if the
size of the newly patched function size was known in
advance (or an random value was choosen).

There is also a strict order of compiling:
 1) xen_hello_world_func.c
 2) config.h - extract the size of the new function,
    the old function and the old function address.
 3) xen_hello_world.c - which contains the .xsplice.funcs
    structure.
 4) Link the object files in an xen_hello_world.xsplice file.

The use-case is simple:

$xen-xsplice load /usr/lib/debug/xen_hello_world.xsplice
$xen-xsplice list
 ID                                     | status
----------------------------------------+------------
xen_hello_world                           APPLIED
$xl info | grep extra
xen_extra              : Hello World
$xen-xsplice revert xen_hello_world
Performing revert: completed
$xen-xsplice unload xen_hello_world
Performing unload: completed
$xl info | grep extra
xen_extra              : -unstable

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Julien Grall <julien.grall@arm.com> [ARM]
Acked-by: Jan Beulich <jbeulich@suse.com>
Release-acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
Konrad Rzeszutek Wilk committed 2016-04-29 03:58:32 -04:00
1 parent 29f4ab0b0a
commit ffcd7c0698
8 files changed
+148 -2

No files matched your search

+2
View File
@@ -246,6 +246,8 @@ xen/arch/x86/efi.lds
xen/arch/x86/efi/check.efi
xen/arch/x86/efi/disabled
xen/arch/x86/efi/mkreloc
xen/arch/x86/test/config.h
xen/arch/x86/test/xen_hello_world.xsplice
xen/arch/*/efi/boot.c
xen/arch/*/efi/compat.c
xen/arch/*/efi/efi.h
+37
View File
@@ -331,6 +331,43 @@ When reverting a patch, the hypervisor iterates over each `xsplice_patch_func`
and the core code copies the data from the undo buffer (private internal copy)
to `old_addr`.
### Example of .xsplice.funcs
A simple example of what a payload file can be:
<pre>
/* MUST be in sync with hypervisor. */
struct xsplice_patch_func {
const char *name;
void *new_addr;
void *old_addr;
uint32_t new_size;
uint32_t old_size;
uint8_t version;
uint8_t pad[31];
};
/* Our replacement function for xen_extra_version. */
const char *xen_hello_world(void)
{
return "Hello World";
}
static unsigned char patch_this_fnc[] = "xen_extra_version";
struct xsplice_patch_func xsplice_hello_world = {
.version = XSPLICE_PAYLOAD_VERSION,
.name = patch_this_fnc,
.new_addr = xen_hello_world,
.old_addr = (void *)0xffff82d08013963c, /* Extracted from xen-syms. */
.new_size = 13, /* To be be computed by scripts. */
.old_size = 13, /* -----------""--------------- */
} __attribute__((__section__(".xsplice.funcs")));
</pre>
Code must be compiled with -fPIC.
## Hypercalls
We will employ the sub operations of the system management hypercall (sysctl).
+6 -2
View File
@@ -39,8 +39,8 @@ dist: install
build install:: include/config/auto.conf
.PHONY: build install uninstall clean distclean cscope TAGS tags MAP gtags
build install uninstall debug clean distclean cscope TAGS tags MAP gtags::
.PHONY: build install uninstall clean distclean cscope TAGS tags MAP gtags tests
build install uninstall debug clean distclean cscope TAGS tags MAP gtags tests::
ifneq ($(XEN_TARGET_ARCH),x86_32)
$(MAKE) -f Rules.mk _$@
else
@@ -76,6 +76,10 @@ _install: $(TARGET)$(CONFIG_XEN_INSTALL_SUFFIX)
fi; \
fi
.PHONY: _tests
_tests:
$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) tests
.PHONY: _uninstall
_uninstall: D=$(DESTDIR)
_uninstall: T=$(notdir $(TARGET))
+3
View File
@@ -57,6 +57,9 @@ ifeq ($(CONFIG_ARM_64),y)
ln -sf $(notdir $@) ../../$(notdir $@).efi
endif
.PHONY: tests
tests:
$(TARGET).axf: $(TARGET)-syms
# XXX: VE model loads by VMA so instead of
# making a proper ELF we link with LMA == VMA and adjust crudely
+4
View File
@@ -76,6 +76,9 @@ $(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
`$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
.PHONY: tests
tests:
$(MAKE) -f $(BASEDIR)/Rules.mk -C test xsplice
ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(BASEDIR)/arch/x86/efi/built_in.o $(ALL_OBJS)
@@ -179,3 +182,4 @@ clean::
rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d
rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc
rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
$(MAKE) -f $(BASEDIR)/Rules.mk -C test clean
+42
View File
@@ -0,0 +1,42 @@
include $(XEN_ROOT)/Config.mk
CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
.PHONY: default
XSPLICE := xen_hello_world.xsplice
default: xsplice
install: xsplice
$(INSTALL_DATA) $(XSPLICE) $(DESTDIR)$(DEBUG_DIR)/$(XSPLICE)
uninstall:
rm -f $(DESTDIR)$(DEBUG_DIR)/$(XSPLICE)
.PHONY: clean
clean::
rm -f *.o .*.o.d *.xsplice config.h
#
# To compute these values we need the binary files: xen-syms
# and xen_hello_world_func.o to be already compiled.
#
.PHONY: config.h
config.h: OLD_CODE=$(call CODE_ADDR,$(BASEDIR)/xen-syms,xen_extra_version)
config.h: OLD_CODE_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_extra_version)
config.h: NEW_CODE_SZ=$(call CODE_SZ,$<,xen_hello_world)
config.h: xen_hello_world_func.o
(set -e; \
echo "#define NEW_CODE_SZ $(NEW_CODE_SZ)"; \
echo "#define OLD_CODE_SZ $(OLD_CODE_SZ)"; \
echo "#define OLD_CODE $(OLD_CODE)") > $@
xen_hello_world.o: config.h
.PHONY: $(XSPLICE)
$(XSPLICE): xen_hello_world_func.o xen_hello_world.o
$(LD) $(LDFLAGS) -r -o $(XSPLICE) $^
.PHONY: xsplice
xsplice: $(XSPLICE)
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
*
*/
#include "config.h"
#include <xen/types.h>
#include <xen/xsplice.h>
#include <public/sysctl.h>
static char hello_world_patch_this_fnc[] = "xen_extra_version";
extern const char *xen_hello_world(void);
struct xsplice_patch_func __section(".xsplice.funcs") xsplice_xen_hello_world = {
.version = XSPLICE_PAYLOAD_VERSION,
.name = hello_world_patch_this_fnc,
.new_addr = xen_hello_world,
.old_addr = (void *)OLD_CODE,
.new_size = NEW_CODE_SZ,
.old_size = OLD_CODE_SZ,
};
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
*
*/
#include <xen/types.h>
/* Our replacement function for xen_extra_version. */
const char *xen_hello_world(void)
{
return "Hello World";
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
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.