Bug 1295801 - buffer overflow in refresh_proc_net_softnet
buffer overflow in refresh_proc_net_softnet
Status: CLOSED ERRATA
Product: Red Hat Enterprise Linux 6
Classification: Red Hat
Component: pcp (Show other bugs)
6.8
i686 Unspecified
unspecified Severity unspecified
: rc
: ---
Assigned To: Nathan Scott
Miloš Prchlík
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2016-01-05 08:46 EST by Miloš Prchlík
Modified: 2016-05-10 17:13 EDT (History)
5 users (show)

See Also:
Fixed In Version: pcp-3.10.9-3.el6
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2016-05-10 17:13:24 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Miloš Prchlík 2016-01-05 08:46:38 EST
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:
Comment 1 Miloš Prchlík 2016-01-05 08:56:49 EST
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.
Comment 2 Nathan Scott 2016-01-05 17:44:17 EST
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!
Comment 4 Miloš Prchlík 2016-02-08 04:50:21 EST
Verified for build pcp-3.10.9-5.el6.
Comment 6 errata-xmlrpc 2016-05-10 17:13:24 EDT
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

Note You need to log in before you can comment on or make changes to this bug.