summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Thode <prometheanfire@gentoo.org>2013-12-13 21:10:36 +0000
committerMatthew Thode <prometheanfire@gentoo.org>2013-12-13 21:10:36 +0000
commitf82c5005d54e892e971e07ec44923dc3f31cd94c (patch)
treed70b1710a8f689085ff98a5d958bd2b1a3b7932e /sys-cluster/nova/files
parentversion bump (diff)
downloadgentoo-2-f82c5005d54e892e971e07ec44923dc3f31cd94c.tar.gz
gentoo-2-f82c5005d54e892e971e07ec44923dc3f31cd94c.tar.bz2
gentoo-2-f82c5005d54e892e971e07ec44923dc3f31cd94c.zip
fixes for CVE-2013-6419
(Portage version: 2.2.7/cvs/Linux x86_64, signed Manifest commit with key 0x2471eb3e40ac5ac3)
Diffstat (limited to 'sys-cluster/nova/files')
-rw-r--r--sys-cluster/nova/files/CVE-2013-6419_2013.1.4.patch129
-rw-r--r--sys-cluster/nova/files/CVE-2013-6419_2013.2.patch186
2 files changed, 315 insertions, 0 deletions
diff --git a/sys-cluster/nova/files/CVE-2013-6419_2013.1.4.patch b/sys-cluster/nova/files/CVE-2013-6419_2013.1.4.patch
new file mode 100644
index 000000000000..541b794899d0
--- /dev/null
+++ b/sys-cluster/nova/files/CVE-2013-6419_2013.1.4.patch
@@ -0,0 +1,129 @@
+commit d4155b806f52f2168742ceb37988fc7f405b44cd
+Author: Aaron Rosen <arosen@nicira.com>
+Date: Mon Oct 7 13:33:31 2013 -0700
+
+ Prevent spoofing instance_id from neturon to nova
+
+ Previously, one could update a port's device_id in neutron to be that
+ of another tenant's instance_id and then be able to retrieve that instance's
+ metadata. This patch prevents this from occuring by checking that X-Tenant-ID
+ received from the metadata request matches the tenant_id in the nova database.
+
+ DocImpact - This patch is dependent on another patch in neutron which adds
+ X-Tenant-ID to the request. Therefore to minimize downtime one
+ should upgrade Neutron first (then restart neutron-metadata-agent)
+ and lastly update nova.
+
+ Fixes bug: 1235450
+
+diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py
+index bbaeba5..2b7f659 100644
+--- a/nova/api/metadata/handler.py
++++ b/nova/api/metadata/handler.py
+@@ -144,6 +144,7 @@ class MetadataRequestHandler(wsgi.Application):
+
+ def _handle_instance_id_request(self, req):
+ instance_id = req.headers.get('X-Instance-ID')
++ tenant_id = req.headers.get('X-Tenant-ID')
+ signature = req.headers.get('X-Instance-ID-Signature')
+ remote_address = req.headers.get('X-Forwarded-For')
+
+@@ -151,8 +152,12 @@ class MetadataRequestHandler(wsgi.Application):
+
+ if instance_id is None:
+ msg = _('X-Instance-ID header is missing from request.')
++ elif tenant_id is None:
++ msg = _('X-Tenant-ID header is missing from request.')
+ elif not isinstance(instance_id, basestring):
+ msg = _('Multiple X-Instance-ID headers found within request.')
++ elif not isinstance(tenant_id, basestring):
++ msg = _('Multiple X-Tenant-ID headers found within request.')
+ else:
+ msg = None
+
+@@ -188,4 +193,12 @@ class MetadataRequestHandler(wsgi.Application):
+ LOG.error(_('Failed to get metadata for instance id: %s'),
+ instance_id)
+
++ if meta_data.instance['project_id'] != tenant_id:
++ LOG.warning(_("Tenant_id %(tenant_id)s does not match tenant_id "
++ "of instance %(instance_id)s."),
++ {'tenant_id': tenant_id,
++ 'instance_id': instance_id})
++ # causes a 404 to be raised
++ meta_data = None
++
+ return meta_data
+diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
+index 01f274f..51b6f72 100644
+--- a/nova/tests/test_metadata.py
++++ b/nova/tests/test_metadata.py
+@@ -510,6 +510,7 @@ class MetadataHandlerTestCase(test.TestCase):
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ headers={'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+ self.assertEqual(response.status_int, 200)
+
+@@ -522,6 +523,7 @@ class MetadataHandlerTestCase(test.TestCase):
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+
+ self.assertEqual(response.status_int, 200)
+@@ -536,10 +538,36 @@ class MetadataHandlerTestCase(test.TestCase):
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': ''})
+
+ self.assertEqual(response.status_int, 403)
+
++ # missing X-Tenant-ID from request
++ response = fake_request(
++ self.stubs, self.mdinst,
++ relpath="/2009-04-04/user-data",
++ address="192.192.192.2",
++ fake_get_metadata_by_instance_id=fake_get_metadata,
++ headers={'X-Forwarded-For': '192.192.192.2',
++ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Instance-ID-Signature': signed})
++
++ self.assertEqual(response.status_int, 400)
++
++ # mismatched X-Tenant-ID
++ response = fake_request(
++ self.stubs, self.mdinst,
++ relpath="/2009-04-04/user-data",
++ address="192.192.192.2",
++ fake_get_metadata_by_instance_id=fake_get_metadata,
++ headers={'X-Forwarded-For': '192.192.192.2',
++ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'FAKE',
++ 'X-Instance-ID-Signature': signed})
++
++ self.assertEqual(response.status_int, 404)
++
+ # without X-Forwarded-For
+ response = fake_request(
+ self.stubs, self.mdinst,
+@@ -547,6 +575,7 @@ class MetadataHandlerTestCase(test.TestCase):
+ address="192.192.192.2",
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+
+ self.assertEqual(response.status_int, 500)
+@@ -564,6 +593,7 @@ class MetadataHandlerTestCase(test.TestCase):
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'z-z-z-z',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+ self.assertEqual(response.status_int, 500)
+
diff --git a/sys-cluster/nova/files/CVE-2013-6419_2013.2.patch b/sys-cluster/nova/files/CVE-2013-6419_2013.2.patch
new file mode 100644
index 000000000000..1dcfe1b9b68f
--- /dev/null
+++ b/sys-cluster/nova/files/CVE-2013-6419_2013.2.patch
@@ -0,0 +1,186 @@
+commit 2a95eee992b66cd65e401e31785c080f811476cf
+Author: Aaron Rosen <arosen@nicira.com>
+Date: Mon Oct 7 13:33:31 2013 -0700
+
+ Prevent spoofing instance_id from neturon to nova
+
+ Previously, one could update a port's device_id in neutron to be that
+ of another tenant's instance_id and then be able to retrieve that instance's
+ metadata. This patch prevents this from occuring by checking that X-Tenant-ID
+ received from the metadata request matches the tenant_id in the nova database.
+
+ DocImpact - This patch is dependent on another patch in neutron which adds
+ X-Tenant-ID to the request. Therefore to minimize downtime one
+ should upgrade Neutron first (then restart neutron-metadata-agent)
+ and lastly update nova.
+
+ Fixes bug: 1235450
+
+diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py
+index 27f4d4e..7ac9023 100644
+--- a/nova/api/metadata/handler.py
++++ b/nova/api/metadata/handler.py
+@@ -140,29 +140,34 @@ class MetadataRequestHandler(wsgi.Application):
+ 'Please try your request again.')
+ raise webob.exc.HTTPInternalServerError(explanation=unicode(msg))
+
+ if meta_data is None:
+ LOG.error(_('Failed to get metadata for ip: %s'), remote_address)
+
+ return meta_data
+
+ def _handle_instance_id_request(self, req):
+ instance_id = req.headers.get('X-Instance-ID')
++ tenant_id = req.headers.get('X-Tenant-ID')
+ signature = req.headers.get('X-Instance-ID-Signature')
+ remote_address = req.headers.get('X-Forwarded-For')
+
+ # Ensure that only one header was passed
+
+ if instance_id is None:
+ msg = _('X-Instance-ID header is missing from request.')
++ elif tenant_id is None:
++ msg = _('X-Tenant-ID header is missing from request.')
+ elif not isinstance(instance_id, basestring):
+ msg = _('Multiple X-Instance-ID headers found within request.')
++ elif not isinstance(tenant_id, basestring):
++ msg = _('Multiple X-Tenant-ID headers found within request.')
+ else:
+ msg = None
+
+ if msg:
+ raise webob.exc.HTTPBadRequest(explanation=msg)
+
+ expected_signature = hmac.new(
+ CONF.neutron_metadata_proxy_shared_secret,
+ instance_id,
+ hashlib.sha256).hexdigest()
+@@ -188,11 +193,19 @@ class MetadataRequestHandler(wsgi.Application):
+ LOG.exception(_('Failed to get metadata for instance id: %s'),
+ instance_id)
+ msg = _('An unknown error has occurred. '
+ 'Please try your request again.')
+ raise webob.exc.HTTPInternalServerError(explanation=unicode(msg))
+
+ if meta_data is None:
+ LOG.error(_('Failed to get metadata for instance id: %s'),
+ instance_id)
+
++ if meta_data.instance['project_id'] != tenant_id:
++ LOG.warning(_("Tenant_id %(tenant_id)s does not match tenant_id "
++ "of instance %(instance_id)s."),
++ {'tenant_id': tenant_id,
++ 'instance_id': instance_id})
++ # causes a 404 to be raised
++ meta_data = None
++
+ return meta_data
+diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py
+index 50f0d07..e75b51f 100644
+--- a/nova/tests/test_metadata.py
++++ b/nova/tests/test_metadata.py
+@@ -594,74 +594,104 @@ class MetadataHandlerTestCase(test.TestCase):
+ CONF.neutron_metadata_proxy_shared_secret,
+ expected_instance_id,
+ hashlib.sha256).hexdigest()
+
+ # try a request with service disabled
+ response = fake_request(
+ self.stubs, self.mdinst,
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ headers={'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+ self.assertEqual(response.status_int, 200)
+
+ # now enable the service
+ self.flags(service_neutron_metadata_proxy=True)
+ response = fake_request(
+ self.stubs, self.mdinst,
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+
+ self.assertEqual(response.status_int, 200)
+ self.assertEqual(response.body,
+ base64.b64decode(self.instance['user_data']))
+
+ # mismatched signature
+ response = fake_request(
+ self.stubs, self.mdinst,
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': ''})
+
+ self.assertEqual(response.status_int, 403)
+
++ # missing X-Tenant-ID from request
++ response = fake_request(
++ self.stubs, self.mdinst,
++ relpath="/2009-04-04/user-data",
++ address="192.192.192.2",
++ fake_get_metadata_by_instance_id=fake_get_metadata,
++ headers={'X-Forwarded-For': '192.192.192.2',
++ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Instance-ID-Signature': signed})
++
++ self.assertEqual(response.status_int, 400)
++
++ # mismatched X-Tenant-ID
++ response = fake_request(
++ self.stubs, self.mdinst,
++ relpath="/2009-04-04/user-data",
++ address="192.192.192.2",
++ fake_get_metadata_by_instance_id=fake_get_metadata,
++ headers={'X-Forwarded-For': '192.192.192.2',
++ 'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'FAKE',
++ 'X-Instance-ID-Signature': signed})
++
++ self.assertEqual(response.status_int, 404)
++
+ # without X-Forwarded-For
+ response = fake_request(
+ self.stubs, self.mdinst,
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Instance-ID': 'a-b-c-d',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+
+ self.assertEqual(response.status_int, 500)
+
+ # unexpected Instance-ID
+ signed = hmac.new(
+ CONF.neutron_metadata_proxy_shared_secret,
+ 'z-z-z-z',
+ hashlib.sha256).hexdigest()
+
+ response = fake_request(
+ self.stubs, self.mdinst,
+ relpath="/2009-04-04/user-data",
+ address="192.192.192.2",
+ fake_get_metadata_by_instance_id=fake_get_metadata,
+ headers={'X-Forwarded-For': '192.192.192.2',
+ 'X-Instance-ID': 'z-z-z-z',
++ 'X-Tenant-ID': 'test',
+ 'X-Instance-ID-Signature': signed})
+ self.assertEqual(response.status_int, 500)
+
+
+ class MetadataPasswordTestCase(test.TestCase):
+ def setUp(self):
+ super(MetadataPasswordTestCase, self).setUp()
+ fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs)
+ self.instance = copy.copy(INSTANCES[0])
+ self.instance['system_metadata'] = get_default_sys_meta()