diff mbox

[v3,2/3] XENVER_build_id: Provide ld-embedded build-ids (v8)

Message ID 1452219920-14043-3-git-send-email-konrad.wilk@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Konrad Rzeszutek Wilk Jan. 8, 2016, 2:25 a.m. UTC
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 <andrew.cooper3@citrix.com>
Signed-off-by: Martin Pohlack <mpohlack@amazon.de>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
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(-)

Comments

Jan Beulich Jan. 12, 2016, 4:25 p.m. UTC | #1
>>> On 08.01.16 at 03:25, <konrad.wilk@oracle.com> wrote:
> 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'.

Does this or something similar also work on xen.gz and xen.efi?
I ask because xen-syms isn't present on the boot partition, and
may not be present anywhere on an otherwise functioning
system.

> --- 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

Wouldn't it be better to probe the linker for recognizing the --build-id
command line option, along the lines of $(cc-option)?

In any event the option should be added to LDFLAGS unless this
conflicts with something else.

> --- 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

Wouldn't this better be a generic .note section, with .note.gnu.build-id
just special cased ahead of *(.note) *(.note.*)?

> --- 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:

Blank line ahead of case statements please when most/all others
have it that way in a particular switch().

> +    {
> +        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);

Perhaps use the helpers from xen/err.h to limit the amount of
indirection needed?

> +        if ( rc )
> +            return rc;
> +
> +        if ( guest_handle_is_null(arg) )
> +            return sz;
> +
> +        if ( sz > build_id.len )
> +            return -ENOBUFS;

And how will the caller know how much is needed?

> +        if ( copy_to_guest_offset(arg, offsetof(xen_build_id_t, buf), p, sz) )
> +            return -EFAULT;
> +
> +        return sz;
> +    }

Or how much got copied?

> +int xen_build_id(char **p, unsigned int *len)
> +{
> +    const Elf_Note *n = __note_gnu_build_id_start;
> +    static bool_t checked = 0;

Pointless initializer.

Jan
Konrad Rzeszutek Wilk Jan. 12, 2016, 4:43 p.m. UTC | #2
On Tue, Jan 12, 2016 at 09:25:27AM -0700, Jan Beulich wrote:
> >>> On 08.01.16 at 03:25, <konrad.wilk@oracle.com> wrote:
> > 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'.
> 
> Does this or something similar also work on xen.gz and xen.efi?

Sadly no.
> I ask because xen-syms isn't present on the boot partition, and
> may not be present anywhere on an otherwise functioning
> system.

Right. Some later patches (xsplice related) hook the build-id printing
to a keyboard handler. Would that work ?

Or are you suggesting that perhaps the kernel should at boot time
print the build-id (like it does the changset)?

> 
> > --- 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
> 
> Wouldn't it be better to probe the linker for recognizing the --build-id
> command line option, along the lines of $(cc-option)?

Let me see what happens with that.
> 
> In any event the option should be added to LDFLAGS unless this
> conflicts with something else.
> 
> > --- 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
> 
> Wouldn't this better be a generic .note section, with .note.gnu.build-id
> just special cased ahead of *(.note) *(.note.*)?
> 
> > --- 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:
> 
> Blank line ahead of case statements please when most/all others
> have it that way in a particular switch().
> 
> > +    {
> > +        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);
> 
> Perhaps use the helpers from xen/err.h to limit the amount of
> indirection needed?
> 
> > +        if ( rc )
> > +            return rc;
> > +
> > +        if ( guest_handle_is_null(arg) )
> > +            return sz;
> > +
> > +        if ( sz > build_id.len )
> > +            return -ENOBUFS;
> 
> And how will the caller know how much is needed?

Duh. I shall update the build_id.len with the appropiate value.
> 
> > +        if ( copy_to_guest_offset(arg, offsetof(xen_build_id_t, buf), p, sz) )
> > +            return -EFAULT;
> > +
> > +        return sz;
> > +    }
> 
> Or how much got copied?

That one is easy - we do return 'sz' which tells us how much got copied.

Or are you suggesting that the build_id.len should also be updated?
> 
> > +int xen_build_id(char **p, unsigned int *len)
> > +{
> > +    const Elf_Note *n = __note_gnu_build_id_start;
> > +    static bool_t checked = 0;
> 
> Pointless initializer.
> 
> Jan
>
Jan Beulich Jan. 12, 2016, 5 p.m. UTC | #3
>>> On 12.01.16 at 17:43, <konrad.wilk@oracle.com> wrote:
> On Tue, Jan 12, 2016 at 09:25:27AM -0700, Jan Beulich wrote:
>> >>> On 08.01.16 at 03:25, <konrad.wilk@oracle.com> wrote:
>> > 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'.
>> 
>> Does this or something similar also work on xen.gz and xen.efi?
> 
> Sadly no.
>> I ask because xen-syms isn't present on the boot partition, and
>> may not be present anywhere on an otherwise functioning
>> system.
> 
> Right. Some later patches (xsplice related) hook the build-id printing
> to a keyboard handler. Would that work ?

Key handlers are strictly a debugging facility.

> Or are you suggesting that perhaps the kernel should at boot time
> print the build-id (like it does the changset)?

Perhaps, albeit to me that's a bit orthogonal to being able to find out
the build ID for a given binary.

>> > +        if ( rc )
>> > +            return rc;
>> > +
>> > +        if ( guest_handle_is_null(arg) )
>> > +            return sz;
>> > +
>> > +        if ( sz > build_id.len )
>> > +            return -ENOBUFS;
>> 
>> And how will the caller know how much is needed?
> 
> Duh. I shall update the build_id.len with the appropiate value.

Ah, actually I now see you have Andrew's beloved NULL handle
check up a few lines - that may suffice. Albeit I'm not generally in
favor of this model; I prefer a first attempt to succeed if possible,
and a second one only to be needed if the caller estimated size in
fact didn't suffice (and then no 3rd one being necessary in order
to obtain the needed size).

>> > +        if ( copy_to_guest_offset(arg, offsetof(xen_build_id_t, buf), p, sz) )
>> > +            return -EFAULT;
>> > +
>> > +        return sz;
>> > +    }
>> 
>> Or how much got copied?
> 
> That one is easy - we do return 'sz' which tells us how much got copied.

Ah, right. Perhaps I shouldn't be reviewing patches a few minutes
before heading home...

Jan
Konrad Rzeszutek Wilk Jan. 14, 2016, 2:02 a.m. UTC | #4
> > Or are you suggesting that perhaps the kernel should at boot time
> > print the build-id (like it does the changset)?
> 
> Perhaps, albeit to me that's a bit orthogonal to being able to find out
> the build ID for a given binary.

I can make some magic objdump + awk to extract the buildid from
the hypervisor and deposit as a text file in /usr/../xen/debug?
Similar to how xen-syms is copied there?

Would that work?

But I am a bit lost of what your use-case is?

The third patch implements 'xl info' to display it.

> 
> >> > +        if ( rc )
> >> > +            return rc;
> >> > +
> >> > +        if ( guest_handle_is_null(arg) )
> >> > +            return sz;
> >> > +
> >> > +        if ( sz > build_id.len )
> >> > +            return -ENOBUFS;
> >> 
> >> And how will the caller know how much is needed?
> > 
> > Duh. I shall update the build_id.len with the appropiate value.
> 
> Ah, actually I now see you have Andrew's beloved NULL handle
> check up a few lines - that may suffice. Albeit I'm not generally in
> favor of this model; I prefer a first attempt to succeed if possible,
> and a second one only to be needed if the caller estimated size in
> fact didn't suffice (and then no 3rd one being necessary in order
> to obtain the needed size).

The code I wrote (libxl) tries with a large buffer (1020 bytes)
and if that didn't work just reports the error.

I shall change the code to follow your steps.
Jan Beulich Jan. 14, 2016, 8:58 a.m. UTC | #5
>>> On 14.01.16 at 03:02, <konrad@kernel.org> wrote:
>> > Or are you suggesting that perhaps the kernel should at boot time
>> > print the build-id (like it does the changset)?
>> 
>> Perhaps, albeit to me that's a bit orthogonal to being able to find out
>> the build ID for a given binary.
> 
> I can make some magic objdump + awk to extract the buildid from
> the hypervisor and deposit as a text file in /usr/../xen/debug?
> Similar to how xen-syms is copied there?
> 
> Would that work?

No, because of ...

> But I am a bit lost of what your use-case is?

... this is about holding a standalone Xen binary in hands, and
wanting to identify its build ID. Not sure how limited the range of
permitted things is in the simplified ELF binary we generate -
perhaps adding a proper PT_NOTE segment there would do?

Jan
Martin Pohlack Jan. 14, 2016, 9:07 a.m. UTC | #6
On 14.01.2016 09:58, Jan Beulich wrote:
>>>> On 14.01.16 at 03:02, <konrad@kernel.org> wrote:
>>>> Or are you suggesting that perhaps the kernel should at boot time
>>>> print the build-id (like it does the changset)?
>>>
>>> Perhaps, albeit to me that's a bit orthogonal to being able to find out
>>> the build ID for a given binary.
>>
>> I can make some magic objdump + awk to extract the buildid from
>> the hypervisor and deposit as a text file in /usr/../xen/debug?
>> Similar to how xen-syms is copied there?
>>
>> Would that work?
> 
> No, because of ...
> 
>> But I am a bit lost of what your use-case is?
> 
> ... this is about holding a standalone Xen binary in hands, and
> wanting to identify its build ID. Not sure how limited the range of
> permitted things is in the simplified ELF binary we generate -
> perhaps adding a proper PT_NOTE segment there would do?

To clarify your question:

  readelf -n xen-syms

should result in finding and dumping the build ID.  The original patch
to xen.lds did achieve that.

Is that enough for you or do you want that to work as well for the
stripped xen file?

Martin
Amazon Development Center Germany GmbH
Berlin - Dresden - Aachen
main office: Krausenstr. 38, 10117 Berlin
Geschaeftsfuehrer: Dr. Ralf Herbrich, Christian Schlaeger
Ust-ID: DE289237879
Eingetragen am Amtsgericht Charlottenburg HRB 149173 B
Jan Beulich Jan. 14, 2016, 9:14 a.m. UTC | #7
>>> On 14.01.16 at 10:07, <mpohlack@amazon.com> wrote:
> On 14.01.2016 09:58, Jan Beulich wrote:
>>>>> On 14.01.16 at 03:02, <konrad@kernel.org> wrote:
>>>>> Or are you suggesting that perhaps the kernel should at boot time
>>>>> print the build-id (like it does the changset)?
>>>>
>>>> Perhaps, albeit to me that's a bit orthogonal to being able to find out
>>>> the build ID for a given binary.
>>>
>>> I can make some magic objdump + awk to extract the buildid from
>>> the hypervisor and deposit as a text file in /usr/../xen/debug?
>>> Similar to how xen-syms is copied there?
>>>
>>> Would that work?
>> 
>> No, because of ...
>> 
>>> But I am a bit lost of what your use-case is?
>> 
>> ... this is about holding a standalone Xen binary in hands, and
>> wanting to identify its build ID. Not sure how limited the range of
>> permitted things is in the simplified ELF binary we generate -
>> perhaps adding a proper PT_NOTE segment there would do?
> 
> To clarify your question:
> 
>   readelf -n xen-syms
> 
> should result in finding and dumping the build ID.  The original patch
> to xen.lds did achieve that.
> 
> Is that enough for you or do you want that to work as well for the
> stripped xen file?

"Stripped" isn't the right term, because the uncompressed variant
of xen.gz is farther away from xen-syms than just being stripped.
But yes, all this is about is that it should be possible to obtain
xen.gz's and xen.efi's build IDs as well.

Jan
Konrad Rzeszutek Wilk Jan. 15, 2016, 9:49 p.m. UTC | #8
>> --- 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
>
> Wouldn't it be better to probe the linker for recognizing the --build-id
> command line option, along the lines of $(cc-option)?

+ld-ver-build-id = $(shell $(1) --build-id 2>&1 | \
+                                       grep -q unrecognized && echo n
|| echo y)

-ish ?

>
> In any event the option should be added to LDFLAGS unless this
> conflicts with something else.

That had some interesting side-effect:

$ find . -name *.o | xargs readelf -n | more
File: ./arch/x86/built_in.o

Displaying notes found at file offset 0x00000040 with length 0x00000240:
  Owner                 Data size       Description
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: a114d1fdec2ace38448f141013f5a659122f2390
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 4a913d3d1ece4d175fc0df0b36745b801f88bfab
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: ead89ba3aa9a8257cfc863966b7a9a725ecce133
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 9b034a93573015c611d0900e949370d9f776bac1
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 0e5fab6126ce69edd5720b96e2d5414618259c78
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 49eca2138553b5e85ee45bb47c52aca394c31c31
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: f1cc2c8ae09fefe1440662efc44208a0b9ff8ddd
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 29991f03f7a1aeeb59c8f83c0e7a349384a7262c
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 3e2c4df9f60fdbd970bd1a35d03c7b68fd794385
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 2c4f5cd9bcf553a022dace08b7741d85a4eb657f
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 41c502289e5b28722ab5df6ae5bd7b99fb90c09e
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: f268afebdf211de6bb6d12e513520bba969130cc
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: b73b7296f6165d3dcacee36691d92ab1996d9908
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: ff8e080d8e01966cf8d893ce6cd258dd0d1c6124
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: dcc8964716f74bb710911d80faaae016820f72d9
  GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
ID bitstring)
    Build ID: 649f4bb66df2fead426edda62d0c90ab088c5fd4


And during build:
ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.

With:
[konrad@char xen]$ readelf -n xen-syms  | grep Build | wc
     38     114    2090

I think we should skip on the LDFLAGS idea.
Jan Beulich Jan. 18, 2016, 8:51 a.m. UTC | #9
>>> On 15.01.16 at 22:49, <konrad@kernel.org> wrote:
>> > --- 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
>>
>> Wouldn't it be better to probe the linker for recognizing the --build-id
>> command line option, along the lines of $(cc-option)?
> 
> +ld-ver-build-id = $(shell $(1) --build-id 2>&1 | \
> +                                       grep -q unrecognized && echo n
> || echo y)
> 
> -ish ?

If that fulfills the purpose - why not?

>> In any event the option should be added to LDFLAGS unless this
>> conflicts with something else.
> 
> That had some interesting side-effect:
> 
> $ find . -name *.o | xargs readelf -n | more
> File: ./arch/x86/built_in.o
> 
> Displaying notes found at file offset 0x00000040 with length 0x00000240:
>   Owner                 Data size       Description
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: a114d1fdec2ace38448f141013f5a659122f2390
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 4a913d3d1ece4d175fc0df0b36745b801f88bfab
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: ead89ba3aa9a8257cfc863966b7a9a725ecce133
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 9b034a93573015c611d0900e949370d9f776bac1
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 0e5fab6126ce69edd5720b96e2d5414618259c78
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 49eca2138553b5e85ee45bb47c52aca394c31c31
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: f1cc2c8ae09fefe1440662efc44208a0b9ff8ddd
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 29991f03f7a1aeeb59c8f83c0e7a349384a7262c
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 3e2c4df9f60fdbd970bd1a35d03c7b68fd794385
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 2c4f5cd9bcf553a022dace08b7741d85a4eb657f
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 41c502289e5b28722ab5df6ae5bd7b99fb90c09e
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: f268afebdf211de6bb6d12e513520bba969130cc
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: b73b7296f6165d3dcacee36691d92ab1996d9908
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: ff8e080d8e01966cf8d893ce6cd258dd0d1c6124
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: dcc8964716f74bb710911d80faaae016820f72d9
>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
> ID bitstring)
>     Build ID: 649f4bb66df2fead426edda62d0c90ab088c5fd4
> 
> 
> And during build:
> ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
> ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
> ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
> 
> With:
> [konrad@char xen]$ readelf -n xen-syms  | grep Build | wc
>      38     114    2090
> 
> I think we should skip on the LDFLAGS idea.

Isn't that merely a result of LDFLAGS being used for both the
linking of the various built_in.o and the final binaries? A fully
shared set of flags for these two pretty distinct operations
doesn't seem very sensible anyway. In fact I wonder how
much of LDFLAGS is actually relevant when passing -r to ld.

Jan
Konrad Rzeszutek Wilk Jan. 19, 2016, 4:05 p.m. UTC | #10
>>> Wouldn't it be better to probe the linker for recognizing the --build-id
>>> command line option, along the lines of $(cc-option)?
>>
>> +ld-ver-build-id = $(shell $(1) --build-id 2>&1 | \
>> +                                       grep -q unrecognized && echo n
>> || echo y)
>>
>> -ish ?
>
> If that fulfills the purpose - why not?

Great. Will use that (after checking it on on SLES10).
>
>>> In any event the option should be added to LDFLAGS unless this
>>> conflicts with something else.
>>
>> That had some interesting side-effect:
>>
>> $ find . -name *.o | xargs readelf -n | more
>> File: ./arch/x86/built_in.o
>>
>> Displaying notes found at file offset 0x00000040 with length 0x00000240:
>>   Owner                 Data size       Description
>>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
>> ID bitstring)
>>     Build ID: a114d1fdec2ace38448f141013f5a659122f2390
>>   GNU                  0x00000014       NT_GNU_BUILD_ID (unique build
>> ID bitstring)
.. snip..
>> And during build:
>> ld: warning: Cannot create .note.gnu.build-id section, --build-id ignored.
.. snip..
>> I think we should skip on the LDFLAGS idea.
>
> Isn't that merely a result of LDFLAGS being used for both the
> linking of the various built_in.o and the final binaries? A fully

True.
> shared set of flags for these two pretty distinct operations
> doesn't seem very sensible anyway. In fact I wonder how
> much of LDFLAGS is actually relevant when passing -r to ld.
>

That would imply that the idea of putting --build-id should be part
only of the final binaries. Which comes back to how this patch was done
originally - only have the --build-id on specific $(LD) lines.

Are you OK if I re-institute the $(build_id) back in the Makefile, perhaps
rename it to $(build_id_linker) to make it more clear?

Thanks.
Jan Beulich Jan. 19, 2016, 4:36 p.m. UTC | #11
>>> On 19.01.16 at 17:05, <konrad@kernel.org> wrote:
> Are you OK if I re-institute the $(build_id) back in the Makefile, perhaps
> rename it to $(build_id_linker) to make it more clear?

Well, perhaps that's the least troublesome route right now, even
if I don't really like it.

Jan
Konrad Rzeszutek Wilk Jan. 19, 2016, 4:47 p.m. UTC | #12
On Tue, Jan 19, 2016 at 09:36:27AM -0700, Jan Beulich wrote:
> >>> On 19.01.16 at 17:05, <konrad@kernel.org> wrote:
> > Are you OK if I re-institute the $(build_id) back in the Makefile, perhaps
> > rename it to $(build_id_linker) to make it more clear?
> 
> Well, perhaps that's the least troublesome route right now, even
> if I don't really like it.

:-)

Thank you for being OK with this.

I can poke at the LD_FLAGS and the prolifieration of various flags in parallel.
Perhaps after the cleanup of the C-and-P states and now the T-states being trapped?
> 
> Jan
>
Konrad Rzeszutek Wilk Jan. 25, 2016, 3:16 p.m. UTC | #13
> 
> > Or are you suggesting that perhaps the kernel should at boot time
> > print the build-id (like it does the changset)?
> 
> Perhaps, albeit to me that's a bit orthogonal to being able to find out
> the build ID for a given binary.


I looked in the mkelf32 and it looks quite easy to make the resulting
xen.gz have the .note section.

But I am at lost for the EFI file. Could you suggest some ideas of what
type of PE/COFF section it should be put in? Or good specs to consult?

Thank you!
Jan Beulich Jan. 25, 2016, 4:10 p.m. UTC | #14
>>> On 25.01.16 at 16:16, <konrad.wilk@oracle.com> wrote:
>>  
>> > Or are you suggesting that perhaps the kernel should at boot time
>> > print the build-id (like it does the changset)?
>> 
>> Perhaps, albeit to me that's a bit orthogonal to being able to find out
>> the build ID for a given binary.
> 
> 
> I looked in the mkelf32 and it looks quite easy to make the resulting
> xen.gz have the .note section.
> 
> But I am at lost for the EFI file. Could you suggest some ideas of what
> type of PE/COFF section it should be put in? Or good specs to consult?

Well, for xen.efi I really don't have any good idea either. Perhaps
we simply need to declare this as going to be deal with by the
intended re-unification of both binaries which Daniel has been
planning?

Jan
Ian Jackson Feb. 17, 2016, 11:37 a.m. UTC | #15
Konrad Rzeszutek Wilk writes ("[PATCH v3 2/3] XENVER_build_id: Provide ld-embedded build-ids (v8)"):
> 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).

I think this commit message is missing some important explanation for
poor ignorant souls like me.

Something like:

  It is possible to have ld record an arbitrary identifier in an ELF,
  which can then be read out with `readelf'.  We also want to provide
  a way for guests to retrieve the same identifier.

  [ xxx do we? Maybe hosting providers would want to hide which of
  their hosts had been updated ]

  We construct the build-id out of [ ???? ]

  There is ???? no impact on users who want reproducible builds [or]
  ???  users who want reproducible builds are expected to use the
  facilities documented in ??? comments in Config.mk [or something]

Ian.
diff mbox

Patch

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 <xen/compile.h>
 #include <xen/version.h>
+#include <xen/types.h>
+#include <xen/string.h>
+#include <xen/elf.h>
+#include <xen/errno.h>
 
 const char *xen_compile_date(void)
 {
@@ -60,3 +64,41 @@  const char *xen_deny(void)
 {
     return "<denied>\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