commit:     d68cf8abe61faac28a5b87dc0c2b6d6fd669dd4e
Author:     Matthew Thode <prometheanfire <AT> gentoo <DOT> org>
AuthorDate: Tue Mar  8 20:10:39 2016 +0000
Commit:     Matt Thode <prometheanfire <AT> gentoo <DOT> org>
CommitDate: Tue Mar  8 20:10:39 2016 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=d68cf8ab

sys-cluster/nova: fix CVE-2016-2140

Package-Manager: portage-2.2.26

 sys-cluster/nova/files/12.0.2-CVE-2016-2140.patch  | 165 +++++++++++++++++++++
 .../{nova-12.0.2.ebuild => nova-12.0.2-r1.ebuild}  |   1 +
 2 files changed, 166 insertions(+)

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 0000000..20b35b7
--- /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 <[email protected]>
+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
similarity index 99%
rename from sys-cluster/nova/nova-12.0.2.ebuild
rename to sys-cluster/nova/nova-12.0.2-r1.ebuild
index 7fb35af..7b04386 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() {

Reply via email to