summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch')
-rw-r--r--sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch165
1 files changed, 165 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
+