Hide Forgot
Description of problem: Running pminfo with specific arguments - I'm not sure if the actual code flow isn't influenced by the box pminfo runs on in this case - leads to buffer overflow, and pminfo is killed. [root@sheep-2 ~]# pminfo -L -K clear -K add,60,/var/lib/pcp/pmdas/linux/pmda_linux.so,linux_init -f network.softnet.cpu_collision network.softnet.dropped network.softnet.flow_limit_count network.softnet.processed network.softnet.received_rps network.softnet.time_squeeze *** buffer overflow detected ***: pminfo terminated ======= Backtrace: ========= /lib/libc.so.6(__fortify_fail+0x4d)[0x5a9e1d] /lib/libc.so.6[0x5a7e5a] /lib/libc.so.6[0x5a710a] /var/lib/pcp/pmdas/linux/pmda_linux.so(+0x15c6d)[0x670c6d] /var/lib/pcp/pmdas/linux/pmda_linux.so(+0x9f86)[0x664f86] /var/lib/pcp/pmdas/linux/pmda_linux.so(+0xa27f)[0x66527f] /usr/lib/libpcp.so.3(__pmFetchLocal+0x2e3)[0x5c4a263] /usr/lib/libpcp.so.3(pmFetch+0x3d0)[0x5c22970] pminfo[0x8049994] pminfo[0x804a7e1] /lib/libc.so.6(__libc_start_main+0xe6)[0x4c3d36] pminfo[0x8048e21] ======= Memory map: ======== ... Aborted (core dumped) [root@sheep-2 ~]# Using gdb to get further: [root@sheep-2 ~]# gdb pminfo GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6) Copyright (C) 2010 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 "i686-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /usr/bin/pminfo...Reading symbols from /usr/lib/debug/usr/bin/pminfo.debug...done. done. (gdb) (gdb) (gdb) (gdb) r -L -K clear -K add,60,/var/lib/pcp/pmdas/linux/pmda_linux.so,linux_init -f network.softnet.cpu_collision network.softnet.dropped network.softnet.flow_limit_count network.softnet.processed network.softnet.received_rps network.softnet.time_squeeze Starting program: /usr/bin/pminfo -L -K clear -K add,60,/var/lib/pcp/pmdas/linux/pmda_linux.so,linux_init -f network.softnet.cpu_collision network.softnet.dropped network.softnet.flow_limit_count network.softnet.processed network.softnet.received_rps network.softnet.time_squeeze [Thread debugging using libthread_db enabled] *** buffer overflow detected ***: /usr/bin/pminfo terminated ======= Backtrace: ========= <... snip ... > Program received signal SIGABRT, Aborted. 0x00110424 in __kernel_vsyscall () (gdb) (gdb) bt #0 0x00110424 in __kernel_vsyscall () #1 0x004d7871 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #2 0x004d914a in abort () at abort.c:92 #3 0x00517735 in __libc_message (do_abort=2, fmt=0x605290 "*** %s ***: %s terminated\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:198 #4 0x005a9e1d in __fortify_fail (msg=0x605236 "buffer overflow detected") at fortify_fail.c:32 #5 0x005a7e5a in __chk_fail () at chk_fail.c:29 #6 0x005a710a in __strcat_chk (dest=0x134a20 "%08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx ", src=0x12a314 "%08llx ", destlen=<value optimized out>) at strcat_chk.c:51 #7 0x00126c6d in strcat (proc_net_softnet=0x134280) at /usr/include/bits/string3.h:144 #8 refresh_proc_net_softnet (proc_net_softnet=0x134280) at proc_net_softnet.c:44 #9 0x0011af86 in linux_refresh (pmda=0x804eb60, need_refresh=0xbfffee30, context=0) at pmda.c:4585 #10 0x0011b27f in linux_fetch (numpmid=6, pmidlist=0x805d008, resp=0xbfffefd4, pmda=0x804eb60) at pmda.c:6377 #11 0x05c4a263 in __pmFetchLocal (ctxp=0x804e198, numpmid=6, pmidlist=0x804e130, result=0xbffff1f8) at fetchlocal.c:131 #12 0x05c22970 in pmFetch (numpmid=6, pmidlist=0x804e130, result=0xbffff1f8) at fetch.c:147 #13 0x08049994 in report () at pminfo.c:359 #14 0x0804a7e1 in main (argc=13, argv=0xbffff334) at pminfo.c:692 (gdb) frame 8 #8 refresh_proc_net_softnet (proc_net_softnet=0x134280) at proc_net_softnet.c:44 44 strcat(fmt, "%08llx "); (gdb) Looking at fmt in refresh_proc_net_softnet() I wonder if it is big enough: int refresh_proc_net_softnet(proc_net_softnet_t *proc_net_softnet) { <... snip ...> static char fmt[11*7] = { '\0' }; /* 7 == strlen("%08llx ") */ if (fmt[0] == '\0') { int i; /* * one trip initialization to decide the correct sscanf format * for a uint64_t data type .. needs to be * "%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" * or * "%08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx %08llx" */ fmt[0] = '\0'; if (strcmp(FMT_INT64, "lld") == 0) { for (i = 0; i < 11; i++) strcat(fmt, "%08llx "); <=== line 44 } According to backtrace (frame #6) fmt contains 11 formatting groups by this time, and I'd say fmt is 1 byte short - 11 * 7 is enough for 11 groups but the last \0 can't fit in. I did some stepping exercise in gdb, and this idea of mine seems to be correct. Version-Release number of selected component (if applicable): pcp-3.10.9-2.el6.i686 How reproducible: Steps to Reproduce: 1. 2. 3. Actual results: Expected results: Additional info:
Setting Hardware to i686 - the branch in question gets executed when FMT_INT64 == "lld" which in this RHEL is just x86 only, IMHO. On other arches, "%08lx " is short enough to fit 11 times into fmt, including the last '\0'. Also, on other arches in my test run this command runs fine, and provides some network-related data.
mgoodwin and I both had a look this morning and your analysis is spot on as usual Miloš - your fix will flow upstream shortly & a pcp-3.10.9-3 will follow soon. Thanks!
Verified for build pcp-3.10.9-5.el6.
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://rhn.redhat.com/errata/RHBA-2016-0825.html