components/openstack/nova/patches/04-CVE-2014-0134-partial.patch
changeset 4063 12e03e5492b8
parent 4062 f45bb9cec48c
parent 4061 5ac5027dc3e3
--- a/components/openstack/nova/patches/04-CVE-2014-0134-partial.patch	Fri Mar 20 22:56:27 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-This proposed upstream patch is a follow-up to the original fix for
-CVE-2014-0134 (Launchpad bug 1221190) but is tracked under the same CVE
-and Launchpad bug as the original fix. It is designated as such below
-('Partial-bug: #1221190').
-
-From 63064a709162ba1a8a9a19643bd3acdf57c0c0b4 Mon Sep 17 00:00:00 2001
-From: Nikola Dipanov <[email protected]>
-Date: Wed, 9 Apr 2014 15:50:20 +0200
-Subject: [PATCH] Avoid the possibility of truncating disk info file
-
-Commit dc8de42 makes nova persist image format to a file to avoid
-attacks based on changing it later. However the way it was implemented
-leaves a small window of opportunity for the file to be truncated before
-it gets written back to effectively making it possible for data to get
-lost leaving us with a potential problem next time it is attempted to be
-read.
-
-This patch changes the way file is updated to be atomic, thus closing
-the race window (and also removes the chown that we did not really
-need).
-
-It is worth noting that a better solution to this would be
-to allow the code calling the imagebackend to write the file (once!)
-and make it impossible to update after the boot process is done. This
-approach would require more refactoring of the libvirt driver code, and
-may be done in the future.
-
-Partial-bug: #1221190
-Change-Id: Ia1b073f38e096989f34d1774a12a1b4151773fc7
-(cherry picked from commit d416f4310bb946b4b127201ec3c37e530d988714)
----
- etc/nova/rootwrap.d/compute.filters          |    1 -
- nova/tests/virt/libvirt/test_imagebackend.py |   21 ---------------------
- nova/utils.py                                |   14 --------------
- nova/virt/libvirt/imagebackend.py            |   25 +++++++++++++------------
- 4 files changed, 13 insertions(+), 48 deletions(-)
-
-diff --git a/etc/nova/rootwrap.d/compute.filters b/etc/nova/rootwrap.d/compute.filters
-index e98c3f2..ac67180 100644
---- a/etc/nova/rootwrap.d/compute.filters
-+++ b/etc/nova/rootwrap.d/compute.filters
-@@ -41,7 +41,6 @@ mkdir: CommandFilter, mkdir, root
- # nova/virt/libvirt/connection.py: 'chown', os.getuid( console_log
- # nova/virt/libvirt/connection.py: 'chown', os.getuid( console_log
- # nova/virt/libvirt/connection.py: 'chown', 'root', basepath('disk')
--# nova/utils.py: 'chown', owner_uid, path
- chown: CommandFilter, chown, root
- 
- # nova/virt/disk/vfs/localfs.py: 'chmod'
-diff --git a/nova/tests/virt/libvirt/test_imagebackend.py b/nova/tests/virt/libvirt/test_imagebackend.py
-index 5424f7b..80ade57 100644
---- a/nova/tests/virt/libvirt/test_imagebackend.py
-+++ b/nova/tests/virt/libvirt/test_imagebackend.py
-@@ -29,7 +29,6 @@ from nova.openstack.common import uuidutils
- from nova import test
- from nova.tests import fake_processutils
- from nova.tests.virt.libvirt import fake_libvirt_utils
--from nova import utils
- from nova.virt.libvirt import imagebackend
- 
- CONF = cfg.CONF
-@@ -68,10 +67,6 @@ class _ImageTestCase(object):
-             'nova.virt.libvirt.imagebackend.libvirt_utils',
-             fake_libvirt_utils))
- 
--        def fake_chown(path, owner_uid=None):
--            return None
--        self.stubs.Set(utils, 'chown', fake_chown)
--
-     def tearDown(self):
-         super(_ImageTestCase, self).tearDown()
-         shutil.rmtree(self.INSTANCES_PATH)
-@@ -128,10 +123,6 @@ class RawTestCase(_ImageTestCase, test.NoDBTestCase):
-         super(RawTestCase, self).setUp()
-         self.stubs.Set(imagebackend.Raw, 'correct_format', lambda _: None)
- 
--        def fake_chown(path, owner_uid=None):
--            return None
--        self.stubs.Set(utils, 'chown', fake_chown)
--
-     def prepare_mocks(self):
-         fn = self.mox.CreateMockAnything()
-         self.mox.StubOutWithMock(imagebackend.utils.synchronized,
-@@ -246,10 +237,6 @@ class RawTestCase(_ImageTestCase, test.NoDBTestCase):
-         self.mox.StubOutWithMock(os.path, 'exists')
-         self.mox.StubOutWithMock(imagebackend.images, 'qemu_img_info')
- 
--        def fake_chown(path, owner_uid=None):
--            return None
--        self.stubs.Set(utils, 'chown', fake_chown)
--
-         os.path.exists(self.PATH).AndReturn(True)
-         os.path.exists(self.DISK_INFO_PATH).AndReturn(False)
-         info = self.mox.CreateMockAnything()
-@@ -278,10 +265,6 @@ class Qcow2TestCase(_ImageTestCase, test.NoDBTestCase):
-         self.QCOW2_BASE = (self.TEMPLATE_PATH +
-                            '_%d' % (self.SIZE / (1024 * 1024 * 1024)))
- 
--        def fake_chown(path, owner_uid=None):
--            return None
--        self.stubs.Set(utils, 'chown', fake_chown)
--
-     def prepare_mocks(self):
-         fn = self.mox.CreateMockAnything()
-         self.mox.StubOutWithMock(imagebackend.utils.synchronized,
-@@ -873,10 +856,6 @@ class BackendTestCase(test.NoDBTestCase):
-     def setUp(self):
-         super(BackendTestCase, self).setUp()
- 
--        def fake_chown(path, owner_uid=None):
--            return None
--        self.stubs.Set(utils, 'chown', fake_chown)
--
-     def get_image(self, use_cow, image_type):
-         return imagebackend.Backend(use_cow).image(self.INSTANCE,
-                                                    self.NAME,
-diff --git a/nova/utils.py b/nova/utils.py
-index 4757f3a..599cb64 100755
---- a/nova/utils.py
-+++ b/nova/utils.py
-@@ -924,20 +924,6 @@ def temporary_chown(path, owner_uid=None):
-             execute('chown', orig_uid, path, run_as_root=True)
- 
- 
--def chown(path, owner_uid=None):
--    """chown a path.
--
--    :param owner_uid: UID of owner (defaults to current user)
--    """
--    if owner_uid is None:
--        owner_uid = os.getuid()
--
--    orig_uid = os.stat(path).st_uid
--
--    if orig_uid != owner_uid:
--        execute('chown', owner_uid, path, run_as_root=True)
--
--
- @contextlib.contextmanager
- def tempdir(**kwargs):
-     argdict = kwargs.copy()
-diff --git a/nova/virt/libvirt/imagebackend.py b/nova/virt/libvirt/imagebackend.py
-index ed11c90..29131d9 100644
---- a/nova/virt/libvirt/imagebackend.py
-+++ b/nova/virt/libvirt/imagebackend.py
-@@ -264,20 +264,21 @@ class Image(object):
-                             lock_path=self.lock_path)
-         def write_to_disk_info_file():
-             # Use os.open to create it without group or world write permission.
--            fd = os.open(self.disk_info_path, os.O_RDWR | os.O_CREAT, 0o644)
--            with os.fdopen(fd, "r+") as disk_info_file:
-+            fd = os.open(self.disk_info_path, os.O_RDONLY | os.O_CREAT, 0o644)
-+            with os.fdopen(fd, "r") as disk_info_file:
-                 line = disk_info_file.read().rstrip()
-                 dct = _dict_from_line(line)
--                if self.path in dct:
--                    msg = _("Attempted overwrite of an existing value.")
--                    raise exception.InvalidDiskInfo(reason=msg)
--                dct.update({self.path: driver_format})
--                disk_info_file.seek(0)
--                disk_info_file.truncate()
--                disk_info_file.write('%s\n' % jsonutils.dumps(dct))
--            # Ensure the file is always owned by the nova user so qemu can't
--            # write it.
--            utils.chown(self.disk_info_path, owner_uid=os.getuid())
-+
-+            if self.path in dct:
-+                msg = _("Attempted overwrite of an existing value.")
-+                raise exception.InvalidDiskInfo(reason=msg)
-+            dct.update({self.path: driver_format})
-+
-+            tmp_path = self.disk_info_path + ".tmp"
-+            fd = os.open(tmp_path, os.O_WRONLY | os.O_CREAT, 0o644)
-+            with os.fdopen(fd, "w") as tmp_file:
-+                tmp_file.write('%s\n' % jsonutils.dumps(dct))
-+            os.rename(tmp_path, self.disk_info_path)
- 
-         try:
-             if (self.disk_info_path is not None and
--- 
-1.7.9.2
-