summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2013-01-24 10:07:33 +0000
committerPádraig Brady <pbrady@redhat.com>2013-01-29 15:04:14 +0000
commit317cc0af385536dee43ef2addad50a91357fc1ad (patch)
treefca14c6174f9f8cb9ebbec98d348a873ec7c619e
parent747fb95173ca715749b1417471f71e758d26cf91 (diff)
downloadnova-317cc0af385536dee43ef2addad50a91357fc1ad.tar.gz
disallow boot from volume from specifying arbitrary volumes
Fix a vulnerability in volume attachment in nova-volume, affecting the boot-from-volume feature. By passing a specific volume ID, an authenticated user may be able to boot from a volume they don't own, potentially resulting in full access to that 3rd-party volume. Folsom setups making use of Cinder are not affected. Fixes bug: 1069904, CVE-2013-0208 Change-Id: I5f7c8d20d3ebf33ce1ce64bf0a8418bd2b5a6411
-rw-r--r--nova/compute/api.py27
-rw-r--r--nova/exception.py14
2 files changed, 36 insertions, 5 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 3742a0863a..8df3fdf9a9 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -507,6 +507,11 @@ class API(base.Base):
security_group, block_device_mapping)
instances.append(instance)
instance_uuids.append(instance['uuid'])
+ self._validate_bdm(context, instance)
+ # send a state update notification for the initial create to
+ # show it going from non-existent to BUILDING
+ notifications.send_update_with_states(context, instance, None,
+ vm_states.BUILDING, None, None, service="api")
# In the case of any exceptions, attempt DB cleanup and rollback the
# quota reservations.
@@ -623,6 +628,23 @@ class API(base.Base):
self.db.block_device_mapping_update_or_create(elevated_context,
values)
+ def _validate_bdm(self, context, instance):
+ for bdm in self.db.block_device_mapping_get_all_by_instance(
+ context, instance['uuid']):
+ # NOTE(vish): For now, just make sure the volumes are accessible.
+ snapshot_id = bdm.get('snapshot_id')
+ volume_id = bdm.get('volume_id')
+ if volume_id is not None:
+ try:
+ self.volume_api.get(context, volume_id)
+ except Exception:
+ raise exception.InvalidBDMVolume(id=volume_id)
+ elif snapshot_id is not None:
+ try:
+ self.volume_api.get_snapshot(context, snapshot_id)
+ except Exception:
+ raise exception.InvalidBDMSnapshot(id=snapshot_id)
+
def _populate_instance_for_bdm(self, context, instance, instance_type,
image, block_device_mapping):
"""Populate instance block device mapping information."""
@@ -735,11 +757,6 @@ class API(base.Base):
self._populate_instance_for_bdm(context, instance,
instance_type, image, block_device_mapping)
- # send a state update notification for the initial create to
- # show it going from non-existent to BUILDING
- notifications.send_update_with_states(context, instance, None,
- vm_states.BUILDING, None, None, service="api")
-
return instance
def _check_create_policies(self, context, availability_zone,
diff --git a/nova/exception.py b/nova/exception.py
index b92e2ab87f..2eeef046a9 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -223,6 +223,20 @@ class InvalidSnapshot(Invalid):
message = _("Invalid snapshot") + ": %(reason)s"
+class InvalidBDM(Invalid):
+ message = _("Block Device Mapping is Invalid.")
+
+
+class InvalidBDMSnapshot(InvalidBDM):
+ message = _("Block Device Mapping is Invalid: "
+ "failed to get snapshot %(id)s.")
+
+
+class InvalidBDMVolume(InvalidBDM):
+ message = _("Block Device Mapping is Invalid: "
+ "failed to get volume %(id)s.")
+
+
class VolumeUnattached(Invalid):
message = _("Volume %(volume_id)s is not attached to anything")