Bug 1490279
Summary: | vol-resize a luks encrypted image will get unexpected result virtual size | ||
---|---|---|---|
Product: | Red Hat Enterprise Linux 7 | Reporter: | yisun |
Component: | libvirt | Assignee: | John Ferlan <jferlan> |
Status: | CLOSED ERRATA | QA Contact: | Meina Li <meili> |
Severity: | medium | Docs Contact: | |
Priority: | medium | ||
Version: | 7.5 | CC: | berrange, chhu, hhan, jiyan, lmen, meili, rbalakri, xuzhang, yalzhang, yisun |
Target Milestone: | rc | Keywords: | Automation |
Target Release: | --- | ||
Hardware: | x86_64 | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | libvirt-3.9.0-1.el7 | Doc Type: | No Doc Update |
Doc Text: |
undefined
|
Story Points: | --- |
Clone Of: | Environment: | ||
Last Closed: | 2018-04-10 10:55:31 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: | |
Embargoed: |
Description
yisun
2017-09-11 08:41:50 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). 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. 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. Patches posted upstream: https://www.redhat.com/archives/libvir-list/2017-October/msg00332.html 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 $ 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. 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 |