mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
29f4ab0b0a
commit
ffcd7c0698
8 files changed
+148
-2
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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:
|
||||
*/
|
||||