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 1490279 - vol-resize a luks encrypted image will get unexpected result virtual size
Summary: vol-resize a luks encrypted image will get unexpected result virtual size
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: libvirt
Version: 7.5
Hardware: x86_64
OS: Linux
medium
medium
Target Milestone: rc
: ---
Assignee: John Ferlan
QA Contact: Meina Li
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2017-09-11 08:41 UTC by yisun
Modified: 2018-04-10 10:56 UTC (History)
10 users (show)

Fixed In Version: libvirt-3.9.0-1.el7
Doc Type: No Doc Update
Doc Text:
undefined
Clone Of:
Environment:
Last Closed: 2018-04-10 10:55:31 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHEA-2018:0704 0 None None None 2018-04-10 10:56:40 UTC

Description yisun 2017-09-11 08:41:50 UTC
Description of problem:
vol-resize a luks encrypted image will get unexpected result size

Version-Release number of selected component (if applicable):
libvirt-3.7.0-2.el7.x86_64
qemu-kvm-rhev-2.9.0-16.el7_4.6.x86_64

How reproducible:
100%

Steps to Reproduce:
1. Having a test dir pool
## virsh pool-dumpxml testpool
<pool type='dir'>
  <name>testpool</name>
  <uuid>c9afa1ec-b3e2-41a9-bf8b-5dd67eced92e</uuid>
  <capacity unit='bytes'>53660876800</capacity>
  <allocation unit='bytes'>32447188992</allocation>
  <available unit='bytes'>21213687808</available>
  <source>
  </source>
  <target>
    <path>/var/lib/libvirt/images/test</path>
    <permissions>
      <mode>0755</mode>
      <owner>0</owner>
      <group>0</group>
      <label>unconfined_u:object_r:virt_image_t:s0</label>
    </permissions>
  </target>
</pool>

2. create a 100M luks encrypted image
## qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=sec0 /var/lib/libvirt/images/test/luks.img 100M
Formatting '/var/lib/libvirt/images/test/luks.img', fmt=luks size=104857600 key-secret=sec0

3. check the image virtual size
## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 100M (104857600 bytes)

4. refresh the pool
## virsh pool-refresh testpool
Pool testpool refreshed

5. resize the vol with --delta=10M
## virsh vol-resize /var/lib/libvirt/images/test/luks.img 10M --delta
Size of volume 'luks.img' successfully changed by 10M

6. check the virtual size again
## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 108M (113274880 bytes)
<======= only 8M added

7. resize the vol to 150M
##virsh vol-resize /var/lib/libvirt/images/test/luks.img 150M 
Size of volume 'luks.img' successfully changed to 150M


## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 148M (155217920 bytes)
<======= resized to 148 but not 150M



Actual results:
Doesn't resize to a expected value

Expected results:
resize to a expected value

Additional info:
When --delta added, the second round will give a expected value.
1. ## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 100M (104857600 bytes)
2. ## virsh vol-resize /var/lib/libvirt/images/test/luks.img 10M --delta
Size of volume 'luks.img' successfully changed by 10M
/ ## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 108M (113274880 bytes) <==== expected 110M but got 108M
3. ## virsh vol-resize /var/lib/libvirt/images/test/luks.img 10M --delta
Size of volume 'luks.img' successfully changed by 10M
## qemu-img info /var/lib/libvirt/images/test/luks.img  | grep "virtual size"
virtual size: 118M (123760640 bytes) <==== 118-108=10, this time it's expected...

Comment 2 Daniel Berrangé 2017-09-11 08:53:12 UTC
2 MB is the size of the LUKS header region, so it sounds like during resize we're calculating the new size based on the original physical volume size (which includes header), rather than using the original virtual size (which excludes the header).

Comment 3 Daniel Berrangé 2017-09-11 09:03:17 UTC
At the QEMU level resize works correctly:

$ qemu-img create -f luks  --object secret,id=sec0,data=123456 -o key-secret=sec0  demo.luks 100M
Formatting 'demo.luks', fmt=luks size=104857600 key-secret=sec0
$ ls -alh demo.luks 
-rw-r--r--. 1 berrange berrange 102M Sep 11 10:01 demo.luks
$ qemu-img info demo.luks |  grep size
virtual size: 100M (104857600 bytes)
disk size: 256K


$ qemu-img resize  --object secret,id=sec0,data=123456  --image-opts driver=luks,file.filename=demo.luks,key-secret=sec0 +10M
Image resized.
$ ls -alh demo.luks 
-rw-r--r--. 1 berrange berrange 112M Sep 11 10:02 demo.luks
$ qemu-img info demo.luks |  grep size
virtual size: 110M (115343360 bytes)
disk size: 256K


SO this looks like a mistake in the libvirt storage code.

Comment 4 John Ferlan 2017-10-06 13:44:57 UTC
ouch - couple of problems to address... The resize logic clearly was missing any sort of understanding that the local 'raw' volume being resized was a LUKS image - so it was just going through the normal raw resize logic to open the file and essentially use ftruncate() to extend the size.  The second problem is that it performed this action on a LUKS volume without the passphrase to do so.

So obviously some adjustments are need.  Still in order to make this work properly creation of a libvirt secret to store away the LUKS volume password will also be required, the following is what I did for that:

1. Create a secret XML file (calling it secret.xml) in your favorite editor:

<secret ephemeral='no' private='yes'>
   <description>Secret for bz 1490279</description>
   <usage type='volume'>
     <volume>/var/lib/libvirt/images/test/luks.img</volume>
   </usage>
</secret>

virsh secret-define secret.xml
Secret 565f077a-ec0e-4d2d-9b4b-f230f5028cbd created

virsh secret-list
 UUID                                  Usage
-------------------------------------------------------------------------------
...
 565f077a-ec0e-4d2d-9b4b-f230f5028cbd  volume /var/lib/libvirt/images/test/luks.img
...

2. Set the secret value (from above, using "redhat"):

MYSECRET=`printf %s "redhat" | base64`
virsh secret-set-value 565f077a-ec0e-4d2d-9b4b-f230f5028cbd $MYSECRET
Secret value set

3. Thus when you "refresh-pool" the secret will be found:

virsh pool-refresh testpool
Pool testpool refreshed

virsh vol-dumpxml luks.img testpool
<volume type='file'>
  <name>luks.img</name>
  <key>/var/lib/libvirt/images/test/luks.img</key>
  <source>
  </source>
  <capacity unit='bytes'>115343360</capacity>
  <allocation unit='bytes'>262144</allocation>
  <physical unit='bytes'>117411840</physical>
  <target>
    <path>/var/lib/libvirt/images/test/luks.img</path>
    <format type='raw'/>
    <permissions>
      <mode>0644</mode>
      <owner>0</owner>
      <group>0</group>
      <label>unconfined_u:object_r:unlabeled_t:s0</label>
    </permissions>
    <timestamps>
      <atime>1507294522.515367777</atime>
      <mtime>1507294515.847370031</mtime>
      <ctime>1507294515.847370031</ctime>
    </timestamps>
    <encryption format='luks'>
      <secret type='passphrase' uuid='565f077a-ec0e-4d2d-9b4b-f230f5028cbd'/>
    </encryption>
  </target>
</volume>

-=-=--=-=-=

I'll generate some patches to perform the right sequence of calls for the resize logic, but figured I didn't want to lose/forget the above information which will be important when the patches are posted/pushed.

What won't be supported in this model will be the "preallocate" that would normally be supported for a RAW volume, but I'm not sure is feasible using qemu-img to perform the resize.

Comment 5 John Ferlan 2017-10-06 19:56:46 UTC
Patches posted upstream:

https://www.redhat.com/archives/libvir-list/2017-October/msg00332.html

Comment 6 John Ferlan 2017-10-27 09:44:42 UTC
Patches pushed upstream:

commit becb383a63ee3edd40493491a585630f364107c9
Author: John Ferlan <jferlan>
Date:   Fri Oct 6 12:04:19 2017 -0400

    storage: Properly resize a local volume using LUKS
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1490279
    
    Turns out the virStorageBackendVolResizeLocal did not differentiate
    whether the target volume was a LUKS volume or not and just blindly
    did the ftruncate() on the target volume.
    
    Follow the volume creation logic (in general) and create a qemu-img
    resize command to resize the target volume for LUKS ensuring that
    the --object secret is provided as well as the '--image-opts' used
    by the qemu-img resize logic to describe the path and secret ensuring
    that it's using the luks driver on the volume of course.


$ git describe becb383a63ee3edd40493491a585630f364107c9
CVE-2017-1000256-143-gbecb383a63
$

Comment 8 Meina Li 2017-11-28 06:41:42 UTC
Verified env components:
libvirt-3.9.0-3.l7.x86_64
qemu-kvm-rhev-2.10.0-6.el7.x86_64

Verified steps:
1. Having a test dir pool.
# cat dir-pool.xml
<pool type='dir'>
  <name>testpool</name>
  <uuid>c9afa1ec-b3e2-41a9-bf8b-5dd67eced92e</uuid>
  <capacity unit='bytes'>53660876800</capacity>
  <allocation unit='bytes'>32447188992</allocation>
  <available unit='bytes'>21213687808</available>
  <source>
  </source>
  <target>
    <path>/var/lib/libvirt/images/test</path>
    <permissions>
      <mode>0755</mode>
      <owner>0</owner>
      <group>0</group>
      <label>unconfined_u:object_r:virt_image_t:s0</label>
    </permissions>
  </target>
</pool>

2. Create a luks encrypted image/raw image  and check the image virtual size.
# qemu-img create -f luks --object secret,id=sec0,data=`printf %s "redhat" | base64`,format=base64 -o key-secret=sec0 /var/lib/libvirt/images/test/luks.img 100M
Formatting '/var/lib/libvirt/images/test/luks.img', fmt=luks size=104857600 key-secret=sec0
# qemu-img info /var/lib/libvirt/images/test/luks.img | grep "virtual size"
virtual size: 100M (104857600 bytes)

# qemu-img create /var/lib/libvirt/images/test/demo.img 100M
Formatting '/var/lib/libvirt/images/test/demo.img', fmt=raw size=104857600
# qemu-img info /var/lib/libvirt/images/test/demo.img  | grep "virtual size"
virtual size: 100M (104857600 bytes)

3. Refresh the pool and resize the vol.
# virsh pool-refresh testpool
Pool testpool refreshed
# virsh vol-list testpool
 Name                 Path                                    
------------------------------------------------------------------------------
 demo.img             /var/lib/libvirt/images/test/demo.img   
 luks.img            /var/lib/libvirt/images/test/luks.img  
# virsh vol-resize /var/lib/libvirt/images/test/demo.img 10M --delta
Size of volume 'demo.img' successfully changed by 10M   
--->resize successfully for raw image vol

# virsh vol-resize /var/lib/libvirt/images/test/luks.img 10M --delta
error: Failed to change size of volume 'luks.img' by 10M
error: XML error: no secret provided for luks encryption 
--->need to provide secret for luks image vol

4. Provide secret for luks encryption.
#cat secret.xml
<secret ephemeral='no' private='yes'>
   <description>Secret forluks</description>
   <usage type='volume'>
     <volume>/var/lib/libvirt/images/test/luks.img</volume>
   </usage>
</secret>
# virsh secret-define secret.xml 
Secret 0ba0c60e-ee29-4e08-862c-316b5e662027 created
# MYSECRET=`printf %s "redhat" | base64`
# virsh secret-set-value 0ba0c60e-ee29-4e08-862c-316b5e662027 $MYSECRET
Secret value set

5. Refresh the pool and resize the luks vol.
# virsh pool-refresh testpool
Pool testpool refreshed
# virsh vol-resize /var/lib/libvirt/images/test/luks.img 10M --delta
Size of volume 'luks.img' successfully changed by 10M
# qemu-img info /var/lib/libvirt/images/test/luks.img | grep "virtual size"
virtual size: 110M (115343360 bytes) 
# virsh vol-resize /var/lib/libvirt/images/test/luks.img 150M 
Size of volume 'luks.img' successfully changed to 150M
# qemu-img info /var/lib/libvirt/images/test/luks.img | grep "virtual size"
virtual size: 150M (157286400 bytes)   

6. Preallocate is only supported for raw type volume.
# virsh vol-resize /var/lib/libvirt/images/test/luks1.img 120M --allocate
error: Failed to change size of volume 'luks1.img' to 120M
error: Operation not supported: preallocate is only supported for raw type volume
# virsh vol-resize /var/lib/libvirt/images/test/demo.img 120M --allocate
Size of volume 'demo.img' successfully changed to 120M  

All the results are as expected, move this bug to be verified.

Comment 12 errata-xmlrpc 2018-04-10 10:55:31 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://access.redhat.com/errata/RHEA-2018:0704


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