Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 707323 Details for
Bug 919648
CVE-2013-1838 Openstack Nova: DoS by allocating all Fixed IPs
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
CVE-2013-1838-folsom.patch
CVE-2013-1838-folsom.patch (text/plain), 21.38 KB, created by
Kurt Seifried
on 2013-03-09 07:09:32 UTC
(
hide
)
Description:
CVE-2013-1838-folsom.patch
Filename:
MIME Type:
Creator:
Kurt Seifried
Created:
2013-03-09 07:09:32 UTC
Size:
21.38 KB
patch
obsolete
>commit dbe94187193da8741b4b8c270c62eb4d9cb0bd8a >Author: Michael Still <mikal@stillhq.com> >Date: Fri Mar 1 20:22:39 2013 +0000 > > Add quotas for fixed ips. > > DocImpact: there is now a default quota of 10 fixed ips per tenant. > This will need to be adjusted by deployers if that number does not > meet their needs. > > Resolves bug 1125468 for folsom. > > Change-Id: I970d540cfa6a61b7e903703f845a6453ff55f225 > >diff --git a/nova/db/api.py b/nova/db/api.py >index bb69558..9f2ff73 100644 >--- a/nova/db/api.py >+++ b/nova/db/api.py >@@ -507,6 +507,12 @@ def fixed_ip_update(context, address, values): > """Create a fixed ip from the values dictionary.""" > return IMPL.fixed_ip_update(context, address, values) > >+ >+def fixed_ip_count_by_project(context, project_id, session=None): >+ """Count fixed ips used by project.""" >+ return IMPL.fixed_ip_count_by_project(context, project_id, >+ session=session) >+ > #################### > > >diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py >index 4bdab49..013ff69 100644 >--- a/nova/db/sqlalchemy/api.py >+++ b/nova/db/sqlalchemy/api.py >@@ -1273,6 +1273,27 @@ def fixed_ip_update(context, address, values): > fixed_ip_ref.save(session=session) > > >+@require_context >+def fixed_ip_count_by_project(context, project_id, session=None): >+ authorize_project_context(context, project_id) >+ >+ # NOTE(mikal): Yes I know this is horrible, but I couldn't >+ # get a query using a join working, mainly because of a failure >+ # to be able to express the where clause sensibly. Patches >+ # welcome. >+ session = get_session() >+ with session.begin(): >+ instance_uuid_query = model_query(context, models.Instance.uuid, >+ read_deleted="no", session=session).\ >+ filter(models.Instance.project_id == \ >+ project_id) >+ uuid_filter = models.FixedIp.instance_uuid.in_(instance_uuid_query) >+ return model_query(context, models.FixedIp, read_deleted="no", >+ session=session).\ >+ filter(uuid_filter).\ >+ count() >+ >+ > ################### > > >diff --git a/nova/exception.py b/nova/exception.py >index 2eeef04..2da5e6c 100644 >--- a/nova/exception.py >+++ b/nova/exception.py >@@ -998,6 +998,10 @@ class FloatingIpLimitExceeded(QuotaError): > message = _("Maximum number of floating ips exceeded") > > >+class FixedIpLimitExceeded(QuotaError): >+ message = _("Maximum number of fixed ips exceeded") >+ >+ > class MetadataLimitExceeded(QuotaError): > message = _("Maximum number of metadata items exceeds %(allowed)d") > >diff --git a/nova/network/manager.py b/nova/network/manager.py >index 00a6e58..df4493b 100644 >--- a/nova/network/manager.py >+++ b/nova/network/manager.py >@@ -1294,37 +1294,53 @@ class NetworkManager(manager.SchedulerDependentManager): > address = None > instance_ref = self.db.instance_get(context, instance_id) > >- if network['cidr']: >- address = kwargs.get('address', None) >- if address: >- address = self.db.fixed_ip_associate(context, >- address, >- instance_ref['uuid'], >- network['id']) >- else: >- address = self.db.fixed_ip_associate_pool(context.elevated(), >- network['id'], >- instance_ref['uuid']) >- self._do_trigger_security_group_members_refresh_for_instance( >- instance_id) >- get_vif = self.db.virtual_interface_get_by_instance_and_network >- vif = get_vif(context, instance_ref['uuid'], network['id']) >- values = {'allocated': True, >- 'virtual_interface_id': vif['id']} >- self.db.fixed_ip_update(context, address, values) >- >- name = instance_ref['display_name'] >- >- if self._validate_instance_zone_for_dns_domain(context, instance_ref): >- uuid = instance_ref['uuid'] >- self.instance_dns_manager.create_entry(name, address, >- "A", >- self.instance_dns_domain) >- self.instance_dns_manager.create_entry(uuid, address, >- "A", >- self.instance_dns_domain) >- self._setup_network_on_host(context, network) >- return address >+ # Check the quota; can't put this in the API because we get >+ # called into from other places >+ try: >+ reservations = QUOTAS.reserve(context, fixed_ips=1) >+ except exception.OverQuota: >+ pid = context.project_id >+ LOG.warn(_("Quota exceeded for %(pid)s, tried to allocate " >+ "fixed IP") % locals()) >+ raise exception.FixedIpLimitExceeded() >+ >+ try: >+ if network['cidr']: >+ address = kwargs.get('address', None) >+ if address: >+ address = self.db.fixed_ip_associate(context, >+ address, >+ instance_ref['uuid'], >+ network['id']) >+ else: >+ address = self.db.fixed_ip_associate_pool( >+ context.elevated(), network['id'], >+ instance_ref['uuid']) >+ self._do_trigger_security_group_members_refresh_for_instance( >+ instance_id) >+ get_vif = self.db.virtual_interface_get_by_instance_and_network >+ vif = get_vif(context, instance_ref['uuid'], network['id']) >+ values = {'allocated': True, >+ 'virtual_interface_id': vif['id']} >+ self.db.fixed_ip_update(context, address, values) >+ >+ name = instance_ref['display_name'] >+ >+ if self._validate_instance_zone_for_dns_domain(context, >+ instance_ref): >+ uuid = instance_ref['uuid'] >+ self.instance_dns_manager.create_entry( >+ name, address, "A", self.instance_dns_domain) >+ self.instance_dns_manager.create_entry( >+ uuid, address, "A", self.instance_dns_domain) >+ self._setup_network_on_host(context, network) >+ >+ QUOTAS.commit(context, reservations) >+ return address >+ >+ except Exception: >+ with excutils.save_and_reraise_exception(): >+ QUOTAS.rollback(context, reservations) > > def deallocate_fixed_ip(self, context, address, host=None, teardown=True): > """Returns a fixed ip to the pool.""" >@@ -1334,6 +1350,13 @@ class NetworkManager(manager.SchedulerDependentManager): > context.elevated(read_deleted='yes'), > fixed_ip_ref['instance_uuid']) > >+ try: >+ reservations = QUOTAS.reserve(context, fixed_ips=-1) >+ except Exception: >+ reservations = None >+ LOG.exception(_("Failed to update usages deallocating " >+ "fixed IP")) >+ > self._do_trigger_security_group_members_refresh_for_instance( > instance['uuid']) > >@@ -1373,6 +1396,10 @@ class NetworkManager(manager.SchedulerDependentManager): > # callback will get called by nova-dhcpbridge. > self.driver.release_dhcp(dev, address, vif['address']) > >+ # Commit the reservations >+ if reservations: >+ QUOTAS.commit(context, reservations) >+ > def lease_fixed_ip(self, context, address): > """Called by dhcp-bridge when ip is leased.""" > LOG.debug(_('Leased IP |%(address)s|'), locals(), context=context) >diff --git a/nova/quota.py b/nova/quota.py >index d3ba0aa..31e2794 100644 >--- a/nova/quota.py >+++ b/nova/quota.py >@@ -50,6 +50,10 @@ quota_opts = [ > cfg.IntOpt('quota_floating_ips', > default=10, > help='number of floating ips allowed per project'), >+ cfg.IntOpt('quota_fixed_ips', >+ default=10, >+ help=('number of fixed ips allowed per project (this should be ' >+ 'at least the number of instances allowed)')), > cfg.IntOpt('quota_metadata_items', > default=128, > help='number of metadata items allowed per instance'), >@@ -778,6 +782,11 @@ def _sync_floating_ips(context, project_id, session): > context, project_id, session=session)) > > >+def _sync_fixed_ips(context, project_id, session): >+ return dict(fixed_ips=db.fixed_ip_count_by_project( >+ context, project_id, session=session)) >+ >+ > def _sync_security_groups(context, project_id, session): > return dict(security_groups=db.security_group_count_by_project( > context, project_id, session=session)) >@@ -794,6 +803,7 @@ resources = [ > ReservableResource('gigabytes', _sync_volumes, 'quota_gigabytes'), > ReservableResource('floating_ips', _sync_floating_ips, > 'quota_floating_ips'), >+ ReservableResource('fixed_ips', _sync_fixed_ips, 'quota_fixed_ips'), > AbsoluteResource('metadata_items', 'quota_metadata_items'), > AbsoluteResource('injected_files', 'quota_injected_files'), > AbsoluteResource('injected_file_content_bytes', >diff --git a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py >index b732f88..5bee208 100644 >--- a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py >+++ b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py >@@ -25,10 +25,11 @@ from nova.tests.api.openstack import fakes > def quota_set(class_name): > return {'quota_class_set': {'id': class_name, 'metadata_items': 128, > 'volumes': 10, 'gigabytes': 1000, 'ram': 51200, >- 'floating_ips': 10, 'instances': 10, 'injected_files': 5, >- 'cores': 20, 'injected_file_content_bytes': 10240, >- 'security_groups': 10, 'security_group_rules': 20, >- 'key_pairs': 100, 'injected_file_path_bytes': 255}} >+ 'floating_ips': 10, 'fixed_ips': 10, 'instances': 10, >+ 'injected_files': 5, 'cores': 20, >+ 'injected_file_content_bytes': 10240, 'security_groups': 10, >+ 'security_group_rules': 20, 'key_pairs': 100, >+ 'injected_file_path_bytes': 255}} > > > class QuotaClassSetsTest(test.TestCase): >@@ -44,6 +45,7 @@ class QuotaClassSetsTest(test.TestCase): > 'ram': 51200, > 'volumes': 10, > 'floating_ips': 10, >+ 'fixed_ips': 10, > 'metadata_items': 128, > 'gigabytes': 1000, > 'injected_files': 5, >@@ -91,7 +93,8 @@ class QuotaClassSetsTest(test.TestCase): > body = {'quota_class_set': {'instances': 50, 'cores': 50, > 'ram': 51200, 'volumes': 10, > 'gigabytes': 1000, 'floating_ips': 10, >- 'metadata_items': 128, 'injected_files': 5, >+ 'fixed_ips': 10, 'metadata_items': 128, >+ 'injected_files': 5, > 'injected_file_content_bytes': 10240, > 'injected_file_path_bytes': 255, > 'security_groups': 10, >@@ -139,6 +142,7 @@ class QuotaTemplateXMLSerializerTest(test.TestCase): > gigabytes=40, > ram=50, > floating_ips=60, >+ fixed_ips=10, > instances=70, > injected_files=80, > security_groups=10, >diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py >index f628535..adfe129 100644 >--- a/nova/tests/api/openstack/compute/contrib/test_quotas.py >+++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py >@@ -26,11 +26,12 @@ from nova.tests.api.openstack import fakes > > def quota_set(id): > return {'quota_set': {'id': id, 'metadata_items': 128, 'volumes': 10, >- 'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10, >- 'instances': 10, 'injected_files': 5, 'cores': 20, >- 'injected_file_content_bytes': 10240, >- 'security_groups': 10, 'security_group_rules': 20, >- 'key_pairs': 100, 'injected_file_path_bytes': 255}} >+ 'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10, >+ 'fixed_ips': 10, 'instances': 10, >+ 'injected_files': 5, 'cores': 20, >+ 'injected_file_content_bytes': 10240, >+ 'security_groups': 10, 'security_group_rules': 20, >+ 'key_pairs': 100, 'injected_file_path_bytes': 255}} > > > class QuotaSetsTest(test.TestCase): >@@ -46,6 +47,7 @@ class QuotaSetsTest(test.TestCase): > 'ram': 51200, > 'volumes': 10, > 'floating_ips': 10, >+ 'fixed_ips': 10, > 'metadata_items': 128, > 'gigabytes': 1000, > 'injected_files': 5, >@@ -88,6 +90,7 @@ class QuotaSetsTest(test.TestCase): > 'volumes': 10, > 'gigabytes': 1000, > 'floating_ips': 10, >+ 'fixed_ips': 10, > 'metadata_items': 128, > 'injected_files': 5, > 'injected_file_path_bytes': 255, >@@ -120,7 +123,7 @@ class QuotaSetsTest(test.TestCase): > 'injected_file_path_bytes': 255, > 'security_groups': 10, > 'security_group_rules': 20, >- 'key_pairs': 100}} >+ 'key_pairs': 100, 'fixed_ips': 10}} > > req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me', > use_admin_context=True) >@@ -171,6 +174,7 @@ class QuotaXMLSerializerTest(test.TestCase): > gigabytes=40, > ram=50, > floating_ips=60, >+ fixed_ips=10, > instances=70, > injected_files=80, > security_groups=10, >diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py >index e983ad6..f27a176 100644 >--- a/nova/tests/network/test_manager.py >+++ b/nova/tests/network/test_manager.py >@@ -30,6 +30,7 @@ from nova.openstack.common import importutils > from nova.openstack.common import log as logging > from nova.openstack.common import rpc > import nova.policy >+from nova import quota > from nova import test > from nova.tests import fake_network > from nova import utils >@@ -278,6 +279,7 @@ class FlatNetworkTestCase(test.TestCase): > self.mox.StubOutWithMock(db, > 'virtual_interface_get_by_instance_and_network') > self.mox.StubOutWithMock(db, 'fixed_ip_update') >+ self.mox.StubOutWithMock(quota.QUOTAS, 'reserve') > > db.fixed_ip_update(mox.IgnoreArg(), > mox.IgnoreArg(), >@@ -291,6 +293,10 @@ class FlatNetworkTestCase(test.TestCase): > db.instance_get(mox.IgnoreArg(), > mox.IgnoreArg()).AndReturn({'security_groups': > [{'id': 0}]}) >+ >+ quota.QUOTAS.reserve(mox.IgnoreArg(), >+ fixed_ips=mox.IgnoreArg()).AndReturn(None) >+ > db.fixed_ip_associate_pool(mox.IgnoreArg(), > mox.IgnoreArg(), > mox.IgnoreArg()).AndReturn('192.168.0.101') >@@ -310,6 +316,7 @@ class FlatNetworkTestCase(test.TestCase): > self.mox.StubOutWithMock(db, > 'virtual_interface_get_by_instance_and_network') > self.mox.StubOutWithMock(db, 'fixed_ip_update') >+ self.mox.StubOutWithMock(quota.QUOTAS, 'reserve') > > db.fixed_ip_update(mox.IgnoreArg(), > mox.IgnoreArg(), >@@ -323,6 +330,10 @@ class FlatNetworkTestCase(test.TestCase): > db.instance_get(mox.IgnoreArg(), > mox.IgnoreArg()).AndReturn({'security_groups': > [{'id': 0}]}) >+ >+ quota.QUOTAS.reserve(mox.IgnoreArg(), >+ fixed_ips=mox.IgnoreArg()).AndReturn(None) >+ > db.fixed_ip_associate_pool(mox.IgnoreArg(), > mox.IgnoreArg(), > mox.IgnoreArg()).AndReturn('192.168.0.101') >@@ -376,6 +387,7 @@ class FlatNetworkTestCase(test.TestCase): > self.mox.StubOutWithMock(db, > 'virtual_interface_get_by_instance_and_network') > self.mox.StubOutWithMock(db, 'fixed_ip_update') >+ self.mox.StubOutWithMock(quota.QUOTAS, 'reserve') > > db.fixed_ip_update(mox.IgnoreArg(), > mox.IgnoreArg(), >@@ -390,6 +402,9 @@ class FlatNetworkTestCase(test.TestCase): > mox.IgnoreArg()).AndReturn({'security_groups': > [{'id': 0}]}) > >+ quota.QUOTAS.reserve(mox.IgnoreArg(), >+ fixed_ips=mox.IgnoreArg()).AndReturn(None) >+ > db.fixed_ip_associate_pool(mox.IgnoreArg(), > mox.IgnoreArg(), > mox.IgnoreArg()).AndReturn(fixedip) >diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py >index dd86c7c..5baf966 100644 >--- a/nova/tests/test_quota.py >+++ b/nova/tests/test_quota.py >@@ -723,6 +723,7 @@ class DbQuotaDriverTestCase(test.TestCase): > quota_volumes=10, > quota_gigabytes=1000, > quota_floating_ips=10, >+ quota_fixed_ips=10, > quota_metadata_items=128, > quota_injected_files=5, > quota_injected_file_content_bytes=10 * 1024, >@@ -755,6 +756,7 @@ class DbQuotaDriverTestCase(test.TestCase): > volumes=10, > gigabytes=1000, > floating_ips=10, >+ fixed_ips=10, > metadata_items=128, > injected_files=5, > injected_file_content_bytes=10 * 1024, >@@ -791,6 +793,7 @@ class DbQuotaDriverTestCase(test.TestCase): > volumes=10, > gigabytes=500, > floating_ips=10, >+ fixed_ips=10, > metadata_items=64, > injected_files=5, > injected_file_content_bytes=5 * 1024, >@@ -847,6 +850,7 @@ class DbQuotaDriverTestCase(test.TestCase): > self._stub_quota_class_get_all_by_name() > > def test_get_project_quotas(self): >+ self.maxDiff = None > self._stub_get_by_project() > result = self.driver.get_project_quotas( > FakeContext('test_project', 'test_class'), >@@ -888,6 +892,11 @@ class DbQuotaDriverTestCase(test.TestCase): > in_use=2, > reserved=0, > ), >+ fixed_ips=dict( >+ limit=10, >+ in_use=0, >+ reserved=0, >+ ), > metadata_items=dict( > limit=64, > in_use=0, >@@ -926,6 +935,7 @@ class DbQuotaDriverTestCase(test.TestCase): > )) > > def test_get_project_quotas_alt_context_no_class(self): >+ self.maxDiff = None > self._stub_get_by_project() > result = self.driver.get_project_quotas( > FakeContext('other_project', 'other_class'), >@@ -966,6 +976,11 @@ class DbQuotaDriverTestCase(test.TestCase): > in_use=2, > reserved=0, > ), >+ fixed_ips=dict( >+ limit=10, >+ in_use=0, >+ reserved=0, >+ ), > metadata_items=dict( > limit=128, > in_use=0, >@@ -1004,6 +1019,7 @@ class DbQuotaDriverTestCase(test.TestCase): > )) > > def test_get_project_quotas_alt_context_with_class(self): >+ self.maxDiff = None > self._stub_get_by_project() > result = self.driver.get_project_quotas( > FakeContext('other_project', 'other_class'), >@@ -1045,6 +1061,11 @@ class DbQuotaDriverTestCase(test.TestCase): > in_use=2, > reserved=0, > ), >+ fixed_ips=dict( >+ limit=10, >+ in_use=0, >+ reserved=0, >+ ), > metadata_items=dict( > limit=64, > in_use=0, >@@ -1145,6 +1166,9 @@ class DbQuotaDriverTestCase(test.TestCase): > floating_ips=dict( > limit=10, > ), >+ fixed_ips=dict( >+ limit=10, >+ ), > metadata_items=dict( > limit=64, > ),
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 919648
:
707322
| 707323 |
707324