Bug 1311058

Summary: libvirt-python: memoryPeek fail with large memory address.
Product: Red Hat Enterprise Linux 7 Reporter: Kairui Song <kasong>
Component: libvirt-pythonAssignee: Pavel Hrdina <phrdina>
Status: CLOSED ERRATA QA Contact: Virtualization Bugs <virt-bugs>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 7.2CC: dyuan, jdenemar, lcheng, mzhan
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: libvirt-python-1.3.2-1.el7 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-11-04 00:12:33 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
patch to fix the bug. none

Description Kairui Song 2016-02-23 09:59:28 UTC
Created attachment 1129687 [details]
patch to fix the bug.

Description of problem:
libvirt-python: memoryPeek fail with 64bit memory address beyond 0x8000000000000000.


Version-Release number of selected component (if applicable):
libvirt-python-1.2.17-2.el7.x86_64


How reproducible:
100%


Steps to Reproduce:

1.Create a guest vm and start it.

2.run follow script in python

>>> import libvirt
>>> conn = libvirt.open()
>>> dom = conn.lookupByName('libvirt_test_api')
>>> dom.memoryPeek(0xffff880000099000, 8, libvirt.VIR_MEMORY_VIRTUAL)


Actual results:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 1436, in memoryPeek
    ret = libvirtmod.virDomainMemoryPeek(self._o, start, size, flags)
OverflowError: long too big to convert


Expected results:

8 byte of memory data at 0xffff880000099000 dumped.


Additional info:

"virsh qemu-monitor-command libvirt_test_api --hmp memsave 0xffff880000099000 8 tmp/memdump" works well.

'memoryPeek' calls 'virDomainMemoryPeek' which expect a unsigned long long as the address.

At libvirt-override.c:7588
> unsigned long long start;
.....
> if (!PyArg_ParseTuple(args, (char *)"OLnI:virDomainMemoryPeek",
>                       &pyobj_domain, &start, &size, &flags))

Using 'L' for PyArg_ParseTuple to parse a unsinged long long caused overflow with address beyond 0x8000000000000000.

Replace with

> if (!PyArg_ParseTuple(args, (char *)"OKnI:virDomainMemoryPeek",
>                       &pyobj_domain, &start, &size, &flags))

L -> K, will fix it.

There are also many other code using 'L' to parse unsigned long long, (generator.py:316, libvirt-override.c:7555 and others), might cause overflow under certain circumstances.

Comment 2 Pavel Hrdina 2016-03-01 13:39:08 UTC
Upstream commit:

commit bc4c7477f02f3085bf2be47998b17fa6589823ab
Author: Pavel Hrdina <phrdina>
Date:   Tue Feb 23 13:45:36 2016 +0100

    libvirt-override: fix PyArg_ParseTuple for unsigned long long

Comment 5 lcheng 2016-03-09 09:11:03 UTC
I can reproduce it in libvirt-python-1.2.17-2.el7.x86_64.

[root@intel-lizardhead-02 ~]# rpm -q libvirt-python
libvirt-python-1.2.17-2.el7.x86_64

[root@intel-lizardhead-02 ~]# python
Python 2.7.5 (default, Oct 11 2015, 17:47:16) 
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn=libvirt.open()
>>> dom=conn.lookupByName('snapshotguest')
>>> dom.memoryPeek(0xffff880000099000, 8, libvirt.VIR_MEMORY_VIRTUAL)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 1436, in memoryPeek
    ret = libvirtmod.virDomainMemoryPeek(self._o, start, size, flags)
OverflowError: long too big to convert
>>>
>>> dom.blockPeek('vda', 0xffff880000099000, 32, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 779, in blockPeek
    ret = libvirtmod.virDomainBlockPeek(self._o, disk, offset, size, flags)
OverflowError: long too big to convert
>>>
>>> dom.memoryPeek(0xffff88, 0xffffff88ffffffff, libvirt.VIR_MEMORY_VIRTUAL)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 1436, in memoryPeek
    ret = libvirtmod.virDomainMemoryPeek(self._o, start, size, flags)
OverflowError: Python int too large to convert to C long
>>>
>>> dom.blockPeek('vda', 0x88, 0xffffff88ffffffff, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 779, in blockPeek
    ret = libvirtmod.virDomainBlockPeek(self._o, disk, offset, size, flags)
OverflowError: Python int too large to convert to C long


============================================================================

Verify version:
[root@intel-lizardhead-02 ~]# rpm -q libvirt-python
libvirt-python-1.3.2-1.el7.x86_64

Steps:

[root@intel-lizardhead-02 ~]# python
Python 2.7.5 (default, Oct 11 2015, 17:47:16) 
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn=libvirt.open()
>>> dom=conn.lookupByName('snapshotguest')
>>> dom.memoryPeek(0xffff880000099000, 8, libvirt.VIR_MEMORY_VIRTUAL)
'\x00\x00\x00\x00\x00\x00\x00\x00'
>>>
>>> dom.blockPeek('vda', 0xffff880000099000, 32, 0)
libvirt: QEMU Driver error : /var/lib/libvirt/images/libvirt-test-api.1457410307: failed to seek or read: Invalid argument
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 786, in blockPeek
    if ret is None: raise libvirtError ('virDomainBlockPeek() failed', dom=self)
libvirt.libvirtError: /var/lib/libvirt/images/libvirt-test-api.1457410307: failed to seek or read: Invalid argument
>>>
>>> dom.memoryPeek(0xffff88, 0xffffff88ffffffff, libvirt.VIR_MEMORY_VIRTUAL)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 1433, in memoryPeek
    ret = libvirtmod.virDomainMemoryPeek(self._o, start, size, flags)
MemoryError
>>>
>>> dom.blockPeek('vda', 0x88, 0xffffff88ffffffff, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/libvirt.py", line 785, in blockPeek
    ret = libvirtmod.virDomainBlockPeek(self._o, disk, offset, size, flags)
MemoryError


No 'OverflowError', move to verified.

Comment 8 errata-xmlrpc 2016-11-04 00:12:33 UTC
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-2186.html