Bug 1976109 - Improper conversion of large numbers in virConnectDomainEventBlockThresholdCallback handler
Summary: Improper conversion of large numbers in virConnectDomainEventBlockThresholdCa...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux Advanced Virtualization
Classification: Red Hat
Component: libvirt-python
Version: ---
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: 8.5
Assignee: Peter Krempa
QA Contact: lcheng
URL:
Whiteboard:
Depends On:
Blocks: 1948177
TreeView+ depends on / blocked
 
Reported: 2021-06-25 08:30 UTC by Peter Krempa
Modified: 2021-11-16 08:46 UTC (History)
5 users (show)

Fixed In Version: libvirt-python-7.5.0-1.el8
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2021-11-16 07:54:28 UTC
Type: Bug
Target Upstream Version: 7.5.0
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2021:4684 0 None None None 2021-11-16 07:55:15 UTC

Description Peter Krempa 2021-06-25 08:30:38 UTC
Description of problem:
When sufficiently large numbers are reported by the virConnectDomainEventBlockThresholdCallback, they passed to the python handlers as negative numbers due to an overflow happening in the wrapper code:

The event callback has the following prototype:

void
virConnectDomainEventBlockThresholdCallback(virConnectPtr conn, 
					    virDomainPtr dom, 
					    const char * dev, 
					    const char * path, 
					    unsigned long long threshold, 
					    unsigned long long excess, 
					    void * opaque)

I think the problem is in the dispatching code in the python bindings, where we use:

    /* Call the Callback Dispatcher */
    pyobj_ret = PyObject_CallMethod(pyobj_conn,
                                    (char*)"_dispatchDomainEventBlockThresholdCallback",
                                    (char*)"OssiiO",
                                    pyobj_dom, dev, path, threshold, excess,
                                    pyobj_cbData);

The meaning of characters in the third argument is:

i (int) [int]

    Convert a plain C int to a Python integer object.


K (int) [unsigned long long]

    Convert a C unsigned long long to a Python integer object.


Version-Release number of selected component (if applicable):
All versions in existance which support virConnectDomainEventBlockThresholdCallback

How reproducible:
always

Steps to Reproduce:
1. Register threshold callback
2. Exceed it by a large amount
3.

Actual results:


Expected results:


Additional info:

Comment 2 Peter Krempa 2021-06-25 11:57:19 UTC
Fixed upstream:

commit b5cd547bfd7e9dd566de672f76a17aa9229b7c52
Author: Peter Krempa <pkrempa>
Date:   Fri Jun 25 10:46:06 2021 +0200

    Fix BlockThreshold Callback argument conversion once more
    
    The conversion was changed from "OssiiO" to "OssLLO". Unfortunately the
    arguments are unsigned long long, where the proper coversion character
    is 'K'.
    
    Fixes: https://gitlab.com/libvirt/libvirt-python/-/merge_requests/40
    Fixes: fd069ac85c8cf1593587dc9287a3d5eb6bd4bdb9
    Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1976109
    Signed-off-by: Peter Krempa <pkrempa>

Comment 5 Han Han 2021-07-26 07:02:20 UTC
rhel.cpu.iothread.negative_test.disk_attach.delete_without_detach  PASSED on libvirt-7.5.0-1.el9.x86_64

Comment 6 Han Han 2021-07-26 07:05:16 UTC
Sorry for comment5. Restore the previous status...

Comment 7 lcheng 2021-08-04 17:56:49 UTC
Steps to reproduce:

1. Prepare a image.
# qemu-img create -f raw /var/lib/libvirt/images/test-api-block.img 5G

2. Start a guest with a raw disk.
# cat /root/disk.xml 
<disk device="disk" type="file">
    <driver name="qemu" type="raw"/>
    <source file="/var/lib/libvirt/images/test-api-block.img"/>
    <target bus="virtio" dev="vdb"/>
</disk>


3. Set threshold to 3221225472.
# python
Python 3.6.8 (default, Mar 18 2021, 08:58:41) 
[GCC 8.4.1 20200928 (Red Hat 8.4.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import libvirt
>>> conn = libvirt.open()
>>> dom = conn.lookupByName("test")
>>> dom.setBlockThreshold('vdb', 3221225472,0)
0
>>>

4. Run "/usr/share/doc/python3-libvirt/examples/event-test.py" on one terminal to capture event. 
# python /usr/share/doc/python3-libvirt/examples/event-test.py
Using uri 'qemu:///system' and event loop 'poll'

5. Run "mkfs /dev/vdb" command in guest.

6. And then get a negative value.
# python /usr/share/doc/python3-libvirt/examples/event-test.py
Using uri 'qemu:///system' and event loop 'poll'
myDomainEventBlockThresholdCallback: Domain test(7) block device vdb(/var/lib/libvirt/images/test-api-block.img) threshold -1073741824 exceeded by -2147483648
myDomainEventBlockThresholdCallback: Domain test(7) block device vdb[2](/var/lib/libvirt/images/test-api-block.img) threshold -1073741824 exceeded by -2147483648


Verified on python3-libvirt-7.5.0-1.module+el8.5.0+11677+542c8d77.x86_64.
For 6 step,
# python /usr/share/doc/python3-libvirt/examples/event-test.py
Using uri 'qemu:///system' and event loop 'poll'
myDomainEventBlockThresholdCallback: Domain test(3) block device vdb(/var/lib/libvirt/images/test-api-block.img) threshold 3221225472 exceeded by 2147483648
myDomainEventBlockThresholdCallback: Domain test(3) block device vdb[2](/var/lib/libvirt/images/test-api-block.img) threshold 3221225472 exceeded by 2147483648


So move to VERIFIED.

Comment 9 errata-xmlrpc 2021-11-16 07:54:28 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 (virt:av bug fix and enhancement update), 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://access.redhat.com/errata/RHBA-2021:4684


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