From patchwork Fri Jan 8 02:25:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Rzeszutek Wilk X-Patchwork-Id: 7982031 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 23A409F38D for ; Fri, 8 Jan 2016 02:28:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 92FB120149 for ; Fri, 8 Jan 2016 02:28:46 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 034E720142 for ; Fri, 8 Jan 2016 02:28:45 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aHMkC-0004vn-Ve; Fri, 08 Jan 2016 02:25:36 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aHMkA-0004vi-OC for xen-devel@lists.xenproject.org; Fri, 08 Jan 2016 02:25:34 +0000 Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id 1E/D3-18633-E1E1F865; Fri, 08 Jan 2016 02:25:34 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-6.tower-206.messagelabs.com!1452219931!14286208!1 X-Originating-IP: [156.151.31.81] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTU2LjE1MS4zMS44MSA9PiAyODgzMzk=\n X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 34601 invoked from network); 8 Jan 2016 02:25:32 -0000 Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by server-6.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 8 Jan 2016 02:25:32 -0000 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u082PPWu011166 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 8 Jan 2016 02:25:25 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u082POsf029137 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 8 Jan 2016 02:25:24 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u082PNec010827; Fri, 8 Jan 2016 02:25:23 GMT Received: from char.us.oracle.com (/10.137.176.158) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 07 Jan 2016 18:25:23 -0800 Received: by char.us.oracle.com (Postfix, from userid 1000) id 43DB56A058B; Thu, 7 Jan 2016 21:25:22 -0500 (EST) From: Konrad Rzeszutek Wilk To: JBeulich@suse.com, andrew.cooper3@citrix.com, ian.campbell@citrix.com, wei.liu2@citrix.com, ian.jackson@eu.citrix.com, xen-devel@lists.xenproject.org, dgdegra@tycho.nsa.gov, konrad@kernel.org, mpohlack@amazon.de Date: Thu, 7 Jan 2016 21:25:19 -0500 Message-Id: <1452219920-14043-3-git-send-email-konrad.wilk@oracle.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1452219920-14043-1-git-send-email-konrad.wilk@oracle.com> References: <1452219920-14043-1-git-send-email-konrad.wilk@oracle.com> X-Source-IP: aserv0021.oracle.com [141.146.126.233] Cc: Konrad Rzeszutek Wilk Subject: [Xen-devel] [PATCH v3 2/3] XENVER_build_id: Provide ld-embedded build-ids (v8) X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The mechanism to get this is via the XENVER hypercall and we add a new sub-command to retrieve the binary build-id called XENVER_build_id. The sub-hypercall parameter allows an arbitrary size (the buffer and len is provided to the hypervisor). A NULL parameter will probe the hypervisor for the length of the build-id. One can also retrieve the value of the build-id by doing 'readelf -h xen-syms'. For EFI builds we re-use the same build-id that the xen-syms was built with. Note that there are no changes to the XSM files (dummy.c and hooks.c) as the privileged subops fall in the default case. The version of ld that first implemented --build-id is v2.18. Hence we check for that or later version - if older version found we do not build the hypervisor with the build-id (and the return code is -ENODATA for that case). Suggested-by: Andrew Cooper Signed-off-by: Martin Pohlack Signed-off-by: Konrad Rzeszutek Wilk --- v1: Rebase it on Martin's initial patch v2: Move it to XENVER hypercall v3: Fix EFI building (Ross's fix) v4: Don't use the third argument for length. v5: Use new structure for XENVER_build_id with variable buf. v6: Include Ross's fix. v7: Include detection of bin-utils for build-id support, add probing for size, and return -EPERM for XSM denied calls. v8: Build xen_build_id under ARM, required adding ELFSIZE in proper file. --- Config.mk | 11 ++++++++++ tools/libxc/xc_private.c | 7 +++++++ tools/libxc/xc_private.h | 10 +++++++++ xen/arch/arm/Makefile | 6 +++--- xen/arch/arm/xen.lds.S | 6 ++++++ xen/arch/x86/Makefile | 16 +++++++++----- xen/arch/x86/xen.lds.S | 6 ++++++ xen/common/kernel.c | 35 +++++++++++++++++++++++++++++++ xen/common/version.c | 42 +++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/config.h | 2 ++ xen/include/public/version.h | 16 +++++++++++++- xen/include/xen/version.h | 1 + xen/xsm/flask/policy/access_vectors | 4 ++-- 13 files changed, 151 insertions(+), 11 deletions(-) diff --git a/Config.mk b/Config.mk index 62f8209..80d6972 100644 --- a/Config.mk +++ b/Config.mk @@ -126,6 +126,17 @@ endef check-$(gcc) = $(call cc-ver-check,CC,0x040100,"Xen requires at least gcc-4.1") $(eval $(check-y)) +ld-ver = $(shell if [ $$((`$(1) --version | head -1 | sed 's/[^0-9]/ /g' | awk \ + '{ printf "0x%02x%02x", $$1, $$2}'`)) -ge $$(($(2))) ]; \ + then echo y; else echo n; fi ;) + +# binutils 2.18 implement build-id. +ifeq ($(call ld-ver,$(LD),0x0212),n) +build_id := +else +build_id := --build-id=sha1 +endif + # as-insn: Check whether assembler supports an instruction. # Usage: cflags-y += $(call as-insn "insn",option-yes,option-no) as-insn = $(if $(shell echo 'void _(void) { asm volatile ( $(2) ); }' \ diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 6c0c0d6..876e0df 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -712,6 +712,13 @@ int xc_version(xc_interface *xch, int cmd, void *arg) case XENVER_commandline: sz = sizeof(xen_commandline_t); break; + case XENVER_build_id: + { + xen_build_id_t *build_id = (xen_build_id_t *)arg; + sz = sizeof(*build_id) + build_id->len; + HYPERCALL_BOUNCE_SET_DIR(arg, XC_HYPERCALL_BUFFER_BOUNCE_BOTH); + break; + } default: ERROR("xc_version: unknown command %d\n", cmd); return -EINVAL; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index f603c15..b1b1432 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -202,6 +202,16 @@ enum { #define DECLARE_HYPERCALL_BOUNCE(_ubuf, _sz, _dir) DECLARE_NAMED_HYPERCALL_BOUNCE(_ubuf, _ubuf, _sz, _dir) /* + * Change the direction. + * + * Can only be used if the bounce_pre/bounce_post commands have + * not been used. + */ +#define HYPERCALL_BOUNCE_SET_DIR(_buf, _dir) do { if ((HYPERCALL_BUFFER(_buf))->hbuf) \ + assert(1); \ + (HYPERCALL_BUFFER(_buf))->dir = _dir; \ + } while (0) +/* * Set the size of data to bounce. Useful when the size is not known * when the bounce buffer is declared. */ diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 2f050f5..fdf0800 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -79,17 +79,17 @@ $(BASEDIR)/common/symbols-dummy.o: $(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 $(NM) -pa --format=sysv $(@D)/.$(@F).0 \ | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1 $(NM) -pa --format=sysv $(@D)/.$(@F).1 \ | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).1.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(@D)/.$(@F).1.o -o $@ rm -f $(@D)/.$(@F).[0-9]* diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index 0488f37..1d262c4 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -53,6 +53,12 @@ SECTIONS _erodata = .; /* End of read-only data */ } :text + .note.gnu.build-id : { + __note_gnu_build_id_start = .; + *(.note.gnu.build-id) + __note_gnu_build_id_end = .; + } :text + .data : { /* Data */ . = ALIGN(PAGE_SIZE); *(.data.page_aligned) diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 8e6e901..b88a84f 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -103,20 +103,23 @@ $(BASEDIR)/common/symbols-dummy.o: $(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 $(NM) -pa --format=sysv $(@D)/.$(@F).0 \ | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1 $(NM) -pa --format=sysv $(@D)/.$(@F).1 \ | $(BASEDIR)/tools/symbols --sysv --sort --warn-dup >$(@D)/.$(@F).1.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id) \ $(@D)/.$(@F).1.o -o $@ rm -f $(@D)/.$(@F).[0-9]* +build_id.o: $(TARGET)-syms + $(OBJCOPY) --only-section=.note.gnu.build-id $< build_id.o + EFI_LDFLAGS = $(patsubst -m%,-mi386pep,$(LDFLAGS)) --subsystem=10 EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0 --strip-debug EFI_LDFLAGS += --section-alignment=0x200000 --file-alignment=0x20 @@ -129,6 +132,9 @@ $(TARGET).efi: VIRT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A VIR $(TARGET).efi: ALT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A ALT_START$$,,p') # Don't use $(wildcard ...) here - at least make 3.80 expands this too early! $(TARGET).efi: guard = $(if $(shell echo efi/dis* | grep disabled),:) +ifneq ($(build_id),) +$(TARGET).efi: build_id.o +endif $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbols-dummy.o efi/mkreloc $(foreach base, $(VIRT_BASE) $(ALT_BASE), \ $(guard) $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< efi/relocs-dummy.o \ @@ -144,8 +150,8 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbol $(guard) $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).1 \ | $(guard) $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).1s.S $(guard) $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o - $(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds -N $< \ - $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o -o $@ + $(guard) $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T efi.lds $(build_id) -N $< \ + $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o build_id.o -o $@ if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi rm -f $(@D)/.$(@F).[0-9]* diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index e18e08f..329eab6 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -67,6 +67,12 @@ SECTIONS *(.rodata.*) } :text + .note.gnu.build-id : { + __note_gnu_build_id_start = .; + *(.note.gnu.build-id) + __note_gnu_build_id_end = .; + } :text + . = ALIGN(SMP_CACHE_BYTES); .data.read_mostly : { /* Exception table */ diff --git a/xen/common/kernel.c b/xen/common/kernel.c index 2b3ccc4..62a95a5 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -366,6 +366,41 @@ DO(xen_version)(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) return -EFAULT; return 0; } + case XENVER_build_id: + { + xen_build_id_t build_id; + unsigned int sz = 0; + int rc = 0; + char *p = NULL; + + if ( deny ) + return -EPERM; + + /* Only return size. */ + if ( !guest_handle_is_null(arg) ) + { + if ( copy_from_guest(&build_id, arg, 1) ) + return -EFAULT; + + if ( build_id.len == 0 ) + return -EINVAL; + } + + rc = xen_build_id(&p, &sz); + if ( rc ) + return rc; + + if ( guest_handle_is_null(arg) ) + return sz; + + if ( sz > build_id.len ) + return -ENOBUFS; + + if ( copy_to_guest_offset(arg, offsetof(xen_build_id_t, buf), p, sz) ) + return -EFAULT; + + return sz; + } } return -ENOSYS; diff --git a/xen/common/version.c b/xen/common/version.c index 95332a0..f7e120f 100644 --- a/xen/common/version.c +++ b/xen/common/version.c @@ -1,5 +1,9 @@ #include #include +#include +#include +#include +#include const char *xen_compile_date(void) { @@ -60,3 +64,41 @@ const char *xen_deny(void) { return "\0"; } + +#define NT_GNU_BUILD_ID 3 +/* Defined in linker script. */ +extern const Elf_Note __note_gnu_build_id_start[], __note_gnu_build_id_end[]; + +int xen_build_id(char **p, unsigned int *len) +{ + const Elf_Note *n = __note_gnu_build_id_start; + static bool_t checked = 0; + + if ( checked ) + { + *len = n->descsz; + *p = ELFNOTE_DESC(n); + return 0; + } + /* --build-id invoked with wrong parameters. */ + if ( __note_gnu_build_id_end <= __note_gnu_build_id_start ) + return -ENODATA; + + /* Check for full Note header. */ + if ( &n[1] > __note_gnu_build_id_end ) + return -ENODATA; + + /* Check if we really have a build-id. */ + if ( NT_GNU_BUILD_ID != n->type ) + return -ENODATA; + + /* Sanity check, name should be "GNU" for ld-generated build-id. */ + if ( strncmp(ELFNOTE_NAME(n), "GNU", n->namesz) != 0 ) + return -ENODATA; + + *len = n->descsz; + *p = ELFNOTE_DESC(n); + + checked = 1; + return 0; +} diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index 1520b41..b863c80 100644 --- a/xen/include/asm-arm/config.h +++ b/xen/include/asm-arm/config.h @@ -15,8 +15,10 @@ #if defined(CONFIG_ARM_64) # define LONG_BYTEORDER 3 +# define ELFSIZE 64 #else # define LONG_BYTEORDER 2 +# define ELFSIZE 32 #endif #define BYTES_PER_LONG (1 << LONG_BYTEORDER) diff --git a/xen/include/public/version.h b/xen/include/public/version.h index 44f26b0..adca602 100644 --- a/xen/include/public/version.h +++ b/xen/include/public/version.h @@ -30,7 +30,8 @@ #include "xen.h" -/* NB. All ops return zero on success, except XENVER_{version,pagesize} */ +/* NB. All ops return zero on success, except + * XENVER_{version,pagesize,build_id} */ /* arg == NULL; returns major:minor (16:16). */ #define XENVER_version 0 @@ -83,6 +84,19 @@ typedef struct xen_feature_info xen_feature_info_t; #define XENVER_commandline 9 typedef char xen_commandline_t[1024]; +/* Return value is the number of bytes written, or XEN_Exx on error. + * Calling with empty parameter returns the size of build_id. */ +#define XENVER_build_id 10 +struct xen_build_id { + uint32_t len; /* IN: size of buf[]. */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + unsigned char buf[]; +#elif defined(__GNUC__) + unsigned char buf[1]; /* OUT: Variable length buffer with build_id. */ +#endif +}; +typedef struct xen_build_id xen_build_id_t; + #endif /* __XEN_PUBLIC_VERSION_H__ */ /* diff --git a/xen/include/xen/version.h b/xen/include/xen/version.h index 2015c0b..466c977 100644 --- a/xen/include/xen/version.h +++ b/xen/include/xen/version.h @@ -13,5 +13,6 @@ const char *xen_extra_version(void); const char *xen_changeset(void); const char *xen_banner(void); const char *xen_deny(void); +int xen_build_id(char **p, unsigned int *len); #endif /* __XEN_VERSION_H__ */ diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 44a106e..c123256 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -93,8 +93,8 @@ class xen2 pmu_ctrl # PMU use (domains, including unprivileged ones, will be using this operation) pmu_use -# XENVER_commandline usage. - version_priv +# XENVER_[commandline|build_id] usage. + version_priv } # Classes domain and domain2 consist of operations that a domain performs on