diff options
Diffstat (limited to 'sys-cluster/nova')
-rw-r--r-- | sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch | 165 | ||||
-rw-r--r-- | sys-cluster/nova/nova-12.0.2-r1.ebuild (renamed from sys-cluster/nova/nova-12.0.2.ebuild) | 1 |
2 files changed, 166 insertions, 0 deletions
diff --git a/sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch b/sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch new file mode 100644 index 000000000000..20b35b76a812 --- /dev/null +++ b/sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch @@ -0,0 +1,165 @@ +From 8d5ba34751c0ae8093f987d74348dffd8ca0b61c Mon Sep 17 00:00:00 2001 +From: Lee Yarwood <lyarwood@redhat.com> +Date: Wed, 24 Feb 2016 11:23:22 +0000 +Subject: [PATCH] libvirt: Always copy or recreate disk.info during a migration + +The disk.info file contains the path and format of any image, config or +ephermal disk associated with an instance. When using RAW images and migrating +an instance this file should always be copied or recreated. This avoids the Raw +imagebackend reinspecting the format of these disks when spawning the instance +on the destination host. + +By not copying or recreating this disk.info file, a malicious image written to +an instance disk on the source host will cause Nova to reinspect and record a +different format for the disk on the destination. This format then being used +incorrectly when finally spawning the instance on the destination. + +SecurityImpact +Closes-bug: #1548450 +Change-Id: Idfc16f54049aaeab31ac1c1d8d79a129acc9fb87 +--- + nova/tests/unit/virt/libvirt/test_driver.py | 75 +++++++++++++++++++++++++++++ + nova/virt/libvirt/driver.py | 27 +++++++++++ + 2 files changed, 102 insertions(+) + +diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py +index 572facd..55051f1 100644 +--- a/nova/tests/unit/virt/libvirt/test_driver.py ++++ b/nova/tests/unit/virt/libvirt/test_driver.py +@@ -7631,6 +7631,43 @@ class LibvirtConnTestCase(test.NoDBTestCase): + fallback_from_host=instance.host)]) + self.assertIsInstance(res, dict) + ++ def test_pre_live_migration_recreate_disk_info(self): ++ ++ migrate_data = {'is_shared_block_storage': False, ++ 'is_shared_instance_path': False, ++ 'block_migration': True, ++ 'instance_relative_path': '/some/path/'} ++ disk_info = [{'disk_size': 5368709120, 'type': 'raw', ++ 'virt_disk_size': 5368709120, ++ 'path': '/some/path/disk', ++ 'backing_file': '', 'over_committed_disk_size': 0}, ++ {'disk_size': 1073741824, 'type': 'raw', ++ 'virt_disk_size': 1073741824, ++ 'path': '/some/path/disk.eph0', ++ 'backing_file': '', 'over_committed_disk_size': 0}] ++ image_disk_info = {'/some/path/disk': 'raw', ++ '/some/path/disk.eph0': 'raw'} ++ ++ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) ++ instance = objects.Instance(**self.test_instance) ++ instance_path = os.path.dirname(disk_info[0]['path']) ++ disk_info_path = os.path.join(instance_path, 'disk.info') ++ ++ with test.nested( ++ mock.patch.object(os, 'mkdir'), ++ mock.patch.object(fake_libvirt_utils, 'write_to_file'), ++ mock.patch.object(drvr, '_create_images_and_backing') ++ ) as ( ++ mkdir, write_to_file, create_images_and_backing ++ ): ++ drvr.pre_live_migration(self.context, instance, ++ block_device_info=None, ++ network_info=[], ++ disk_info=jsonutils.dumps(disk_info), ++ migrate_data=migrate_data) ++ write_to_file.assert_called_with(disk_info_path, ++ jsonutils.dumps(image_disk_info)) ++ + def test_get_instance_disk_info_works_correctly(self): + # Test data + instance = objects.Instance(**self.test_instance) +@@ -12823,6 +12860,44 @@ class LibvirtDriverTestCase(test.NoDBTestCase): + flavor_obj = objects.Flavor(**flavor) + self._test_migrate_disk_and_power_off(flavor_obj) + ++ @mock.patch('nova.utils.execute') ++ @mock.patch('nova.virt.libvirt.utils.copy_image') ++ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver._destroy') ++ @mock.patch('nova.virt.libvirt.utils.get_instance_path') ++ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver' ++ '._is_storage_shared_with') ++ @mock.patch('nova.virt.libvirt.driver.LibvirtDriver' ++ '.get_instance_disk_info') ++ def test_migrate_disk_and_power_off_resize_copy_disk_info(self, ++ mock_disk_info, ++ mock_shared, ++ mock_path, ++ mock_destroy, ++ mock_copy, ++ mock_execuate): ++ ++ instance = self._create_instance() ++ disk_info = self._disk_info() ++ disk_info_text = jsonutils.loads(disk_info) ++ instance_base = os.path.dirname(disk_info_text[0]['path']) ++ flavor = {'root_gb': 10, 'ephemeral_gb': 25} ++ flavor_obj = objects.Flavor(**flavor) ++ ++ mock_disk_info.return_value = disk_info ++ mock_path.return_value = instance_base ++ mock_shared.return_value = False ++ ++ self.drvr.migrate_disk_and_power_off(context.get_admin_context(), ++ instance, mock.sentinel, ++ flavor_obj, None) ++ ++ src_disk_info_path = os.path.join(instance_base + '_resize', ++ 'disk.info') ++ dst_disk_info_path = os.path.join(instance_base, 'disk.info') ++ mock_copy.assert_any_call(src_disk_info_path, dst_disk_info_path, ++ host=mock.sentinel, on_execute=mock.ANY, ++ on_completion=mock.ANY, compression=mock.ANY) ++ + def test_wait_for_running(self): + def fake_get_info(instance): + if instance['name'] == "not_found": +diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py +index 6328d05..fb53eee 100644 +--- a/nova/virt/libvirt/driver.py ++++ b/nova/virt/libvirt/driver.py +@@ -6279,6 +6279,24 @@ class LibvirtDriver(driver.ComputeDriver): + instance=instance) + os.mkdir(instance_dir) + ++ # Recreate the disk.info file and in doing so stop the ++ # imagebackend from recreating it incorrectly by inspecting the ++ # contents of each file when using the Raw backend. ++ if disk_info: ++ image_disk_info = {} ++ for info in disk_info: ++ image_file = os.path.basename(info['path']) ++ image_path = os.path.join(instance_dir, image_file) ++ image_disk_info[image_path] = info['type'] ++ ++ LOG.debug('Creating disk.info with the contents: %s', ++ image_disk_info, instance=instance) ++ ++ image_disk_info_path = os.path.join(instance_dir, ++ 'disk.info') ++ libvirt_utils.write_to_file(image_disk_info_path, ++ jsonutils.dumps(image_disk_info)) ++ + if not is_shared_block_storage: + # Ensure images and backing files are present. + LOG.debug('Checking to make sure images and backing files are ' +@@ -6823,6 +6841,15 @@ class LibvirtDriver(driver.ComputeDriver): + on_execute=on_execute, + on_completion=on_completion, + compression=compression) ++ ++ # Ensure disk.info is written to the new path to avoid disks being ++ # reinspected and potentially changing format. ++ src_disk_info_path = os.path.join(inst_base_resize, 'disk.info') ++ dst_disk_info_path = os.path.join(inst_base, 'disk.info') ++ libvirt_utils.copy_image(src_disk_info_path, dst_disk_info_path, ++ host=dest, on_execute=on_execute, ++ on_completion=on_completion, ++ compression=compression) + except Exception: + with excutils.save_and_reraise_exception(): + self._cleanup_remote_migration(dest, inst_base, +-- +1.9.1 + diff --git a/sys-cluster/nova/nova-12.0.2.ebuild b/sys-cluster/nova/nova-12.0.2-r1.ebuild index 7fb35af38291..7b043867cd3e 100644 --- a/sys-cluster/nova/nova-12.0.2.ebuild +++ b/sys-cluster/nova/nova-12.0.2-r1.ebuild @@ -229,6 +229,7 @@ RDEPEND=" )" PATCHES=( + "${PV}-CVE-2016-2140.patch" ) pkg_setup() { |