diff options
author | Vishvananda Ishaya <vishvananda@gmail.com> | 2013-01-24 10:07:33 +0000 |
---|---|---|
committer | Pádraig Brady <pbrady@redhat.com> | 2013-01-29 15:04:14 +0000 |
commit | 317cc0af385536dee43ef2addad50a91357fc1ad (patch) | |
tree | fca14c6174f9f8cb9ebbec98d348a873ec7c619e | |
parent | 747fb95173ca715749b1417471f71e758d26cf91 (diff) | |
download | nova-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.py | 27 | ||||
-rw-r--r-- | nova/exception.py | 14 |
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") |