This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[PATCH 0/1] dwflpp::function_entrypc avoid usage of uninitialized memory
- From: Victor Kamensky <kamensky at cisco dot com>
- To: systemtap at sourceware dot org
- Date: Mon, 9 Jul 2018 09:31:18 -0700
- Subject: [PATCH 0/1] dwflpp::function_entrypc avoid usage of uninitialized memory
Hi Folks,
When I tried to upgrade OpenEmbedded SystemTap version from 3.2 to 3.3 on my
simple unit test that traces bunch of functions in busybox failure was
observed.
After digging into it I believe issue happened because of code path
hits cases where uninitialized memory on stap stack was accessed. I
ended up running test case under valgrind memcheck and fixing
'Conditional jump or move depends on uninitialised value(s)' issues
it reported. That fixed the issue. My patch comes along with this
cover letter.
The rest is my debugging notes that explain and justify proposed
fixes:
Failure after move to 3.3 in OE observed
----------------------------------------
+ SYSTEMTAP_DEBUGINFO_PATH=+:.debug:build
+ /wd10/systemtap/20180707_2/packages6/bin/stap -p4 -m mkdir_func -a x86_64 -B CROSS_COMPILE=/wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/recipe-sysroot-native/usr/bin/x86_64-oe-linux/x86_64-oe-linux- -r /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/linux-qemux86_64-standard-build -I /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/tapset -R /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/runtime --sysroot /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/core-image-minimal/1.0-r0/rootfs-dbg --sysenv=PATH=/usr/sbin:/usr/bin:/sbin:/bin --sysenv=LD_LIBRARY_PATH=/usr/lib:/lib -v mkdir_func.stp
Pass 1: parsed user script and 486 library scripts using 148236virt/89484res/6808shr/82824data kb, in 270usr/30sys/297real ms.
semantic error: libdw failure (dwarf_lineaddr): invalid line index
semantic error: libdw failure (dwarf_lineaddr): invalid line index
WARNING: function _start return probe is blacklisted: keyword at mkdir_func.stp:8:1
source: probe process("mkdir").function("*").return {
^
Pass 2: analyzed script: 2899 probes, 216 functions, 4 embeds, 2 globals using 319972virt/262684res/8280shr/254560data kb, in 3310usr/1690sys/4653real ms.
Pass 2: analysis failed. [man error::pass2]
Script source code
------------------
[kamensky@kamensky-w530 examples]$ cat mkdir_func.stp
# trace all function from mkdir executable; in case
# of core-image-minimal mkdir is /bin/busybox.nosuid
# i.e all function in busybox will be traced
probe process("mkdir").function("*").call {
printf ("%s -> %s\n", thread_indent(1), ppfunc())
}
probe process("mkdir").function("*").return {
printf ("%s <- %s\n", thread_indent(-1), ppfunc())
}
Issue is not observed with default build of release-3.3
-------------------------------------------------------
Default build on FC28 with the following options
--disable-docs \
--disable-publican \
--disable-refdocs \
works OK.
Trying to narrowing difference
------------------------------
When SystemTap is configured with the following options issue is
not observed:
--without-nss \
--without-avahi \
--without-dyninst \
--disable-server \
--disable-grapher \
--enable-prologues \
--disable-docs \
--disable-publican \
--disable-refdocs \
--disable-libvirt \
But after adding --disable-nls issue appears. Issue disappeared after
building code with -O0 or -O1.
GDB Session: catching throw
---------------------------
[kamensky@kamensky-w530 examples]$ gdb /wd10/systemtap/20180707_2/packages6/bin/stap
GNU gdb (GDB) Fedora 8.1-19.fc28
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /wd10/systemtap/20180707_2/packages6/bin/stap...done.
(gdb) set args -p4 -m mkdir_func -a x86_64 -B CROSS_COMPILE=/wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/recipe-sysroot-native/usr/bin/x86_64-oe-linux/x86_64-oe-linux- -r /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/linux-qemux86_64-standard-build -I /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/tapset -R /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/runtime --sysroot /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/core-image-minimal/1.0-r0/rootfs-dbg --sysenv=PATH=/usr/sbin:/usr/bin:/sbin:/bin --sysenv=LD_LIBRARY_PATH=/usr/lib:/lib -v mkdir_func.stp
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) run
Starting program: /wd10/systemtap/20180707_2/packages6/bin/stap -p4 -m mkdir_func -a x86_64 -B CROSS_COMPILE=/wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/recipe-sysroot-native/usr/bin/x86_64-oe-linux/x86_64-oe-linux- -r /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/linux-yocto/4.15.18+gitAUTOINC+45c256a5ca_e25dbfe953-r0/linux-qemux86_64-standard-build -I /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/tapset -R /wd10/oe/20180707/build/tmp-glibc/work/x86_64-linux/systemtap-native/3.3-r0/recipe-sysroot-native/usr/share/systemtap/runtime --sysroot /wd10/oe/20180707/build/tmp-glibc/work/qemux86_64-oe-linux/core-image-minimal/1.0-r0/rootfs-dbg --sysenv=PATH=/usr/sbin:/usr/bin:/sbin:/bin --sysenv=LD_LIBRARY_PATH=/usr/lib:/lib -v mkdir_func.stp
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Pass 1: parsed user script and 486 library scripts using 148236virt/89412res/6700shr/82824data kb, in 270usr/40sys/308real ms.
Catchpoint 1 (exception thrown), 0x00007ffff6699181 in __cxxabiv1::__cxa_throw (obj=obj@entry=0x621c2b0, tinfo=tinfo@entry=0x639678 <typeinfo for semantic_error>, dest=dest@entry=
0x4672e0 <semantic_error::~semantic_error()>) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:78
78 PROBE2 (throw, obj, tinfo);
(gdb) bt
#0 0x00007ffff6699181 in __cxxabiv1::__cxa_throw (obj=obj@entry=0x621c2b0, tinfo=tinfo@entry=0x639678 <typeinfo for semantic_error>,
dest=dest@entry=0x4672e0 <semantic_error::~semantic_error()>) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:78
#1 0x0000000000435d3a in dwarf_assert (desc=..., rc=<optimized out>, file="../systemtap/dwflpp.cxx", line=2437)
#2 0x00000000005d754a in safe_dwarf_lineaddr (line=<optimized out>, errfile="../systemtap/dwflpp.cxx", errline=2437) at /usr/include/c++/8/bits/char_traits.h:320
#3 0x00000000005c6332 in dwflpp::resolve_prologue_endings(std::vector<func_info, std::allocator<func_info> >&) () at ../systemtap/dwflpp.cxx:2437
#4 0x0000000000553f09 in query_cu(Dwarf_Die*, dwarf_query*) () at ../systemtap/tapsets.cxx:2330
#5 0x00000000005cc862 in dwflpp::iterate_over_cus<void> (this=<optimized out>, callback=callback@entry=0x553810 <query_cu(Dwarf_Die*, dwarf_query*)>, data=data@entry=0x7fffffff9890,
want_types=want_types@entry=false) at ../systemtap/dwflpp.cxx:477
#6 0x0000000000554ecf in dwflpp::iterate_over_cus<dwarf_query> (want_types=false, data=0x7fffffff9890, callback=0x553810 <query_cu(Dwarf_Die*, dwarf_query*)>, this=<optimized out>)
at ../systemtap/tapsets.cxx:1131
#7 dwarf_query::query_module_dwarf() () at ../systemtap/tapsets.cxx:1131
#8 0x0000000000555460 in dwarf_query::handle_query_module (this=0x7fffffff9890) at ../systemtap/tapsets.cxx:1228
#9 0x0000000000528334 in query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*) () at ../systemtap/tapsets.cxx:2642
#10 0x00007ffff73470c1 in dwfl_getmodules (dwfl=0x5b37ad0, callback=callback@entry=0x527ea0 <query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*)>,
arg=arg@entry=0x7fffffff9890, offset=offset@entry=0) at dwfl_getmodules.c:86
#11 0x00000000005bda33 in dwflpp::iterate_over_modules<void> (this=this@entry=0x5b37680,
callback=callback@entry=0x527ea0 <query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*)>, data=data@entry=0x7fffffff9890) at ../systemtap/dwflpp.cxx:409
#12 0x000000000054cae4 in dwflpp::iterate_over_modules<base_query> (data=0x7fffffff9890,
callback=0x527ea0 <query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*)>, this=0x5b37680) at ../systemtap/tapsets.cxx:8621
#13 dwarf_builder::build(systemtap_session&, probe*, probe_point*, std::map<interned_string, literal*, std::less<interned_string>, std::allocator<std::pair<interned_string const, literal*> > > const&, std::vector<derived_probe*, std::allocator<derived_probe*> >&) () at ../systemtap/tapsets.cxx:8621
#14 0x00000000004b2b57 in match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) () at ../systemtap/elaborate.cxx:474
#15 0x00000000004b3334 in match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) () at ../systemtap/elaborate.cxx:648
#16 0x00000000004b3334 in match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) () at ../systemtap/elaborate.cxx:648
#17 0x00000000004b3334 in match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) () at ../systemtap/elaborate.cxx:648
#18 0x00000000004b3c9e in derive_probes(systemtap_session&, probe*, std::vector<derived_probe*, std::allocator<derived_probe*> >&, bool, bool) () at ../systemtap/elaborate.cxx:1022
#19 0x00000000004b4753 in semantic_pass_symbols(systemtap_session&) () at ../systemtap/elaborate.cxx:1890
#20 0x00000000004c1cda in semantic_pass(systemtap_session&) () at ../systemtap/elaborate.cxx:2441
#21 0x000000000044d5ba in passes_0_4(systemtap_session&) () at ../systemtap/main.cxx:945
#22 0x0000000000447727 in main () at ../systemtap/main.cxx:1412
#23 0x00007ffff77c218b in __libc_start_main (main=0x446f80 <main>, argc=20, argv=0x7fffffffce98, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffce88) at ../csu/libc-start.c:308
#24 0x0000000000449cfa in _start () at /usr/include/c++/8/bits/char_traits.h:285
(gdb) f 3
#3 0x00000000005c6332 in dwflpp::resolve_prologue_endings(std::vector<func_info, std::allocator<func_info> >&) () at ../systemtap/dwflpp.cxx:2437
2437 postprologue_addr = DWARF_LINEADDR(lr);
(gdb) list
2432 Dwarf_Addr postprologue_addr = DWARF_LINEADDR(postprologue_srcline);
2433 if (dwarf_haspc (& it->die, postprologue_addr) != 1)
2434 {
2435 // pick addr of previous line record
2436 Dwarf_Line *lr = dwarf_onesrcline(lines, postprologue_srcline_idx-1);
2437 postprologue_addr = DWARF_LINEADDR(lr);
2438 }
2439
2440 it->prologue_end = postprologue_addr;
2441
(gdb) p lr
$1 = (Dwarf_Line *) 0x0
Running under valgrind
----------------------
==23083== Parent PID: 23082
==23083==
==23083== Conditional jump or move depends on uninitialised value(s)
==23083== at 0x5BDC56: dwflpp::function_entrypc(unsigned long*) (dwflpp.cxx:2477)
==23083== by 0x51FB81: query_dwarf_func(Dwarf_Die*, dwarf_query*) (tapsets.cxx:2265)
==23083== by 0x5CE4D3: int dwflpp::iterate_over_functions<void>(int (*)(Dwarf_Die*, void*), void*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > con
st&) (dwflpp.cxx:1038)
==23083== by 0x5539B8: iterate_over_functions<dwarf_query> (dwflpp.h:283)
==23083== by 0x5539B8: query_cu(Dwarf_Die*, dwarf_query*) (tapsets.cxx:2321)
==23083== by 0x5CC861: void dwflpp::iterate_over_cus<void>(int (*)(Dwarf_Die*, void*), void*, bool) (dwflpp.cxx:477)
==23083== by 0x554ECE: iterate_over_cus<dwarf_query> (dwflpp.h:252)
==23083== by 0x554ECE: dwarf_query::query_module_dwarf() (tapsets.cxx:1131)
==23083== by 0x55545F: dwarf_query::handle_query_module() (tapsets.cxx:1228)
==23083== by 0x528333: query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*) (tapsets.cxx:2642)
==23083== by 0x56CC0C0: dwfl_getmodules (dwfl_getmodules.c:86)
==23083== by 0x54CAE3: iterate_over_modules<base_query> (dwflpp.h:238)
==23083== by 0x54CAE3: dwarf_builder::build(systemtap_session&, probe*, probe_point*, std::map<interned_string, literal*, std::less<interned_string>, std::allocator<std::pair<interne
d_string const, literal*> > > const&, std::vector<derived_probe*, std::allocator<derived_probe*> >&) (tapsets.cxx:8621)
==23083== by 0x4B2B56: match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std:
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) (elaborate.cxx:474)
==23083== by 0x4B3333: match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std:
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) (elaborate.cxx:648)
==23083==
Second uninitialized use (after addr issue is fixed). Issue with start.
==15397== Conditional jump or move depends on uninitialised value(s)
==15397== at 0x51FB8D: query_dwarf_func(Dwarf_Die*, dwarf_query*) (tapsets.cxx:2265)
==15397== by 0x5CE4B3: int dwflpp::iterate_over_functions<void>(int (*)(Dwarf_Die*, void*), void*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (dwflpp.cxx:1038)
==15397== by 0x553998: iterate_over_functions<dwarf_query> (dwflpp.h:283)
==15397== by 0x553998: query_cu(Dwarf_Die*, dwarf_query*) (tapsets.cxx:2321)
==15397== by 0x5CC841: void dwflpp::iterate_over_cus<void>(int (*)(Dwarf_Die*, void*), void*, bool) (dwflpp.cxx:477)
==15397== by 0x554EAE: iterate_over_cus<dwarf_query> (dwflpp.h:252)
==15397== by 0x554EAE: dwarf_query::query_module_dwarf() (tapsets.cxx:1131)
==15397== by 0x55543F: dwarf_query::handle_query_module() (tapsets.cxx:1228)
==15397== by 0x528343: query_module(Dwfl_Module*, void**, char const*, unsigned long, base_query*) (tapsets.cxx:2642)
==15397== by 0x56CC0C0: dwfl_getmodules (dwfl_getmodules.c:86)
==15397== by 0x54CAB3: iterate_over_modules<base_query> (dwflpp.h:238)
==15397== by 0x54CAB3: dwarf_builder::build(systemtap_session&, probe*, probe_point*, std::map<interned_string, literal*, std::less<interned_string>, std::allocator<std::pair<interned_string const, literal*> > > const&, std::vector<derived_probe*, std::allocator<derived_probe*> >&) (tapsets.cxx:8621)
==15397== by 0x4B2B56: match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) (elaborate.cxx:474)
==15397== by 0x4B3333: match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) (elaborate.cxx:648)
==15397== by 0x4B3333: match_node::find_and_build(systemtap_session&, probe*, probe_point*, unsigned int, std::vector<derived_probe*, std::allocator<derived_probe*> >&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) (elaborate.cxx:648)
==15397==
After fixing above two issues, everything looks OK
--------------------------------------------------
iff --git a/dwflpp.cxx b/dwflpp.cxx
index bfbb6b096..2172e705a 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -2465,13 +2465,17 @@ bool
dwflpp::function_entrypc (Dwarf_Addr * addr)
{
assert (function);
+
+ // assign default value
+ *addr = 0;
+
// PR10574: reject 0, which tends to be eliminated COMDAT
if (dwarf_entrypc (function, addr) == 0 && *addr != 0)
return true;
/* Assume the entry pc is the base address, or (if zero)
the first address of the ranges covering this DIE. */
- Dwarf_Addr start, end;
+ Dwarf_Addr start = 0, end;
if (dwarf_ranges (function, 0, addr, &start, &end) >= 0)
{
if (*addr == 0)
--
2.17.1
Victor Kamensky (1):
dwflpp::function_entrypc avoid usage of uninitialized memory
dwflpp.cxx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--
2.17.1