At present when swapping encrypted volumes no attempt is made to attach an encryptor to the target volume. This results in the RAW underlying volume being used during the rebase, where decrypted data is copied from the original volume to the target:
Any attempt to detach and then reattach this volume from the instance will lead to the volume being reformatted as the os-brick supplied encryptors do not identify the volume as encrypted:
Additionally, while unlikely, a malicious user could easily DOS the compute node hosting the instance by writing a corrupt LUKS header to the RAW volume before detaching and reattaching the volume. For example, setting a keyslot iters (used by PBKDF2) to a large value etc (kudos to mdbooth for suggesting this):
This method of DOS'ing the compute host was previously discussed in the context of bug 1724573 but dismissed as access to the underlying volume was dependent on a host reboot, outside of a users control. This bug differs as a user has full control of the above volume-update/swap_volume flow that provides access to the underlying volume.
$ sudo qemu-img info /dev/disk/by-id/scsi-36001405ba072cc9f93e444c9433ead1c
image: /dev/disk/by-id/scsi-36001405ba072cc9f93e444c9433ead1c
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 0
Expected result
===============
The encrypted volumes are rebased with their associated encryptors attached, leading to encrypted data being written to the underlying volumes.
Actual result
=============
Decrypted data from the source volume is written to the underlying target volume. This data will be lost with a subsequent detach / attach cycle. Access to the underlying volume could also be used by a malicious user to DOS the local compute host.
Environment
===========
1. Exact version of OpenStack you are running. See the following
list for all releases: http://docs.openstack.org/releases/
2. Which hypervisor did you use?
(For example: Libvirt + KVM, Libvirt + XEN, Hyper-V, PowerKVM, ...)
What's the version of that?
Libvirt + KVM
2. Which storage type did you use?
(For example: Ceph, LVM, GPFS, ...)
What's the version of that?
LVM
3. Which networking type did you use?
(For example: nova-network, Neutron with OpenVSwitch, ...)
Description
===========
At present when swapping encrypted volumes no attempt is made to attach an encryptor to the target volume. This results in the RAW underlying volume being used during the rebase, where decrypted data is copied from the original volume to the target:
https:/ /github. com/openstack/ nova/blob/ 76dfdfc1ad8c0e5 376bd997e45f65b ec9ff53d12/ nova/virt/ libvirt/ driver. py#L1338- L1372
Any attempt to detach and then reattach this volume from the instance will lead to the volume being reformatted as the os-brick supplied encryptors do not identify the volume as encrypted:
https:/ /github. com/openstack/ os-brick/ blob/6835b885dc 4144fdc6e9863ca 59ae54f76938995 /os_brick/ encryptors/ luks.py# L138-L161
Additionally, while unlikely, a malicious user could easily DOS the compute node hosting the instance by writing a corrupt LUKS header to the RAW volume before detaching and reattaching the volume. For example, setting a keyslot iters (used by PBKDF2) to a large value etc (kudos to mdbooth for suggesting this):
https:/ /gitlab. com/cryptsetup/ cryptsetup/ wikis/LUKS- standard/ on-disk- format. pdf
This method of DOS'ing the compute host was previously discussed in the context of bug 1724573 but dismissed as access to the underlying volume was dependent on a host reboot, outside of a users control. This bug differs as a user has full control of the above volume- update/ swap_volume flow that provides access to the underlying volume.
Steps to reproduce
==================
- Create two encrypted volumes
$ cinder type-create LUKS type-create --cipher aes-xts-plain64 \
--key_ size 256 \
--control_ location front-end LUKS luks
$ cinder encryption-
$ cinder type-create LUKS_NEW type-create --cipher aes-xts-plain64 \
--key_ size 256 \
--control_ location front-end LUKS_NEW luks
$ cinder encryption-
$ cinder create --volume-type LUKS 1
$ cinder create --volume-type LUKS_NEW 1
- Spawn an instance, attaching the first volume before swapping to the second:
$ nova boot --image cirros- 0.3.5-x86_ 64-disk --flavor 1 swap_test
$ nova volume-attach $instance $vol-luks
$ nova volume-update $instance $vol-luks $vol-luks-new
- Review the resulting volume attachment on the compute host:
$ virsh domblklist $instance ------- ------- ------- ------- ------- ------ data/nova/ instances/ 3d4c5842- 45ab-4660- bf6e-9459f9a2ff 8a/disk by-id/scsi- 36001405ba072cc 9f93e444c9433ea d1c
Target Source
-------
vda /opt/stack/
vdb /dev/disk/
$ ll /dev/disk/ by-id/scsi- 36001405ba072cc 9f93e444c9433ea d1c by-id/scsi- 36001405ba072cc 9f93e444c9433ea d1c -> ../../sdd
lrwxrwxrwx. 1 root root 9 Dec 21 05:30 /dev/disk/
$ sudo qemu-img info /dev/disk/ by-id/scsi- 36001405ba072cc 9f93e444c9433ea d1c by-id/scsi- 36001405ba072cc 9f93e444c9433ea d1c
image: /dev/disk/
file format: raw
virtual size: 1.0G (1073741824 bytes)
disk size: 0
Expected result
===============
The encrypted volumes are rebased with their associated encryptors attached, leading to encrypted data being written to the underlying volumes.
Actual result
=============
Decrypted data from the source volume is written to the underlying target volume. This data will be lost with a subsequent detach / attach cycle. Access to the underlying volume could also be used by a malicious user to DOS the local compute host.
Environment docs.openstack. org/releases/
===========
1. Exact version of OpenStack you are running. See the following
list for all releases: http://
2. Which hypervisor did you use?
(For example: Libvirt + KVM, Libvirt + XEN, Hyper-V, PowerKVM, ...)
What's the version of that?
Libvirt + KVM
2. Which storage type did you use?
(For example: Ceph, LVM, GPFS, ...)
What's the version of that?
LVM
3. Which networking type did you use?
(For example: nova-network, Neutron with OpenVSwitch, ...)
N/A
Logs & Configs
==============
N/A