RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 680281 - off-by-one in virFileAbsPath can lead to memory corruption
Summary: off-by-one in virFileAbsPath can lead to memory corruption
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 6
Classification: Red Hat
Component: libvirt
Version: 6.1
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Eric Blake
QA Contact: Virtualization Bugs
URL:
Whiteboard:
Depends On:
Blocks: 680289
TreeView+ depends on / blocked
 
Reported: 2011-02-24 22:04 UTC by Eric Blake
Modified: 2011-06-02 06:49 UTC (History)
6 users (show)

Fixed In Version: libvirt-0.8.7-8.el6
Doc Type: Bug Fix
Doc Text:
Clone Of:
: 680289 (view as bug list)
Environment:
Last Closed: 2011-05-19 13:28:14 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2011:0596 0 normal SHIPPED_LIVE libvirt bug fix and enhancement update 2011-05-18 17:56:36 UTC

Description Eric Blake 2011-02-24 22:04:33 UTC
Description of problem:
virFileAbsPath writes past the bounds of a malloc'd array; this can probably be exploited to cause DoS attacks if that overwrite happens to cross a word boundary and corrupt malloc() data structures, although I have not yet tried to find a reproducer test case.

Version-Release number of selected component (if applicable):
libvirt-0.8.7-7.el6
also applies back to upstream 0.7.2, which means this should be cloned to RHEL 5.7 (and if I can come up with a crasher testcase, also to 5.6.z and 6.0.z).

How reproducible:
not sure yet; found by code inspection

Steps to Reproduce:
1.
2.
3.
  
Actual results:


Expected results:


Additional info:
Fixed by upstream patch:

commit 9f5bbe3b926b52c6490346fd3c026546caadaefd
Author: Daniel P. Berrange <berrange>
Date:   Tue Feb 22 17:08:12 2011 +0000

    Fix off-by-1 in virFileAbsPath.
    
    The virFileAbsPath was not taking into account the '/' directory
    separator when allocating memory for combining cwd + path. Convert
    to use virAsprintf to avoid this type of bug completely.
    
    * src/util/util.c: Convert virFileAbsPath to use virAsprintf

Comment 2 Eric Blake 2011-02-24 22:11:06 UTC
related to bug 679164, but the memory bugs in that bug don't extend back to RHEL 5; created this as a separate bug for easier cloning

Comment 6 Eric Blake 2011-02-24 23:28:27 UTC
It turns out that virLogParseOutputs in logging.c is the only client of the faulty virFileAbsPath; this in turn is only called when parsing the environment variable LIBVIRT_LOG_OUTPUTS or the log_outputs line in libvirtd.conf.  The problem only occurs when accessing a problematic log directive of the form <n>:file:relative-path).  A workaround is to always use <n>:file:/absolute-path if it is desired to perform logging via that environment variable or configuration line.  Therefore, I'm debating whether this is severe enough to warrant the hassle of a z-stream fix, or whether it is easy enough to avoid.

Here's a reproducer under valgrind:

$ LIBVIRT_LOG_OUTPUTS='4:file:log' valgrind virsh version
...
==17924== Invalid write of size 1
==17924==    at 0x4A0675F: strcpy (mc_replace_strmem.c:311)
==17924==    by 0x3D6543DE3D: virFileAbsPath (string3.h:107)
==17924==    by 0x3D65431563: virLogParseOutputs (logging.c:768)
==17924==    by 0x3D65472D5A: virInitialize (libvirt.c:337)
==17924==    by 0x3D6547389C: virConnectOpenAuth (libvirt.c:1495)
==17924==    by 0x41B62F: main (virsh.c:10559)
==17924==  Address 0x4c6356f is 0 bytes after a block of size 31 alloc'd

I was not able to quickly find a particular file length of $CWD plus the relative name where the out-of-bounds write would scribble over malloc data (rather than in the allocation padding) to the point of actually causing a crash, but that doesn't rule out the possibility of such a length.

Comment 7 Wayne Sun 2011-02-25 05:26:42 UTC
Verified

build:
RHEL6.1-20110202.n.0

Packages:
libvirt-0.8.7-8.el6.x86_64
valgrind-3.6.0-3.el6.x86_64
qemu-kvm-0.12.1.2-2.143.el6.x86_64
kernel-2.6.32-118.el6.x86_64
libnl-1.1-13.el6.x86_64

Steps:
# LIBVIRT_LOG_OUTPUTS='4:file:log' valgrind virsh version

Output:

LIBVIRT_LOG_OUTPUTS='4:file:log' valgrind virsh version
==10746== Memcheck, a memory error detector
==10746== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==10746== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info
==10746== Command: virsh version
==10746== 
Compiled against library: libvir 0.8.7
Using library: libvir 0.8.7
Using API: QEMU 0.8.7
Running hypervisor: QEMU 0.12.1

==10746== 
==10746== HEAP SUMMARY:
==10746==     in use at exit: 2,962 bytes in 45 blocks
==10746==   total heap usage: 194 allocs, 149 frees, 1,970,457 bytes allocated
==10746== 
==10746== LEAK SUMMARY:
==10746==    definitely lost: 0 bytes in 0 blocks
==10746==    indirectly lost: 0 bytes in 0 blocks
==10746==      possibly lost: 0 bytes in 0 blocks
==10746==    still reachable: 2,962 bytes in 45 blocks
==10746==         suppressed: 0 bytes in 0 blocks

Comment 10 errata-xmlrpc 2011-05-19 13:28:14 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2011-0596.html

Comment 11 Huming Jiang 2011-06-02 06:49:54 UTC
Could reproduce this bug on the following components of rh5.6:

Packages:
libvirt-0.8.2-15.el5
valgrind-3.5.0-1.el5
kernel-2.6.18-238.el5
libnl-1.0-0.10.pre5.5

Steps:
# LIBVIRT_LOG_OUTPUTS='4:file:log' valgrind virsh version

Outputs:

# LIBVIRT_LOG_OUTPUTS='4:file:log' valgrind virsh version
==6569== Memcheck, a memory error detector
==6569== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==6569== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==6569== Command: virsh version
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02CE72BF: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B16C02EC4: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a0 is 0 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02C6E3B1: _IO_default_xsputn (in /lib64/libc-2.5.so)
==6569==    by 0x3B02C43D38: vfprintf (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE72E7: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B16C02EC4: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a0 is 0 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02CE72FD: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B16C02EC4: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a1 is 1 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02CE72BF: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a1 is 1 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02C43762: vfprintf (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE72E7: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a1 is 1 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x3B02CE72FD: __vsnprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B02CE722A: __snprintf_chk (in /lib64/libc-2.5.so)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569==  Address 0x4c501a2 is 2 bytes after a block of size 0 alloc'd
==6569==    at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==6569==    by 0x3B16C02D9B: numa_init (in /usr/lib64/libnuma.so.1)
==6569==    by 0x3B0280D1BA: call_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B0280D2C4: _dl_init (in /lib64/ld-2.5.so)
==6569==    by 0x3B02800AA9: ??? (in /lib64/ld-2.5.so)
==6569==    by 0x1: ???
==6569==    by 0x7FF000946: ???
==6569==    by 0x7FF00094C: ???
==6569== 
==6569== Invalid write of size 1
==6569==    at 0x4A082E7: strcpy (mc_replace_strmem.c:303)
==6569==    by 0x3B17037DA9: virFileAbsPath (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF27: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569==  Address 0x4c53e08 is 0 bytes after a block of size 8 alloc'd
==6569==    at 0x4A05F1D: realloc (vg_replace_malloc.c:476)
==6569==    by 0x3B1702E37E: virReallocN (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17037D87: virFileAbsPath (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF27: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569== 
==6569== Syscall param open(filename) points to unaddressable byte(s)
==6569==    at 0x3B0380E210: __open_nocancel (in /lib64/libpthread-2.5.so)
==6569==    by 0x3B1702DF48: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569==  Address 0x4c53e08 is 0 bytes after a block of size 8 alloc'd
==6569==    at 0x4A05F1D: realloc (vg_replace_malloc.c:476)
==6569==    by 0x3B1702E37E: virReallocN (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17037D87: virFileAbsPath (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF27: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569== 
==6569== Invalid read of size 1
==6569==    at 0x4A06D94: strlen (mc_replace_strmem.c:275)
==6569==    by 0x3B02C798B5: strdup (in /lib64/libc-2.5.so)
==6569==    by 0x3B1702D3B6: virLogDefineOutput (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF76: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569==  Address 0x4c53e08 is 0 bytes after a block of size 8 alloc'd
==6569==    at 0x4A05F1D: realloc (vg_replace_malloc.c:476)
==6569==    by 0x3B1702E37E: virReallocN (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17037D87: virFileAbsPath (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF27: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569== 
==6569== Invalid read of size 1
==6569==    at 0x4A080C0: memcpy (mc_replace_strmem.c:482)
==6569==    by 0x3B1702D3B6: virLogDefineOutput (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF76: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569==  Address 0x4c53e08 is 0 bytes after a block of size 8 alloc'd
==6569==    at 0x4A05F1D: realloc (vg_replace_malloc.c:476)
==6569==    by 0x3B1702E37E: virReallocN (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17037D87: virFileAbsPath (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B1702DF27: virLogParseOutputs (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076D02: virInitialize (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x3B17076E34: virConnectOpenAuth (in /usr/lib64/libvirt.so.0.8.2)
==6569==    by 0x41876A: ??? (in /usr/bin/virsh)
==6569==    by 0x3B02C1D993: (below main) (in /lib64/libc-2.5.so)
==6569== 
error: unable to connect to '/var/run/libvirt/libvirt-sock', libvirtd may need to be started: Connection refused
error: failed to connect to the hypervisor
==6569== 
==6569== HEAP SUMMARY:
==6569==     in use at exit: 21,628 bytes in 386 blocks
==6569==   total heap usage: 651 allocs, 265 frees, 407,408 bytes allocated
==6569== 
==6569== LEAK SUMMARY:
==6569==    definitely lost: 11 bytes in 1 blocks
==6569==    indirectly lost: 0 bytes in 0 blocks
==6569==      possibly lost: 0 bytes in 0 blocks
==6569==    still reachable: 21,617 bytes in 385 blocks
==6569==         suppressed: 0 bytes in 0 blocks
==6569== Rerun with --leak-check=full to see details of leaked memory
==6569== 
==6569== For counts of detected and suppressed errors, rerun with: -v
==6569== ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 4 from 4)


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