Re: kvmtool: invalid embedded ELF binaries' size

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Here's a quick shell script which reproduces the bug with a PIE program:

 $ ./pie.sh
   3: 0000000000000004 0 NOTYPE GLOBAL DEFAULT ABS _binary_bar_txt_size
   9: 0000000000000004 0 NOTYPE GLOBAL DEFAULT ABS _binary_bar_txt_size
  50: 0000000000000004 0 NOTYPE GLOBAL DEFAULT ABS _binary_bar_txt_size
 0x563bd4d39004

Expected value is 0x4 while 0x563bd4d39004 is printed because
_binary_bar_txt_size is relocated. According to man 5 elf,

    SHN_ABS       This value specifies absolute values  for  the
                  corresponding reference.  For example, symbols
                  defined relative  to  section  number  SHN_ABS
                  have  absolute  values and are not affected by
                  relocation.

_binary_bar_txt_size shouldn't be relocated, but I don't know if it
makes sense to use the address of an absolute symbol in a PIE binary.

The patch sent in the following mail fixes this issue.

On 01/04/2017 06:19 PM, G. Campana wrote:
> Hello,
> 
> My previous analysis of this issue is wrong. Here's the output of nm:
> 
>     $ nm guest/guest_pre_init.o
>     0000000000000310 D _binary_guest_pre_init_end
>     0000000000000310 A _binary_guest_pre_init_size
>     0000000000000000 D _binary_guest_pre_init_start
> 
>     $ nm lkvm | grep guest_pre_init
>     0000000000233788 D _binary_guest_pre_init_end
>     0000000000000310 A _binary_guest_pre_init_size
>     0000000000233478 D _binary_guest_pre_init_start
> 
> According to nm manpage:
> 
>     "A" The symbol's value is absolute, and will not be changed by
> further linking.
> 
> But debugging lkvm with gdb clearly shows that the value of
> _binary_guest_pre_init_size changes and is relocated:
> 
>     $ rm -rf ~/.lkvm/blah/
>     $ gdb -q lkvm
>     gdb$ x/2i kvm_setup_guest_init
>        0x8c60 <kvm_setup_guest_init>:       push   rbx
>        0x8c61 <kvm_setup_guest_init+1>:     lea
> rcx,[rip+0xffffffffffff76a8]        # 0x310
> 
>     gdb$ r setup blah
>     [code]
>     => 0x55555555cc60 <kvm_setup_guest_init>:       push   rbx
>        0x55555555cc61 <kvm_setup_guest_init+1>:     lea
> rcx,[rip+0xffffffffffff76a8]        # 0x555555554310
>     Breakpoint 1, kvm_setup_guest_init (guestfs_name=0x7fffffffe33a
> "blah") at builtin-setup.c:156
> 
> So I finally think this is an issue in gcc...
> 
> On 01/03/2017 03:57 PM, G. Campana wrote:
>> Hi,
>>
>> I just noticed that a typo is present in the original subject (kvmtool
>> is misspelled.) I assume that some of you filter messages according to
>> their subject, hence this new mail.
>>
>> Sorry for the spam.
>>
>> -------- Forwarded Message --------
>> Subject: kmvtool: invalid embedded ELF binaries' size
>> Date: Mon, 2 Jan 2017 15:04:50 +0100
>> To: kvm@xxxxxxxxxxxxxxx
>>
>> Hi,
>>
>> A user of the NoFear project reported a bug (
>> https://github.com/cappsule/nofear/issues/6 ) suggesting that kvmtool is
>> broken if compiled with a specific gcc version. This issue can be
>> reproduced with gcc version 6.2.1 20161124 (Debian 6.2.1-5), but not
>> with gcc version 6.1.1 20160802 (Debian 6.1.1-11).
>>
>> The function extract_file() writes embedded ELF files to the filesystem:
>>
>>     static int extract_file(const char *guestfs_name, const char *filename,
>> 			    const void *data, const void *_size)
>>         ...
>> 	    ret = xwrite(fd, data, (size_t)_size);
>>         ...
>>     }
>>
>>     extern char _binary_guest_init_start;
>>     extern char _binary_guest_init_size;
>>     extern char _binary_guest_pre_init_start;
>>     extern char _binary_guest_pre_init_size;
>>
>> I didn't manage to find how _binary_guest_init_size and
>> _binary_guest_pre_init_size are created during the link step, but a
>> quick debug session shows that they're 4 bytes wide:
>>
>>     (gdb) disass kvm_setup_guest_init
>>     Dump of assembler code for function kvm_setup_guest_init:
>>     => 0x00005599b846dc60 <+0>:     push   rbx
>>        0x00005599b846dc61 <+1>:     lea    rcx,[rip+0xffffffffffff76a8]
>>       # 0x5599b8465310
>>        0x00005599b846dc68 <+8>:     lea    rdx,[rip+0x22a809]        #
>> 0x5599b8698478
>>        0x00005599b846dc6f <+15>:    lea    rsi,[rip+0x18a2c]        #
>> 0x5599b84866a2
>>        0x00005599b846dc76 <+22>:    mov    rbx,rdi
>>        0x00005599b846dc79 <+25>:    call   0x5599b846d9e0 <extract_file>
>>        ...
>>     (gdb) x/xw 0x5599b8465310
>>     0x5599b8465310: 0x000004c2
>>     (gdb) x/xg 0x5599b8465310
>>     0x5599b8465310: 0x00000012000004c2
>>
>> Casting _size to size_t in extract_file() is wrong because _size is 4
>> bytes wide. On x64, xwrite thus fails when the 4 bytes following
>> _binary_guest_init_size/_binary_guest_pre_init_size are different than 0.
>>
>> I think that casting _size to unsigned int should fix this issue, but I
>> would appreciate if someone can explain how _binary_guest_init_size and
>> _binary_guest_pre_init_size are produced by the linker.
>>
>> Thanks
>>

Attachment: pie.sh
Description: application/shellscript


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux