Re: [PATCH] libdwfl: Use process_vm_readv when available.
On Tue, 2018-03-20 at 23:32 +0100, Mark Wielaard wrote: > On Sun, Mar 18, 2018 at 01:43:23AM +0100, Mark Wielaard wrote: > > If possible use process_vm_readv to read 4K blocks instead of fetching > > each word individually with ptrace. For unwinding this often means we > > only have to do one process_vm_readv of the stack instead of dozens of > > ptrace calls. There is one 4K cache per process, cleared whenever a > > thread is detached. > > It seems to work well, but the GCC undefined sanitizer > (configure --enable-sanitize-undefined) found an issue in the > run-backtrace-native-biarch.sh testcase (from x86_64 to i686) > when reading unaligned data. To fix that don't assign to the > Dwarf_Word directly when unaligned, but use memcpy (which gcc > seems to inline). I pushed this to master now. Adding some comments about the word size being actually architecture defined even though we use a 64bit Dwarf_Word everywhere. Cheers, Mark
[Bug tools/23011] New: Infinite loop in handle_sysv_hash (src/readelf.c)
https://sourceware.org/bugzilla/show_bug.cgi?id=23011 Bug ID: 23011 Summary: Infinite loop in handle_sysv_hash (src/readelf.c) Product: elfutils Version: unspecified Status: UNCONFIRMED Severity: normal Priority: P2 Component: tools Assignee: unassigned at sourceware dot org Reporter: traceprobe at gmail dot com CC: elfutils-devel at sourceware dot org Target Milestone: --- Created attachment 10920 --> https://sourceware.org/bugzilla/attachment.cgi?id=10920&action=edit poc for readelf In elfutils version 0.170 and commit afffdff29228db03e2131af577f58a22aec6c1fe, there is an infinite loop in handle_sysv_hash function of src/readelf.c, which can be triggered by the POC below. The issue happens since when processing System V-style hash table, the loop value could be manipulated by input file. For instance in line 3150, if chain[1] = 1, the program falls in infinite loop. 3108 static void 3109 handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) 3110 { ... 3141 for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) 3142 { 3143 Elf32_Word inner = bucket[cnt]; 3144 while (inner > 0 && inner < nchain) 3145 { 3146 ++nsyms; 3147 if (maxlength < ++lengths[cnt]) 3148 ++maxlength; 3149 3150 inner = chain[inner]; 3151 } 3152 } To reproduce the issue, run: ./eu-readelf -a $POC The full stack trace is: 0x0040d78f in handle_sysv_hash (ebl=0x639670, scn=0x639238, shdr=0x7fffdae0, shstrndx=256) at /home/test/test/./elfutils/master/src/src/readelf.c:3144 3144 while (inner > 0 && inner < nchain) (gdb) bt #0 0x0040d78f in handle_sysv_hash (ebl=0x639670, scn=0x639238, shdr=0x7fffdae0, shstrndx=256) at /home/test/test/./elfutils/master/src/src/readelf.c:3144 #1 0x0040e24c in handle_hash (ebl=0x639670) at /home/test/test/./elfutils/master/src/src/readelf.c:3360 #2 0x0040615d in process_elf_file (dwflmod=0x639340, fd=3) at /home/test/test/./elfutils/master/src/src/readelf.c:915 #3 0x00405747 in process_dwflmod (dwflmod=0x639340, userdata=0x639350, name=0x6394e0 "poc/id:00,src:000294,op:flip1,pos:51.", base=0, arg=0x7fffdd50) at /home/test/test/./elfutils/master/src/src/readelf.c:707 #4 0x77ba4c96 in dwfl_getmodules (dwfl=0x639000, callback=0x4056a9 , arg=0x7fffdd50, offset=0) at /home/test/test/./elfutils/master/src/libdwfl/dwfl_getmodules.c:86 #5 0x00405c2d in process_file (fd=3, fname=0x7fffe2b9 "poc/id:00,src:000294,op:flip1,pos:51.", only_one=true) at /home/test/test/./elfutils/master/src/src/readelf.c:806 #6 0x0040461e in main (argc=3, argv=0x7fffdf88) at /home/test/test/./elfutils/master/src/src/readelf.c:322 -- You are receiving this mail because: You are on the CC list for the bug.
[Bug tools/23011] Infinite loop in handle_sysv_hash (src/readelf.c)
https://sourceware.org/bugzilla/show_bug.cgi?id=23011 Mark Wielaard changed: What|Removed |Added CC||mark at klomp dot org --- Comment #1 from Mark Wielaard --- ewww nasty. The idea is that the bucket entries point to the (first) symbol for a particular hash. If that symbol is not the one needed then you look whether there are other symbols with the same hash value in the chain. There are as many chain entries as symbols, and for each symbol n, chain[n] is either zero if there are no other symbols with the same hash, or it is the value of the next symbol with the same hash (for the last one the chain entry is zero). There are obviously not supposed to be "loops" in the chain. The easiest to check would be the limit the number of chains to follow to the number of symbols, which is equal the total number of chain entries (nchain). Note that the same could happen in handle_sysv_hash64 which uses the same kind of bucket chain loop. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug tools/23011] Infinite loop in handle_sysv_hash (src/readelf.c)
https://sourceware.org/bugzilla/show_bug.cgi?id=23011 Mark Wielaard changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2018-03-28 Ever confirmed|0 |1 --- Comment #2 from Mark Wielaard --- Proposed fix: https://sourceware.org/ml/elfutils-devel/2018-q1/msg00118.html -- You are receiving this mail because: You are on the CC list for the bug.
[PATCH] readelf: Break sysv[64] symbol hash bucket chain loops.
The bucket chain should not contain loops. If it does we should mark the hash bucket chain as invalid. This is easily checked by noticing when we have seen more than the number of chain elements. Which equals the max number as symbols in the table. https://sourceware.org/bugzilla/show_bug.cgi?id=23011 Signed-off-by: Mark Wielaard --- src/ChangeLog | 6 ++ src/readelf.c | 8 2 files changed, 14 insertions(+) diff --git a/src/ChangeLog b/src/ChangeLog index 1ad6b3d..e8bd6bf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2018-03-28 Mark Wielaard + + * readelf.c (handle_sysv_hash): Break bucket chain after nchain + entries are found. + (handle_sysv_hash64): Likewise. + 2018-03-27 Mark Wielaard * readelf.c (attr_callback): Print dwarf_dieoffset as %PRIx64, diff --git a/src/readelf.c b/src/readelf.c index 4e35b61..226b19b 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -3141,9 +3141,13 @@ handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt) { Elf32_Word inner = bucket[cnt]; + Elf32_Word chain_len = 0; while (inner > 0 && inner < nchain) { ++nsyms; + ++chain_len; + if (chain_len > nchain) + goto invalid_data; if (maxlength < ++lengths[cnt]) ++maxlength; @@ -3198,9 +3202,13 @@ handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx) for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt) { Elf64_Xword inner = bucket[cnt]; + Elf64_Xword chain_len = 0; while (inner > 0 && inner < nchain) { ++nsyms; + ++chain_len; + if (chain_len > nchain) + goto invalid_data; if (maxlength < ++lengths[cnt]) ++maxlength; -- 1.8.3.1
Re: [PATCH] libdwfl: Use process_vm_readv when available.
On Wed, Mar 28, 2018 at 04:33:26PM +0200, Mark Wielaard wrote: > On Tue, 2018-03-20 at 23:32 +0100, Mark Wielaard wrote: > > On Sun, Mar 18, 2018 at 01:43:23AM +0100, Mark Wielaard wrote: > > > If possible use process_vm_readv to read 4K blocks instead of fetching > > > each word individually with ptrace. For unwinding this often means we > > > only have to do one process_vm_readv of the stack instead of dozens of > > > ptrace calls. There is one 4K cache per process, cleared whenever a > > > thread is detached. > > > > It seems to work well, but the GCC undefined sanitizer > > (configure --enable-sanitize-undefined) found an issue in the > > run-backtrace-native-biarch.sh testcase (from x86_64 to i686) > > when reading unaligned data. To fix that don't assign to the > > Dwarf_Word directly when unaligned, but use memcpy (which gcc > > seems to inline). > > I pushed this to master now. Adding some comments about the word size > being actually architecture defined even though we use a 64bit > Dwarf_Word everywhere. Thanks! -- ldv signature.asc Description: PGP signature