components/openstack/nova/patches/08-CVE-2014-3608.patch
author John Beck <John.Beck@Oracle.COM>
Thu, 09 Oct 2014 18:23:12 -0700
changeset 2144 96440b7aa33e
parent 2127 9574188edd5d
permissions -rw-r--r--
19782835 imagemagick doesn't build on s12_58

This upstream patch addresses CVE-2014-3608 and is tracked under Launchpad
bug 1319182.  It is addressed in Juno 2014.2 and Icehouse 2014.1.3.  It has
been modified to apply cleanly into our current Havana implementation.

From 8ff170dc95bf3101fe38a2624e941bfa3b7c1138 Mon Sep 17 00:00:00 2001
From: "Leandro I. Costantino" <[email protected]>
Date: Mon, 19 May 2014 19:58:47 -0300
Subject: [PATCH] VM in rescue state must have a restricted set of actions

Right now it is possible to pause, suspend and stop a VM in state RESCUED,
so after the state is changed, it's not possible to trigger unrescue anymore
since the original state is lost.

This patch remove vm_states.RESCUED as valid state from stop,
pause and suspend actions.

The vm_states devref is also updated to reflect this change including the
current reboot flow.( vm_states.RESCUED cannot be rebooted as per
today code)

DocImpact
Closes-Bug: #1319182
Co-Authored-By: Cyril Roelandt <[email protected]>
Change-Id: I531dea5a5499bf93c24bea37850d562134dee281
---
 doc/source/devref/vmstates.rst         |  7 ++++--
 nova/compute/api.py                    |  7 +++---
 nova/tests/compute/test_compute_api.py | 46 ++++++++++++++++++++++++++++++++--
 3 files changed, 52 insertions(+), 8 deletions(-)

--- nova-2013.2.3/doc/source/devref/vmstates.rst	2014-04-03 11:49:38.000000000 -0700
+++ nova-2013.2.3/doc/source/devref/vmstates.rst	2014-09-29 10:32:35.921504377 -0700
@@ -88,6 +88,7 @@
     rescue -> error
     active -> rescue
     stopped -> rescue
+    error -> rescue
 
     unrescue [shape="rectangle"]
     unrescue -> active
@@ -139,7 +140,9 @@
     reboot -> error
     active -> reboot
     stopped -> reboot
-    rescued -> reboot
+    paused -> reboot
+    suspended -> reboot
+    error -> reboot
 
     live_migrate [shape="rectangle"]
     live_migrate -> active
@@ -159,4 +162,4 @@
 power states when a new VM instance is created.
 
 
-.. image:: /images/run_instance_walkthrough.png
\ No newline at end of file
+.. image:: /images/run_instance_walkthrough.png
--- nova-2013.2.3/nova/compute/api.py	2014-04-03 11:49:46.000000000 -0700
+++ nova-2013.2.3/nova/compute/api.py	2014-09-29 10:32:50.868945930 -0700
@@ -1619,8 +1619,7 @@
     @check_instance_lock
     @check_instance_host
     @check_instance_cell
-    @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.RESCUED,
-                                    vm_states.ERROR],
+    @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.RESCUED],
                           task_state=[None])
     def stop(self, context, instance, do_cast=True):
         """Stop an instance."""
@@ -2429,7 +2428,7 @@
     @wrap_check_policy
     @check_instance_lock
     @check_instance_cell
-    @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.RESCUED])
+    @check_instance_state(vm_state=[vm_states.ACTIVE])
     def pause(self, context, instance):
         """Pause the given instance."""
         instance.task_state = task_states.PAUSING
@@ -2456,7 +2455,7 @@
     @wrap_check_policy
     @check_instance_lock
     @check_instance_cell
-    @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.RESCUED])
+    @check_instance_state(vm_state=[vm_states.ACTIVE])
     def suspend(self, context, instance):
         """Suspend the given instance."""
         instance.task_state = task_states.SUSPENDING
--- nova-2013.2.3/nova/tests/compute/test_compute_api.py	2014-04-03 11:49:46.000000000 -0700
+++ nova-2013.2.3/nova/tests/compute/test_compute_api.py	2014-09-29 10:32:35.926521781 -0700
@@ -56,6 +56,16 @@
         self.context = context.RequestContext(self.user_id,
                                               self.project_id)
 
+    def _get_vm_states(self, exclude_states=None):
+        vm_state = set([vm_states.ACTIVE, vm_states.BUILDING, vm_states.PAUSED,
+                    vm_states.SUSPENDED, vm_states.RESCUED, vm_states.STOPPED,
+                    vm_states.RESIZED, vm_states.SOFT_DELETED,
+                    vm_states.DELETED, vm_states.ERROR, vm_states.SHELVED,
+                    vm_states.SHELVED_OFFLOADED])
+        if not exclude_states:
+            exclude_states = set()
+        return vm_state - exclude_states
+
     def _create_flavor(self, params=None):
         flavor = {'id': 1,
                   'flavorid': 1,
@@ -193,6 +203,19 @@
         self.assertEqual(task_states.SUSPENDING,
                          instance.task_state)
 
+    def _test_suspend_fails(self, vm_state):
+        params = dict(vm_state=vm_state)
+        instance = self._create_instance_obj(params=params)
+        self.assertIsNone(instance.task_state)
+        self.assertRaises(exception.InstanceInvalidState,
+                          self.compute_api.suspend,
+                          self.context, instance)
+
+    def test_suspend_fails_invalid_states(self):
+        invalid_vm_states = self._get_vm_states(set([vm_states.ACTIVE]))
+        for state in invalid_vm_states:
+            self._test_suspend_fails(state)
+
     def test_resume(self):
         # Ensure instance can be resumed (if suspended).
         instance = self._create_instance_obj(
@@ -298,13 +321,19 @@
     def test_stop_stopped_instance_with_bypass(self):
         self._test_stop(vm_states.STOPPED, force=True)
 
-    def test_stop_invalid_state(self):
-        params = dict(vm_state=vm_states.PAUSED)
+    def _test_stop_invalid_state(self, vm_state):
+        params = dict(vm_state=vm_state)
         instance = self._create_instance_obj(params=params)
         self.assertRaises(exception.InstanceInvalidState,
                           self.compute_api.stop,
                           self.context, instance)
 
+    def test_stop_fails_invalid_states(self):
+        invalid_vm_states = self._get_vm_states(set([vm_states.ACTIVE,
+                                                     vm_states.ERROR]))
+        for state in invalid_vm_states:
+            self._test_stop_invalid_state(state)
+
     def test_stop_a_stopped_inst(self):
         params = {'vm_state': vm_states.STOPPED}
         instance = self._create_instance_obj(params=params)
@@ -1075,6 +1104,19 @@
         self.assertEqual(task_states.PAUSING,
                          instance.task_state)
 
+    def _test_pause_fails(self, vm_state):
+        params = dict(vm_state=vm_state)
+        instance = self._create_instance_obj(params=params)
+        self.assertIsNone(instance.task_state)
+        self.assertRaises(exception.InstanceInvalidState,
+                          self.compute_api.pause,
+                          self.context, instance)
+
+    def test_pause_fails_invalid_states(self):
+        invalid_vm_states = self._get_vm_states(set([vm_states.ACTIVE]))
+        for state in invalid_vm_states:
+            self._test_pause_fails(state)
+
     def test_unpause(self):
         # Ensure instance can be unpaused.
         params = dict(vm_state=vm_states.PAUSED)