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 2040610 - the libnbd OCaml bindings map C's "uint32_t" type to OCaml's "int32" type
Summary: the libnbd OCaml bindings map C's "uint32_t" type to OCaml's "int32" type
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 9
Classification: Red Hat
Component: libnbd
Version: 9.0
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Laszlo Ersek
QA Contact: Vera
URL:
Whiteboard:
: 2040609 (view as bug list)
Depends On:
Blocks: 2027598
TreeView+ depends on / blocked
 
Reported: 2022-01-14 08:46 UTC by Laszlo Ersek
Modified: 2022-05-17 13:12 UTC (History)
9 users (show)

Fixed In Version: libnbd-1.10.3-1.el9
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2022-05-17 12:51:02 UTC
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RHELPLAN-108160 0 None None None 2022-01-14 08:50:36 UTC
Red Hat Product Errata RHEA-2022:2409 0 None None None 2022-05-17 12:51:16 UTC

Description Laszlo Ersek 2022-01-14 08:46:57 UTC
* Description of problem:
Dependent on the guest disk image being copied with virt-v2v, if there is a segment >= 2GiB in size with identical block allocation status, NBD.block_status will return an entry with negative "length" in the entries array.

* Version-Release number of selected component (if applicable):
libnbd-1.10.2-1.el9

* How reproducible:
Dependent on the guest disk image being copied with virt-v2v, if there is a segment >= 2GiB in size with identical block allocation status, NBD.block_status will return an entry with negative "length" in the entries array.

* Steps to Reproduce:
Refer to <https://bugzilla.redhat.com/show_bug.cgi?id=2027598#c61> and onwards.

* Actual results:
Refer to <https://bugzilla.redhat.com/show_bug.cgi?id=2027598#c40> and onwards -- the "Utils.get_disk_allocated" function in virt-v2v, which is supposed to make progress in every interation of its loop, will go backwards on occasion, and decay into an infinite loop.

* Expected results:
The OCaml bindings should faithfully represent uint32_t values >= 0x8000_0000. More closely, "Utils.get_disk_allocated" in virt-v2v should always terminate.

* Additional info:
(1) This is arguably a (mild) security bug, but our analysis in <https://bugzilla.redhat.com/show_bug.cgi?id=2027598#c61> is already public.

(2) The same issue exists for C's uint64_t <-> OCaml's int64 -- this is in fact a bug (or limitation) in OCaml's type system. We can't do anything about that, at the moment, as there is no OCaml type we could widen uint64_t to. (At least we can widen C's uint32_t to OCaml's int64.)

Comment 1 Richard W.M. Jones 2022-01-14 10:15:38 UTC
*** Bug 2040609 has been marked as a duplicate of this bug. ***

Comment 2 Richard W.M. Jones 2022-01-14 10:17:18 UTC
(Adding Eric as heads up because I think he has a patch series which will
conflict with changes in this area)

Comment 3 Richard W.M. Jones 2022-01-14 10:18:56 UTC
> (2) The same issue exists for C's uint64_t <-> OCaml's int64 -- this is in fact a bug (or limitation) in OCaml's type system. We can't do anything about that, at the moment, as there is no OCaml type we could widen uint64_t to. (At least we can widen C's uint32_t to OCaml's int64.)

NBD offsets are always [0..0x7fff_ffff_ffff_ffff] so we're probably OK in most
practical cases.

Comment 4 Laszlo Ersek 2022-01-14 10:22:28 UTC
I've got a patch for fixing the problem with the conversion between OCaml's "int32" type and C's "uint32_t".

Additionally, I've mostly reviewed the existing mappings, between OCaml's (signed-only) int* types, and the various unsigned types of C (represented by SizeT, UInt, UIntPtr, UInt64; and in the reverse direction, RSizeT, RUInt, RSizeT, ...) in "generator/OCaml.ml". I can see many-many problems; catching all out-of-range errors is a Herculean task.

In trying to come up with some range checks, I wanted to see what the *actual* range of the OCaml "int" type was. Turns out that on a 64-bit platform, it has *62* value bits, where

- the LSB determines whether the thing is an OCaml "block", or an "unboxed integer",
- then we have 62 value bits,
- and the MSB is the sign bit.

Now here's my problem:

$ ocaml
        OCaml version 4.12.0

# let x = 4611686018427387903;;
val x : int = 4611686018427387903
# let x = 4611686018427387904;;
val x : int = -4611686018427387904

The first definition creates "x" with value 0x3FFF_FFFF_FFFF_FFFF; that is, with the 62 value bits set, and the sign bit clear. The type that OCaml infers from the constant is "int". All good.

The second definition redefines "x" (in a narrower scope) with value 0x4000_0000_0000_0000, with the 62 value bits clear, and *attempting* to set "value bit #62" (that is, attempting to set the "63rd value bit") -- which does not exist. Unfortunately, instead of producing an exception *or* inferring a type other than "int", OCaml silently sets the sign bit, permitting "x" (of type "int") to wrap to negative. :/

Given this (i.e., that the "int" type can be overflowed in *purely OCaml* code, before it reaches the libnbd bindings, and is converted to a particular C-language type), I don't think I can do anything at all in the libnbd bindings to catch overflows and underflows.

Comment 5 Richard W.M. Jones 2022-01-14 10:56:21 UTC
We shouldn't be using OCaml "int" type for storing any 64 bit numbers, that's
a mistake if it happens.  On 32 bit platforms it's 31 bits (signed).

However with a quick look at the bindings it seems we map signed and
unsigned Int64 / UInt64 to OCaml "int64".  This is boxed and has a full
range of 64 bits (signed).  It's technically wrong to store a uint64_t
in this type, but we can probably get away with it if it's an NBD offset
since those are limited to [0..7fff_ffff_ffff_ffff]

There is, sadly, no overflow checking ...

Comment 6 Richard W.M. Jones 2022-01-14 12:52:39 UTC
About unsigned integers see also:
https://discuss.ocaml.org/t/unsigned-integers/9145
https://github.com/ocaml/ocaml/pull/1201

Comment 7 Richard W.M. Jones 2022-01-14 13:27:21 UTC
(In reply to Richard W.M. Jones from comment #5)
> However with a quick look at the bindings it seems we map signed and
> unsigned Int64 / UInt64 to OCaml "int64".

So I realised what I should have been looking at are the UInt32
mapping.  That is mapped to OCaml int32, which is definitely wrong.

Luckily it doesn't affect very many APIs, just these ones (and here
I'm only talking about the OCaml bindings, the underlying APIs are fine):

- connect_vsock
- aio_connect_vsock
- block_status       # this bug
- aio_block_status   #

Comment 8 Laszlo Ersek 2022-01-14 13:39:49 UTC
[Libguestfs] [libnbd PATCH] ocaml: map C's uint32_t to OCaml's int64
https://listman.redhat.com/archives/libguestfs/2022-January/msg00093.html
Message-Id: <20220114133833.24835-1-lersek>

Comment 10 Laszlo Ersek 2022-01-17 13:58:51 UTC
(In reply to Laszlo Ersek from comment #8)
> [Libguestfs] [libnbd PATCH] ocaml: map C's uint32_t to OCaml's int64
> https://listman.redhat.com/archives/libguestfs/2022-January/msg00093.html
> Message-Id: <20220114133833.24835-1-lersek>

Upstream commit 0e714a6e06e6.

Comment 11 Richard W.M. Jones 2022-01-18 21:29:35 UTC
Temporarily adding Verified:Tested to move this to a compose
so I can build virt-v2v against it.

Comment 15 Vera 2022-01-25 02:41:30 UTC
Verified with the versions:
libnbd-1.10.3-1.el9.x86_64
virt-v2v-1.45.97-2.el9.x86_64
qemu-img-6.2.0-4.el9.x86_64
libvirt-libs-8.0.0-1.el9.x86_64
guestfs-tools-1.46.1-6.el9.x86_64
nbdkit-1.28.4-2.el9.x86_64
rhv 4.4.10.2-0.1.el8ev

Steps:
1.Convert a guest from VMware to rhv4.4 via -o rhv by v2v
# virt-v2v -ic vpx://root.73.141/data/10.73.75.219/?no_verify=1 -it vddk -io vddk-libdir=/root/vddk_libdir/latest -io vddk-thumbprint=1F:97:34:5F:B6:C2:BA:66:46:CB:1A:71:76:7D:6B:50:1E:03:00:EA  -ip /v2v-ops/esxpw   -o rhv -os 10.73.195.48:/home/nfs_export -b ovirtmgmt  esx6.7-rhel8.4-x86_64
[   0.0] Setting up the source: -i libvirt -ic vpx://root.73.141/data/10.73.75.219/?no_verify=1 -it vddk esx6.7-rhel8.4-x86_64
[   1.9] Opening the source
[   9.5] Inspecting the source
[  18.4] Checking for sufficient free disk space in the guest
[  18.4] Converting Red Hat Enterprise Linux 8.4 (Ootpa) to run on KVM
virt-v2v: This guest has virtio drivers installed.
[  67.2] Mapping filesystem data to avoid copying unused and blank areas
[  68.6] Closing the overlay
[  68.9] Assigning disks to buses
[  68.9] Checking if the guest needs BIOS or UEFI to boot
[  68.9] Setting up the destination: -o rhv
[  71.1] Copying disk 1/1
█ 100% [****************************************]
[ 364.5] Creating output metadata
[ 373.8] Finishing off


2. Check if the guest is in "Storage--> Storage Domains--->nfs_export --> VM Import" on rhv4.4 after conversion

3. Import the guest and check the stauts on rhv4.4


Moving to Verified.

Comment 17 errata-xmlrpc 2022-05-17 12:51:02 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 (new packages: libnbd), 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/RHEA-2022:2409


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