From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: xen-devel@lists.xenproject.org, ross.lagerwall@citrix.com,
konrad@kernel.org, andrew.cooper3@citrix.com, mpohlack@amazon.de,
sasha.levin@oracle.com
Cc: Keir Fraser <keir@xen.org>, Julien Grall <julien.grall@arm.com>,
Stefano Stabellini <stefano.stabellini@citrix.com>,
Jan Beulich <jbeulich@suse.com>,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: [PATCH v4 16/34] xsplice: Implement payload loading
Date: Tue, 15 Mar 2016 13:56:38 -0400 [thread overview]
Message-ID: <1458064616-23101-17-git-send-email-konrad.wilk@oracle.com> (raw)
In-Reply-To: <1458064616-23101-1-git-send-email-konrad.wilk@oracle.com>
From: Ross Lagerwall <ross.lagerwall@citrix.com>
Add support for loading xsplice payloads. This is somewhat similar to
the Linux kernel module loader, implementing the following steps:
- Verify the elf file.
- Parse the elf file.
- Allocate a region of memory mapped within a free area of
[xen_virt_end, XEN_VIRT_END].
- Copy allocated sections into the new region.
- Resolve section symbols. All other symbols must be absolute addresses.
(Note that patch titled "xsplice,symbols: Implement symbol name resolution
on address" implements that)
- Perform relocations.
We capitalize on the vmalloc callback API to allocate a region
of memory within the [xen_virt_end, XEN_VIRT_END] for the code.
The .data, .rodata and so on will be (not implemented in this
patch) populated in vmalloc area.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Stefano Stabellini <stefano.stabellini@citrix.com>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
v2: - Change the 'xsplice_patch_func' structure layout/size.
- Add more error checking. Fix memory leak.
- Move elf_resolve and elf_perform relocs in elf file.
- Print the payload address and pages in keyhandler.
v3:
- Make it build under ARM
- Build it without using the return_ macro.
- Add fixes from Ross.
v4:
- Add the _return macro back - but only use it during debug builds.
v5:
- Remove the macro, prefix arch_ on arch specific calls.
- Move alloc_payload to arch specific file.
- Use void* instead of uint8_t, use const
v6:
- Add copyrights
v7:
- Unroll the vmap code to add ASSERT. Change while to not incur
potential long error loop
v8:
- Use vmalloc/vfree cb APIs
- Secure .text pages to be RX instead of RWX.
---
---
xen/arch/arm/Makefile | 1 +
xen/arch/arm/xsplice.c | 56 +++++++++
xen/arch/x86/Makefile | 1 +
xen/arch/x86/setup.c | 7 ++
xen/arch/x86/xsplice.c | 256 ++++++++++++++++++++++++++++++++++++++
xen/common/xsplice.c | 186 ++++++++++++++++++++++++++-
xen/common/xsplice_elf.c | 85 +++++++++++++
xen/include/asm-x86/x86_64/page.h | 2 +
xen/include/xen/xsplice.h | 44 +++++++
xen/include/xen/xsplice_elf.h | 5 +
10 files changed, 641 insertions(+), 2 deletions(-)
create mode 100644 xen/arch/arm/xsplice.c
create mode 100644 xen/arch/x86/xsplice.c
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 0328b50..eae5cb3 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -40,6 +40,7 @@ obj-y += device.o
obj-y += decode.o
obj-y += processor.o
obj-y += smc.o
+obj-$(CONFIG_XSPLICE) += xsplice.o
#obj-bin-y += ....o
diff --git a/xen/arch/arm/xsplice.c b/xen/arch/arm/xsplice.c
new file mode 100644
index 0000000..b20365c
--- /dev/null
+++ b/xen/arch/arm/xsplice.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/xsplice_elf.h>
+#include <xen/xsplice.h>
+
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data)
+{
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ return -ENOSYS;
+}
+
+void *arch_xsplice_alloc_payload(unsigned int pages, enum va_type type,
+ mfn_t **mfn)
+{
+ return NULL;
+}
+
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type type,
+ const mfn_t *mfn)
+{
+ return -ENOSYS;
+}
+
+void arch_xsplice_register_find_space(find_space_t cb)
+{
+}
+
+void arch_xsplice_free_payload(void *va, unsigned int pages, enum va_type type)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 1bcb08b..dfcebe8 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -63,6 +63,7 @@ obj-y += vm_event.o
obj-y += xstate.o
obj-$(crash_debug) += gdbstub.o
+obj-$(CONFIG_XSPLICE) += xsplice.o
x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 115e6fd..27a4677 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -100,6 +100,9 @@ unsigned long __read_mostly xen_phys_start;
unsigned long __read_mostly xen_virt_end;
+unsigned long __read_mostly avail_virt_start;
+unsigned long __read_mostly avail_virt_end;
+
DEFINE_PER_CPU(struct tss_struct, init_tss);
char __section(".bss.stack_aligned") cpu0_stack[STACK_SIZE];
@@ -1206,6 +1209,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
~((1UL << L2_PAGETABLE_SHIFT) - 1);
destroy_xen_mappings(xen_virt_end, XEN_VIRT_START + BOOTSTRAP_MAP_BASE);
+ avail_virt_start = xen_virt_end;
+ avail_virt_end = XEN_VIRT_END - NR_CPUS * PAGE_SIZE;
+ BUG_ON(avail_virt_end <= avail_virt_start);
+
nr_pages = 0;
for ( i = 0; i < e820.nr_map; i++ )
if ( e820.map[i].type == E820_RAM )
diff --git a/xen/arch/x86/xsplice.c b/xen/arch/x86/xsplice.c
new file mode 100644
index 0000000..48a3645
--- /dev/null
+++ b/xen/arch/x86/xsplice.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/vmap.h>
+#include <xen/xsplice_elf.h>
+#include <xen/xsplice.h>
+
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data)
+{
+
+ Elf_Ehdr *hdr = data;
+
+ if ( !IS_ELF(*hdr) )
+ {
+ printk(XENLOG_ERR "%s%s: Not an ELF payload!\n", XSPLICE, elf->name);
+ return -EINVAL;
+ }
+ if ( elf->len < (sizeof *hdr) ||
+ !IS_ELF(*hdr) ||
+ hdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ hdr->e_ident[EI_DATA] != ELFDATA2LSB ||
+ hdr->e_ident[EI_OSABI] != ELFOSABI_SYSV ||
+ hdr->e_machine != EM_X86_64 ||
+ hdr->e_type != ET_REL ||
+ hdr->e_phnum != 0 )
+ {
+ printk(XENLOG_ERR "%s%s: Invalid ELF payload!\n", XSPLICE, elf->name);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ dprintk(XENLOG_ERR, "%s%s: SHR_REL relocation unsupported\n",
+ XSPLICE, elf->name);
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ Elf_RelA *r;
+ unsigned int symndx, i;
+ uint64_t val;
+ uint8_t *dest;
+
+ if ( !rela->sec->sh_entsize || !rela->sec->sh_size ||
+ rela->sec->sh_entsize != sizeof(Elf_RelA) )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Section relative header is corrupted!\n",
+ XSPLICE, elf->name);
+ return -EINVAL;
+ }
+ for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+ {
+ r = (Elf_RelA *)(rela->data + i * rela->sec->sh_entsize);
+ if ( (unsigned long)r > (unsigned long)(elf->hdr + elf->len) )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Relative section %u is past end!\n",
+ XSPLICE, elf->name, i);
+ return -EINVAL;
+ }
+ symndx = ELF64_R_SYM(r->r_info);
+ if ( symndx > elf->nsym )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Relative symbol wants symbol@%u which is past end!\n",
+ XSPLICE, elf->name, symndx);
+ return -EINVAL;
+ }
+ dest = base->load_addr + r->r_offset;
+ val = r->r_addend + elf->sym[symndx].sym->st_value;
+
+ switch ( ELF64_R_TYPE(r->r_info) )
+ {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_64:
+ *(uint64_t *)dest = val;
+ break;
+ case R_X86_64_PLT32:
+ /*
+ * Xen uses -fpic which normally uses PLT relocations
+ * except that it sets visibility to hidden which means
+ * that they are not used. However, when gcc cannot
+ * inline memcpy it emits memcpy with default visibility
+ * which then creates a PLT relocation. It can just be
+ * treated the same as R_X86_64_PC32.
+ */
+ /* Fall through */
+ case R_X86_64_PC32:
+ *(uint32_t *)dest = val - (uint64_t)dest;
+ break;
+ default:
+ printk(XENLOG_ERR "%s%s: Unhandled relocation %lu\n",
+ XSPLICE, elf->name, ELF64_R_TYPE(r->r_info));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static find_space_t find_space_fnc = NULL;
+
+void arch_xsplice_register_find_space(find_space_t cb)
+{
+ ASSERT(!find_space_fnc);
+
+ find_space_fnc = cb;
+}
+
+static void* xsplice_map_rx(const mfn_t *mfn, unsigned int pages)
+{
+ unsigned long cur;
+ unsigned long start, end;
+
+ start = (unsigned long)avail_virt_start;
+ end = start + pages * PAGE_SIZE;
+
+ ASSERT(find_space_fnc);
+
+ if ( (find_space_fnc)(pages, &start, &end) )
+ return NULL;
+
+ if ( end >= avail_virt_end )
+ return NULL;
+
+ for ( cur = start; pages--; ++mfn, cur += PAGE_SIZE )
+ {
+ /*
+ * We would like to to RX, but we need to copy data in it first.
+ * See arch_xsplice_secure for how we lockdown.
+ */
+ if ( map_pages_to_xen(start, mfn_x(*mfn), 1, PAGE_HYPERVISOR_RWX) )
+ {
+ if ( cur != start )
+ destroy_xen_mappings(start, cur);
+ return NULL;
+ }
+ }
+ return (void*)start;
+}
+
+/*
+ * The function prepares an xSplice payload by allocating space which
+ * then can be used for loading the allocated sections, resolving symbols,
+ * performing relocations, etc.
+ */
+void *arch_xsplice_alloc_payload(unsigned int pages, enum va_type type,
+ mfn_t **mfn)
+{
+ vmap_cb_t cb = NULL;
+ unsigned int i;
+ void *p;
+
+ ASSERT(pages); /* Which is in bytes. */
+ ASSERT(mfn && !*mfn);
+
+ /*
+ * Initially the pages allocated must have W otherwise we can't
+ * put anything in them.
+ */
+ if ( type == XSPLICE_VA_RX )
+ cb = xsplice_map_rx;
+ else
+ cb = vmap;
+
+ *mfn = NULL;
+ /*
+ * We let the vmalloc allocate the pages we need, and use
+ * our callback.
+ */
+ p = vmalloc_cb(pages * PAGE_SIZE, cb, mfn);
+ WARN_ON(!p);
+ if ( !p )
+ return NULL;
+ for ( i = 0; i < pages; i++ )
+ clear_page(p + (i * PAGE_SIZE) );
+
+ /* Note that we do not free mfn. The caller is responsible for that. */
+ return p;
+}
+
+static void arch_xsplice_vfree_cb(void *va, unsigned int pages)
+{
+ unsigned long addr = (unsigned long)va;
+
+ destroy_xen_mappings(addr, addr + pages * PAGE_SIZE);
+}
+
+/*
+ * Once the resolving symbols, performing relocations, etc is complete
+ * we secure the memory by putting in the proper page table attributes
+ * for the desired type.
+ *
+ */
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type type,
+ const mfn_t *mfn)
+{
+ unsigned long cur;
+ unsigned long start = (unsigned long)va;
+
+ ASSERT(va);
+ ASSERT(pages);
+
+ if ( type != XSPLICE_VA_RX )
+ return 0;
+
+ /*
+ * We could walk the pagetable and do the pagetable manipulations
+ * (strip the _PAGE_RW), which would mean also not needing the mfn
+ * array, but there are no generic code for this yet (TODO).
+ *
+ * For right now tear down the pagetables and recreate them.
+ */
+ arch_xsplice_vfree_cb(va, pages);
+
+ for ( cur = start; pages--; ++mfn, cur += PAGE_SIZE )
+ {
+ if ( map_pages_to_xen(start, mfn_x(*mfn), 1, PAGE_HYPERVISOR_RX) )
+ {
+ if ( cur != start )
+ destroy_xen_mappings(start, cur);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+void arch_xsplice_free_payload(void *va, unsigned int pages, enum va_type type)
+{
+ if ( type == XSPLICE_VA_RX )
+ vfree_cb(va, pages, arch_xsplice_vfree_cb);
+ else
+ vfree(va);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
index ba2d376..5bbb5bb 100644
--- a/xen/common/xsplice.c
+++ b/xen/common/xsplice.c
@@ -12,6 +12,7 @@
#include <xen/smp.h>
#include <xen/spinlock.h>
#include <xen/vmap.h>
+#include <xen/xsplice_elf.h>
#include <xen/xsplice.h>
#include <asm/event.h>
@@ -27,6 +28,9 @@ struct payload {
uint32_t state; /* One of the XSPLICE_STATE_*. */
int32_t rc; /* 0 or -XEN_EXX. */
struct list_head list; /* Linked to 'payload_list'. */
+ void *payload_address; /* Virtual address mapped. */
+ size_t payload_pages; /* Nr of the pages. */
+ mfn_t *mfn; /* Array of MFNs of the pages. */
char name[XEN_XSPLICE_NAME_SIZE + 1];/* Name of it. */
};
@@ -92,6 +96,136 @@ static int find_payload(const xen_xsplice_name_t *name, struct payload **f)
}
/*
+ * Functions related to XEN_SYSCTL_XSPLICE_UPLOAD (see xsplice_upload), and
+ * freeing payload (XEN_SYSCTL_XSPLICE_ACTION:XSPLICE_ACTION_UNLOAD).
+ */
+
+static void free_payload_data(struct payload *payload)
+{
+ /* Set to zero until "move_payload". */
+ if ( !payload->payload_address )
+ return;
+
+ xfree(payload->mfn);
+ payload->mfn = NULL;
+ arch_xsplice_free_payload(payload->payload_address,
+ payload->payload_pages, XSPLICE_VA_RX);
+
+ payload->payload_address = NULL;
+ payload->payload_pages = 0;
+}
+
+static void calc_section(struct xsplice_elf_sec *sec, size_t *size)
+{
+ size_t align_size = ROUNDUP(*size, sec->sec->sh_addralign);
+ sec->sec->sh_entsize = align_size;
+ *size = sec->sec->sh_size + align_size;
+}
+
+static int find_hole(ssize_t pages, unsigned long *hole_start,
+ unsigned long *hole_end)
+{
+ struct payload *data, *data2;
+
+ spin_lock_recursive(&payload_lock);
+ list_for_each_entry ( data, &payload_list, list )
+ {
+ list_for_each_entry ( data2, &payload_list, list )
+ {
+ unsigned long start, end;
+
+ start = (unsigned long)data2->payload_address;
+ end = start + data2->payload_pages * PAGE_SIZE;
+ if ( *hole_end > start && *hole_start < end )
+ {
+ *hole_start = end;
+ *hole_end = end + pages * PAGE_SIZE;
+ break;
+ }
+ }
+ if ( &data2->list == &payload_list )
+ break;
+ }
+ spin_unlock_recursive(&payload_lock);
+
+ return 0;
+}
+
+static int move_payload(struct payload *payload, struct xsplice_elf *elf)
+{
+ uint8_t *buf;
+ unsigned int i;
+ size_t size = 0;
+
+ /* Compute text regions. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & (SHF_ALLOC|SHF_EXECINSTR)) ==
+ (SHF_ALLOC|SHF_EXECINSTR) )
+ calc_section(&elf->sec[i], &size);
+ }
+
+ /* Compute rw data. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) &&
+ !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) &&
+ (elf->sec[i].sec->sh_flags & SHF_WRITE) )
+ calc_section(&elf->sec[i], &size);
+ }
+
+ /* Compute ro data. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) &&
+ !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) &&
+ !(elf->sec[i].sec->sh_flags & SHF_WRITE) )
+ calc_section(&elf->sec[i], &size);
+ }
+
+ size = PFN_UP(size);
+ buf = arch_xsplice_alloc_payload(size, XSPLICE_VA_RX, &payload->mfn);
+ if ( !buf ) {
+ printk(XENLOG_ERR "%s%s: Could not allocate memory for payload!\n",
+ XSPLICE, elf->name);
+ return -ENOMEM;
+ }
+ payload->payload_address = buf;
+ payload->payload_pages = size;
+
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( elf->sec[i].sec->sh_flags & SHF_ALLOC )
+ {
+ elf->sec[i].load_addr = buf + elf->sec[i].sec->sh_entsize;
+
+ /* Don't copy NOBITS - such as BSS. */
+ if ( elf->sec[i].sec->sh_type != SHT_NOBITS )
+ {
+ memcpy(elf->sec[i].load_addr, elf->sec[i].data,
+ elf->sec[i].sec->sh_size);
+ dprintk(XENLOG_DEBUG, "%s%s: Loaded %s at 0x%p\n", XSPLICE,
+ elf->name, elf->sec[i].name, elf->sec[i].load_addr);
+ }
+ }
+ }
+ return 0;
+}
+
+static int secure_payload(struct payload *payload, struct xsplice_elf *elf)
+{
+ int rc;
+
+ ASSERT(payload->mfn);
+
+ rc = arch_xsplice_secure(payload->payload_address, payload->payload_pages,
+ XSPLICE_VA_RX, payload->mfn);
+ xfree(payload->mfn);
+ payload->mfn = NULL;
+ return rc;
+}
+
+/*
* We MUST be holding the payload_lock spinlock.
*/
static void free_payload(struct payload *data)
@@ -100,9 +234,51 @@ static void free_payload(struct payload *data)
list_del(&data->list);
payload_cnt--;
payload_version++;
+ free_payload_data(data);
xfree(data);
}
+static int load_payload_data(struct payload *payload, void *raw, ssize_t len)
+{
+ struct xsplice_elf elf;
+ int rc = 0;
+
+ memset(&elf, 0, sizeof(elf));
+ elf.name = payload->name;
+ elf.len = len;
+
+ rc = arch_xsplice_verify_elf(&elf, raw);
+ if ( rc )
+ return rc;
+
+ rc = xsplice_elf_load(&elf, raw);
+ if ( rc )
+ goto out;
+
+ rc = move_payload(payload, &elf);
+ if ( rc )
+ goto out;
+
+ rc = xsplice_elf_resolve_symbols(&elf);
+ if ( rc )
+ goto out;
+
+ rc = xsplice_elf_perform_relocs(&elf);
+ if ( rc )
+ goto out;
+
+ rc = secure_payload(payload, &elf);
+
+ out:
+ if ( rc )
+ free_payload_data(payload);
+
+ /* Free our temporary data structure. */
+ xsplice_elf_free(&elf);
+
+ return rc;
+}
+
static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload)
{
struct payload *data = NULL;
@@ -137,6 +313,10 @@ static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload)
if ( copy_from_guest(raw_data, upload->payload, upload->size) )
goto out;
+ rc = load_payload_data(data, raw_data, upload->size);
+ if ( rc )
+ goto out;
+
data->state = XSPLICE_STATE_CHECKED;
data->rc = 0;
INIT_LIST_HEAD(&data->list);
@@ -365,8 +545,9 @@ static void xsplice_printall(unsigned char key)
spin_lock_recursive(&payload_lock);
list_for_each_entry ( data, &payload_list, list )
- printk(" name=%s state=%s(%d)\n", data->name,
- state2str(data->state), data->state);
+ printk(" name=%s state=%s(%d) %p using %zu pages.\n", data->name,
+ state2str(data->state), data->state, data->payload_address,
+ data->payload_pages);
spin_unlock_recursive(&payload_lock);
}
@@ -374,6 +555,7 @@ static void xsplice_printall(unsigned char key)
static int __init xsplice_init(void)
{
register_keyhandler('x', xsplice_printall, "print xsplicing info", 1);
+ arch_xsplice_register_find_space(&find_hole);
return 0;
}
__initcall(xsplice_init);
diff --git a/xen/common/xsplice_elf.c b/xen/common/xsplice_elf.c
index ae87361..6128726 100644
--- a/xen/common/xsplice_elf.c
+++ b/xen/common/xsplice_elf.c
@@ -206,6 +206,91 @@ static int elf_get_sym(struct xsplice_elf *elf, const void *data)
return 0;
}
+int xsplice_elf_resolve_symbols(struct xsplice_elf *elf)
+{
+ unsigned int i;
+
+ /*
+ * The first entry of an ELF symbol table is the "undefined symbol index".
+ * aka reserved so we skip it.
+ */
+ ASSERT( elf->sym );
+ for ( i = 1; i < elf->nsym; i++ )
+ {
+ switch ( elf->sym[i].sym->st_shndx )
+ {
+ case SHN_COMMON:
+ printk(XENLOG_ERR "%s%s: Unexpected common symbol: %s\n",
+ XSPLICE, elf->name, elf->sym[i].name);
+ return -EINVAL;
+ break;
+ case SHN_UNDEF:
+ printk(XENLOG_ERR "%s%s: Unknown symbol: %s\n",
+ XSPLICE, elf->name, elf->sym[i].name);
+ return -ENOENT;
+ break;
+ case SHN_ABS:
+ dprintk(XENLOG_DEBUG, "%s%s: Absolute symbol: %s => 0x%"PRIx64"\n",
+ XSPLICE, elf->name, elf->sym[i].name,
+ elf->sym[i].sym->st_value);
+ break;
+ default:
+ if ( elf->sec[elf->sym[i].sym->st_shndx].sec->sh_flags & SHF_ALLOC )
+ {
+ elf->sym[i].sym->st_value +=
+ (unsigned long)elf->sec[elf->sym[i].sym->st_shndx].load_addr;
+ if ( elf->sym[i].name )
+ printk(XENLOG_DEBUG "%s%s: Symbol resolved: %s => 0x%"PRIx64"\n",
+ XSPLICE, elf->name, elf->sym[i].name,
+ elf->sym[i].sym->st_value);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int xsplice_elf_perform_relocs(struct xsplice_elf *elf)
+{
+ struct xsplice_elf_sec *rela, *base;
+ unsigned int i;
+ int rc;
+
+ /*
+ * The first entry of an ELF symbol table is the "undefined symbol index".
+ * aka reserved so we skip it.
+ */
+ ASSERT( elf->sym );
+ for ( i = 1; i < elf->hdr->e_shnum; i++ )
+ {
+ rela = &elf->sec[i];
+
+ if ( (rela->sec->sh_type != SHT_RELA ) &&
+ (rela->sec->sh_type != SHT_REL ) )
+ continue;
+
+ /* Is it a valid relocation section? */
+ if ( rela->sec->sh_info >= elf->hdr->e_shnum )
+ continue;
+
+ base = &elf->sec[rela->sec->sh_info];
+
+ /* Don't relocate non-allocated sections. */
+ if ( !(base->sec->sh_flags & SHF_ALLOC) )
+ continue;
+
+ if ( elf->sec[i].sec->sh_type == SHT_RELA )
+ rc = arch_xsplice_perform_rela(elf, base, rela);
+ else /* SHT_REL */
+ rc = arch_xsplice_perform_rel(elf, base, rela);
+
+ if ( rc )
+ return rc;
+ }
+
+ return 0;
+}
+
static int xsplice_header_check(const struct xsplice_elf *elf)
{
if ( sizeof(*elf->hdr) >= elf->len )
diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
index 86abb94..a854e05 100644
--- a/xen/include/asm-x86/x86_64/page.h
+++ b/xen/include/asm-x86/x86_64/page.h
@@ -38,6 +38,8 @@
#include <xen/pdx.h>
extern unsigned long xen_virt_end;
+extern unsigned long avail_virt_start;
+extern unsigned long avail_virt_end;
#define spage_to_pdx(spg) (((spg) - spage_table)<<(SUPERPAGE_SHIFT-PAGE_SHIFT))
#define pdx_to_spage(pdx) (spage_table + ((pdx)>>(SUPERPAGE_SHIFT-PAGE_SHIFT)))
diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h
index cd805a8..343e59f 100644
--- a/xen/include/xen/xsplice.h
+++ b/xen/include/xen/xsplice.h
@@ -6,6 +6,9 @@
#ifndef __XEN_XSPLICE_H__
#define __XEN_XSPLICE_H__
+struct xsplice_elf;
+struct xsplice_elf_sec;
+struct xsplice_elf_sym;
struct xen_sysctl_xsplice_op;
#ifdef CONFIG_XSPLICE
@@ -15,6 +18,47 @@ struct xen_sysctl_xsplice_op;
int xsplice_op(struct xen_sysctl_xsplice_op *);
+/* Arch hooks. */
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data);
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela);
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela);
+enum va_type {
+ XSPLICE_VA_RX, /* .text */
+ XSPLICE_VA_RW, /* Everything else. */
+};
+
+#include <xen/mm.h>
+void *arch_xsplice_alloc_payload(unsigned int pages, enum va_type, mfn_t **mfn);
+
+/*
+ * Function to secure the allocate pages (from arch_xsplice_alloc_payload)
+ * with the right page permissions.
+ */
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type type,
+ const mfn_t *mfn);
+
+void arch_xsplice_free_payload(void *va, unsigned int pages, enum va_type);
+
+/*
+ * Callback to find available virtual address space in which the
+ * payload could be put in.
+ *
+ * The arguments are:
+ * - The size of the payload in bytes.
+ * - The starting virtual address to search. To be updated by
+ * callback if space found.
+ * - The ending virtual address to search. To be updated by
+ * callback if space found.
+ *
+ * The return value is zero if search was done. -EXX values
+ * if errors were encountered.
+ */
+typedef int (*find_space_t)(ssize_t, unsigned long *, unsigned long *);
+void arch_xsplice_register_find_space(find_space_t cb);
#else
#include <xen/errno.h> /* For -ENOSYS */
diff --git a/xen/include/xen/xsplice_elf.h b/xen/include/xen/xsplice_elf.h
index e2dea18..f6ffcbe 100644
--- a/xen/include/xen/xsplice_elf.h
+++ b/xen/include/xen/xsplice_elf.h
@@ -15,6 +15,8 @@ struct xsplice_elf_sec {
elf_resolve_section_names. */
const void *data; /* Pointer to the section (done by
elf_resolve_sections). */
+ uint8_t *load_addr; /* A pointer to the allocated destination.
+ Done by load_payload_data. */
};
struct xsplice_elf_sym {
@@ -38,6 +40,9 @@ struct xsplice_elf_sec *xsplice_elf_sec_by_name(const struct xsplice_elf *elf,
int xsplice_elf_load(struct xsplice_elf *elf, void *data);
void xsplice_elf_free(struct xsplice_elf *elf);
+int xsplice_elf_resolve_symbols(struct xsplice_elf *elf);
+int xsplice_elf_perform_relocs(struct xsplice_elf *elf);
+
#endif /* __XEN_XSPLICE_ELF_H__ */
/*
--
2.5.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-03-15 18:00 UTC|newest]
Thread overview: 124+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-15 17:56 [PATCH v4] xSplice v1 design and implementation Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 01/34] compat/x86: Remove unncessary #define Konrad Rzeszutek Wilk
2016-03-15 18:57 ` Andrew Cooper
2016-03-16 11:08 ` Jan Beulich
2016-03-17 0:44 ` Konrad Rzeszutek Wilk
2016-03-17 7:45 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 02/34] libxc: Remove dead code (XENVER_capabilities) Konrad Rzeszutek Wilk
2016-03-15 18:04 ` Andrew Cooper
2016-03-15 18:08 ` Konrad Rzeszutek Wilk
2016-03-16 18:11 ` Wei Liu
2016-03-15 17:56 ` [PATCH v4 03/34] xsm/xen_version: Add XSM for the xen_version hypercall Konrad Rzeszutek Wilk
2016-03-18 11:55 ` Jan Beulich
2016-03-18 17:26 ` Konrad Rzeszutek Wilk
2016-03-21 11:22 ` Jan Beulich
2016-03-22 16:10 ` Konrad Rzeszutek Wilk
2016-03-22 17:54 ` Daniel De Graaf
2016-03-22 17:49 ` Daniel De Graaf
2016-03-24 15:34 ` anshul makkar
2016-03-24 19:19 ` Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 04/34] HYPERCALL_version_op. New hypercall mirroring XENVER_ but sane Konrad Rzeszutek Wilk
2016-03-15 18:29 ` Andrew Cooper
2016-03-15 20:19 ` Konrad Rzeszutek Wilk
2016-03-17 1:38 ` Konrad Rzeszutek Wilk
2016-03-17 14:28 ` Andrew Cooper
2016-03-18 12:36 ` Jan Beulich
2016-03-18 19:22 ` Konrad Rzeszutek Wilk
2016-03-21 12:45 ` Jan Beulich
2016-03-22 15:52 ` Konrad Rzeszutek Wilk
2016-03-22 16:06 ` Jan Beulich
2016-03-22 18:57 ` Konrad Rzeszutek Wilk
2016-03-22 19:28 ` Andrew Cooper
2016-03-22 20:39 ` Konrad Rzeszutek Wilk
2016-03-23 8:56 ` Jan Beulich
2016-03-24 2:37 ` Konrad Rzeszutek Wilk
2016-03-24 9:15 ` Jan Beulich
2016-03-24 11:39 ` Konrad Rzeszutek Wilk
2016-03-22 17:51 ` Daniel De Graaf
2016-03-15 17:56 ` [PATCH v4 05/34] libxc/libxl/python/xenstat: Use new XEN_VERSION_OP hypercall Konrad Rzeszutek Wilk
2016-03-15 18:45 ` Andrew Cooper
2016-03-16 12:31 ` George Dunlap
2016-03-16 18:11 ` Wei Liu
2016-03-17 1:08 ` Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 06/34] x86/arm: Add BUGFRAME_NR define and BUILD checks Konrad Rzeszutek Wilk
2016-03-15 18:54 ` Andrew Cooper
2016-03-16 11:49 ` Julien Grall
2016-03-18 12:40 ` Jan Beulich
2016-03-18 19:59 ` Konrad Rzeszutek Wilk
2016-03-21 12:49 ` Jan Beulich
2016-03-22 15:39 ` Konrad Rzeszutek Wilk
2016-03-22 15:58 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 07/34] arm/x86: Use struct virtual_region to do bug, symbol, and (x86) exception tables Konrad Rzeszutek Wilk
2016-03-15 19:24 ` Andrew Cooper
2016-03-15 19:34 ` Konrad Rzeszutek Wilk
2016-03-15 19:51 ` Andrew Cooper
2016-03-15 20:02 ` Andrew Cooper
2016-03-16 10:33 ` Jan Beulich
2016-03-18 13:07 ` Jan Beulich
2016-03-22 20:18 ` Konrad Rzeszutek Wilk
2016-03-23 8:19 ` Jan Beulich
2016-03-23 11:17 ` Julien Grall
2016-03-23 11:21 ` Jan Beulich
2016-03-24 2:49 ` Konrad Rzeszutek Wilk
2016-03-24 9:20 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 08/34] vmap: Make the while loop less fishy Konrad Rzeszutek Wilk
2016-03-15 19:33 ` Andrew Cooper
2016-03-17 11:49 ` Jan Beulich
2016-03-17 14:37 ` Andrew Cooper
2016-03-17 15:30 ` Jan Beulich
2016-03-17 16:06 ` Ian Jackson
2016-03-17 11:48 ` Jan Beulich
2016-03-17 16:08 ` Ian Jackson
2016-03-21 12:04 ` George Dunlap
2016-03-21 13:26 ` Jan Beulich
2016-03-21 14:22 ` George Dunlap
2016-03-21 15:05 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 09/34] vmap: ASSERT on NULL Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 10/34] vmap: Add vmalloc_cb and vfree_cb Konrad Rzeszutek Wilk
2016-03-18 13:20 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 11/34] xsplice: Design document Konrad Rzeszutek Wilk
2016-03-23 11:18 ` Jan Beulich
2016-03-23 20:12 ` Konrad Rzeszutek Wilk
2016-03-23 20:21 ` Konrad Rzeszutek Wilk
2016-03-24 3:15 ` Konrad Rzeszutek Wilk
2016-03-24 9:32 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 12/34] xen/xsplice: Hypervisor implementation of XEN_XSPLICE_op Konrad Rzeszutek Wilk
2016-03-16 12:12 ` Julien Grall
2016-03-16 19:58 ` Konrad Rzeszutek Wilk
2016-03-23 13:51 ` Jan Beulich
2016-03-24 3:13 ` Konrad Rzeszutek Wilk
2016-03-24 9:29 ` Jan Beulich
2016-03-15 17:56 ` [PATCH v4 13/34] libxc: Implementation of XEN_XSPLICE_op in libxc Konrad Rzeszutek Wilk
2016-03-16 18:12 ` Wei Liu
2016-03-16 20:36 ` Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 14/34] xen-xsplice: Tool to manipulate xsplice payloads Konrad Rzeszutek Wilk
2016-03-16 18:12 ` Wei Liu
2016-03-15 17:56 ` [PATCH v4 15/34] xsplice: Add helper elf routines Konrad Rzeszutek Wilk
2016-03-15 17:56 ` Konrad Rzeszutek Wilk [this message]
2016-03-22 17:25 ` [PATCH v4 16/34] xsplice: Implement payload loading Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 17/34] xsplice: Implement support for applying/reverting/replacing patches Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 18/34] x86/xen_hello_world.xsplice: Test payload for patching 'xen_extra_version' Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 19/34] xsplice, symbols: Implement symbol name resolution on address Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 20/34] x86, xsplice: Print payload's symbol name and payload name in backtraces Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 21/34] xsplice: Add .xsplice.hooks functions and test-case Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 22/34] xsplice: Add support for bug frames Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 23/34] xsplice: Add support for exception tables Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 24/34] xsplice: Add support for alternatives Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 25/34] build_id: Provide ld-embedded build-ids Konrad Rzeszutek Wilk
2016-03-16 18:34 ` Julien Grall
2016-03-16 21:02 ` Konrad Rzeszutek Wilk
2016-03-17 1:12 ` Konrad Rzeszutek Wilk
2016-03-17 11:08 ` Julien Grall
2016-03-17 13:39 ` Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 26/34] HYPERCALL_version_op: Add VERSION_OP_build_id to retrieve build-id Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 27/34] libxl: info: Display build_id of the hypervisor using XEN_VERSION_OP_build_id Konrad Rzeszutek Wilk
2016-03-16 18:12 ` Wei Liu
2016-03-15 17:56 ` [PATCH v4 28/34] xsplice: Print build_id in keyhandler and on bootup Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 29/34] xsplice: Stacking build-id dependency checking Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 30/34] xsplice/xen_replace_world: Test-case for XSPLICE_ACTION_REPLACE Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 31/34] xsplice: Print dependency and payloads build_id in the keyhandler Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 32/34] xsplice: Prevent duplicate payloads from being loaded Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 33/34] xsplice: Add support for shadow variables Konrad Rzeszutek Wilk
2016-03-15 17:56 ` [PATCH v4 34/34] MAINTAINERS/xsplice: Add myself and Ross as the maintainers Konrad Rzeszutek Wilk
2016-03-16 11:10 ` Jan Beulich
2016-03-17 0:44 ` Konrad Rzeszutek Wilk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1458064616-23101-17-git-send-email-konrad.wilk@oracle.com \
--to=konrad.wilk@oracle.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=julien.grall@arm.com \
--cc=keir@xen.org \
--cc=konrad@kernel.org \
--cc=mpohlack@amazon.de \
--cc=ross.lagerwall@citrix.com \
--cc=sasha.levin@oracle.com \
--cc=stefano.stabellini@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).