Bug 5356

Summary: debugedit: segment fault while file's bss offset have a large number
Product: [Build System, Metadata & Runtime] OE-Core Reporter: Hongxu Jia <hongxu.jia>
Component: coreAssignee: Hongxu Jia <hongxu.jia>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: Medium CC: hongxu.jia, jessica.zhang, liezhi.yang, mark.hatle, meta.mr.watcher, meta.watcher, Qi.Chen, sgw, yi.zhao
Version: 1.5   
Target Milestone: 1.6   
Hardware: x86   
OS: Multiple   
Whiteboard:
OS type for building Yocto: --- Type of Regression: ---
Verified: Documentation change: Don't know
Attachments:
Description Flags
The file whose bss offset have a large number none

Description Hongxu Jia 2013-10-16 10:25:12 UTC
Created attachment 1566 [details]
The file whose bss offset have a large number

*Environment
$ cat /etc/issue
Ubuntu 13.04 \n \l

$ uname -a
Linux pek-hjia-d1 3.8.0-31-generic #46-Ubuntu SMP Tue Sep 10 20:03:44 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux


*Problem
Segment fault while invoke debugedit to process 'xB.linkhuge' file

Step 1:
touch debugsources.list

Step 2:
$ ls xB.linkhuge -al
-rwxr-xr-x 1 hongxujia hongxujia 1221403 Oct 16 16:14 xB.linkhuge

Step 3:
tmp/sysroots/x86_64-linux/usr/lib/rpm/bin/debugedit -b '/var/src/debug/log' -d '/usr/src/debug' -i -l 'debugsources.list' 'xB.linkhuge'
364d09c997aa5c65b27d030a689363e9b88c6816
Segmentation fault (core dumped)

Step 4:
$ ls -al xB.linkhuge 
-rwxr-xr-x 1 hongxujia hongxujia 2097152 Oct 16 16:14 xB.linkhuge

It only happens at first invoking and the file's bss Offset have a
large number.
$ readelf -a xB.linkhuge
......
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
skip..
  [25] .data             PROGBITS         00000000005128a0  001128a0
       0000000000010168  0000000000000000  WA       0     0     32
  [26] .bss              NOBITS           0000000001000000  00200000
       0000000000010050  0000000000000000  WA       0     0     32
  [27] .comment          PROGBITS         0000000000000000  00122a08
       0000000000000011  0000000000000001  MS       0     0     1
......

*Analysis

In debugedit, it invoked elf_begin with ELF_C_RDWR_MMAP as start, and
invoked elf_update to modify the file and memory, and then invoked elf_end
in the end.

1) While ELF_C_RDWR_MMAP was used, elf_begin invoked mmap() to map file
into memory with the size of '1221403'. Log from strace:
......
open("debugsources.list", O_WRONLY|O_CREAT|O_APPEND|O_LARGEFILE, 0644) = 3
stat64("xB.linkhuge", {st_mode=S_IFREG|0755, st_size=1221403, ...}) = 0
chmod("xB.linkhuge", 0100755)           = 0
open("xB.linkhuge", O_RDWR|O_LARGEFILE) = 4
fcntl64(4, F_GETFL)                     = 0x8002 (flags O_RDWR|O_LARGEFILE)
fstat64(4, {st_mode=S_IFREG|0755, st_size=1221403, ...}) = 0
mmap2(NULL, 1221403, PROT_READ|PROT_WRITE, MAP_SHARED, 4, 0) = 0xb761d000
......

2) While file's bss Offset has a large number '00200000', elf_update
caculated file size by __elf64_updatenull_wrlock and the size was
enlarged.

3) In this situation, elf_update invoked ftruncate to enlarge the file,
and memory size (elf->maximum_size) also was incorrectly updated. Log
from strace:
......
ftruncate64(4, 2097152)                 = 0
msync(0xb761d000, 1216568, MS_SYNC)     = 0
......

4) There was segment fault in elf_end which invoked munmap with the
length is incorrectly enlarged file size '2097152', not the length of
mmap in elf_begin '1216568'. Log from strace:
......
munmap(0xb761d000, 2097152)             = 0
......

*Solution

1) I tried to use ELF_C_RDWR instaed of ELF_C_RDWR_MMAP while invoke
elf_begin, but it failed to modify the file's build_id.

2) I also tried to modify elf library, don't update memory size
(elf->maximum_size) in this situation. It fixed this issue and
everything looks ok, but I am not sure the modification is necessary.
......
 11 diff --git a/libelf/elf_update.c b/libelf/elf_update.c
 12 --- a/libelf/elf_update.c
 13 +++ b/libelf/elf_update.c
 14 @@ -120,7 +120,9 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum)
 15        size = -1;
 16      }
 17 
 18 -  if (size != -1 && elf->parent == NULL)
 19 +  /* If the file is enlarged by truncate, we should not update maximum_size to
 20 +     avoid segment fault while invoking munmap in elf_end */
 21 +  if (size != -1 && elf->parent == NULL && (size_t) size <= elf->maximum_size)
 22      elf->maximum_size = size;
......
Comment 1 Hongxu Jia 2013-10-16 10:29:00 UTC
This defect exists on the Distro's rpm, so I have reported this to upstream.

https://bugzilla.redhat.com/show_bug.cgi?id=1019707
Comment 2 Hongxu Jia 2013-10-18 11:37:17 UTC
The real reason was about elflib also, I have filed another bug to upstream:

https://bugzilla.redhat.com/show_bug.cgi?id=1020842