Bug#1144916: trixie-pu: package octavia/16.0.0-2

Thomas Goirand <[email protected]>
Newsgroups gmane.linux.debian.devel.release
Message-ID <178722923832.125548.1721793709172438288.reportbug__47606.9653801218$1787229451$gmane$org@zbuz.infomaniak.ch>
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:octavia
User: [email protected]
Usertags: pu

Hi,

[ Reason ]
I would like to upload Octavia octavia_16.0.0-3+deb13u1 to
p-u to address:
https://security.openstack.org/ossa/OSSA-2026-035.html
aka:
https://bugs.debian.org/1144814

[ Impact ]
As per upstream announce:
[there is] a vulnerability in Octavia quality of service (QoS) policy
authorization. By associating another project’s QoS policy with an amphora, an
authenticated user may prevent deletion of that policy. All Octavia deployments
are affected.

[ Tests ]
The patch includes tests. I have also ran the fixes through my own CI,
so I could run functional tests.

[ Risks ]
The patch only adds a "context" object here and there, it's kind of
comprehensive.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Just a new upstream patch to fix the issue.

Please allow me to upload octavia/16.0.0-3+deb13u1 to p-u.

Cheers,

Thomas Goirand (zigo)
octavia_16.0.0-3+deb13u1.debdiff (text/plain, 8 KB)
diff -Nru octavia-16.0.0/debian/changelog octavia-16.0.0/debian/changelog
--- octavia-16.0.0/debian/changelog	2025-08-22 16:56:10.000000000 +0200
+++ octavia-16.0.0/debian/changelog	2026-08-20 14:22:30.000000000 +0200
@@ -1,3 +1,11 @@
+octavia (16.0.0-3+deb13u1) trixie; urgency=medium
+
+  * CVE-2026-74248 / OSSA-2026-035: Unauthorized QoS policy deletion lock.
+    Applied upstream patch: "Fix QoS policy validation to use request context".
+    (Closes: #1144814).
+
+ -- Thomas Goirand <[email protected]>  Thu, 20 Aug 2026 14:22:30 +0200
+
 octavia (16.0.0-3) unstable; urgency=medium
 
   * Add an aphora-agent.service as this is what the Octavia user_data script
diff -Nru octavia-16.0.0/debian/patches/CVE-2026-74248_OSSA-2026-035_Fix_QoS_policy_validation_to_use_request_context.patch octavia-16.0.0/debian/patches/CVE-2026-74248_OSSA-2026-035_Fix_QoS_policy_validation_to_use_request_context.patch
--- octavia-16.0.0/debian/patches/CVE-2026-74248_OSSA-2026-035_Fix_QoS_policy_validation_to_use_request_context.patch	1970-01-01 01:00:00.000000000 +0100
+++ octavia-16.0.0/debian/patches/CVE-2026-74248_OSSA-2026-035_Fix_QoS_policy_validation_to_use_request_context.patch	2026-08-20 14:22:30.000000000 +0200
@@ -0,0 +1,134 @@
+Author: Gregory Thiemonge <[email protected]>
+Date: Thu, 23 Jul 2026 06:39:28 +0000
+Description: Fix QoS policy validation to use request context
+ The qos_policy_exists validation was using service credentials
+ instead of the user's request context when querying Neutron for
+ QoS policies. This allowed users to reference QoS policies from
+ other tenants when creating or updating a load balancer.
+ .
+ Pass the request context through qos_policy_exists, get_qos_policy,
+ and down to _get_resource so that Neutron enforces tenant scoping.
+Bug: https://launchpad.net/bugs/2161500
+Bug-Debian: https://bugs.debian.org/1144814
+Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
+Change-Id: I0a30cf54fc31b83e6c48d1b65b804659e06fd7f7
+Signed-off-by: Gregory Thiemonge <[email protected]>
+Origin: upstream, https://review.opendev.org/c/openstack/octavia/+/1000295
+Last-Update: 2026-08-19
+
+diff --git a/octavia/api/v2/controllers/load_balancer.py b/octavia/api/v2/controllers/load_balancer.py
+index 3fe5935..a2cabaf 100644
+--- a/octavia/api/v2/controllers/load_balancer.py
++++ b/octavia/api/v2/controllers/load_balancer.py
+@@ -295,7 +295,7 @@
+             load_balancer.vip_network_id = subnet.network_id
+         if load_balancer.vip_qos_policy_id:
+             validate.qos_policy_exists(
+-                qos_policy_id=load_balancer.vip_qos_policy_id)
++                qos_policy_id=load_balancer.vip_qos_policy_id, context=context)
+ 
+         # Even though we've just validated the subnet or else retrieved its ID
+         # directly from the port, we might still be missing the network.
+@@ -745,7 +745,8 @@
+             validate.qos_extension_enabled(network_driver)
+             if load_balancer.vip_qos_policy_id is not None:
+                 if db_lb.vip.qos_policy_id != load_balancer.vip_qos_policy_id:
+-                    validate.qos_policy_exists(load_balancer.vip_qos_policy_id)
++                    validate.qos_policy_exists(load_balancer.vip_qos_policy_id,
++                                               context=context)
+ 
+         if not isinstance(load_balancer.vip_sg_ids, wtypes.UnsetType):
+             if load_balancer.vip_sg_ids is None:
+diff --git a/octavia/common/validate.py b/octavia/common/validate.py
+index e2c33bc..7458b8e 100644
+--- a/octavia/common/validate.py
++++ b/octavia/common/validate.py
+@@ -350,11 +350,12 @@
+     return subnet
+ 
+ 
+-def qos_policy_exists(qos_policy_id):
++def qos_policy_exists(qos_policy_id, context=None):
+     network_driver = utils.get_network_driver()
+     qos_extension_enabled(network_driver)
+     try:
+-        qos_policy = network_driver.get_qos_policy(qos_policy_id)
++        qos_policy = network_driver.get_qos_policy(qos_policy_id,
++                                                   context=context)
+     except Exception as e:
+         raise exceptions.InvalidSubresource(
+             resource='qos_policy', id=qos_policy_id) from e
+diff --git a/octavia/network/drivers/neutron/base.py b/octavia/network/drivers/neutron/base.py
+index 063fca0..ff69486 100644
+--- a/octavia/network/drivers/neutron/base.py
++++ b/octavia/network/drivers/neutron/base.py
+@@ -281,8 +281,8 @@
+             'port', unique_item=True,
+             network_id=network_id, device_id=device_id)
+ 
+-    def get_qos_policy(self, qos_policy_id):
+-        return self._get_resource('qos_policy', qos_policy_id)
++    def get_qos_policy(self, qos_policy_id, context=None):
++        return self._get_resource('qos_policy', qos_policy_id, context=context)
+ 
+     def qos_enabled(self):
+         return self._qos_enabled
+diff --git a/octavia/network/drivers/noop_driver/driver.py b/octavia/network/drivers/noop_driver/driver.py
+index e30e065..f581af6 100644
+--- a/octavia/network/drivers/noop_driver/driver.py
++++ b/octavia/network/drivers/noop_driver/driver.py
+@@ -431,7 +431,7 @@
+ 
+         return amp_configs
+ 
+-    def get_qos_policy(self, qos_policy_id):
++    def get_qos_policy(self, qos_policy_id, context=None):
+         LOG.debug("Qos Policy %s no-op, get_qos_policy qos_policy_id %s",
+                   self.__class__.__name__, qos_policy_id)
+         self.networkconfigconfig[qos_policy_id] = (qos_policy_id,
+@@ -590,8 +590,8 @@
+             'network_models.SecurityGroup'):
+         return self.driver.get_security_group_by_id(sg_id, context=context)
+ 
+-    def get_qos_policy(self, qos_policy_id):
+-        return self.driver.get_qos_policy(qos_policy_id)
++    def get_qos_policy(self, qos_policy_id, context=None):
++        return self.driver.get_qos_policy(qos_policy_id, context=context)
+ 
+     def get_network_by_name(self, network_name):
+         return self.driver.get_network_by_name(network_name)
+diff --git a/octavia/tests/unit/common/test_validate.py b/octavia/tests/unit/common/test_validate.py
+index f2f7674..272e02f 100644
+--- a/octavia/tests/unit/common/test_validate.py
++++ b/octavia/tests/unit/common/test_validate.py
+@@ -368,12 +368,15 @@
+     def test_qos_policy_exists(self):
+         qos_policy_id = uuidutils.generate_uuid()
+         qos_policy = network_models.QosPolicy(id=qos_policy_id)
++        context = mock.Mock()
+         with mock.patch(
+                 'octavia.common.utils.get_network_driver') as net_mock:
+             net_mock.return_value.get_qos_policy.return_value = qos_policy
+             self.assertEqual(
+-                validate.qos_policy_exists(qos_policy_id),
++                validate.qos_policy_exists(qos_policy_id, context=context),
+                 qos_policy)
++            net_mock.return_value.get_qos_policy.assert_called_once_with(
++                qos_policy_id, context=context)
+ 
+             net_mock.return_value.get_qos_policy.side_effect = Exception
+             self.assertRaises(exceptions.InvalidSubresource,
+diff --git a/releasenotes/notes/fix-qos-policy-context-baa964df88ba4645.yaml b/releasenotes/notes/fix-qos-policy-context-baa964df88ba4645.yaml
+new file mode 100644
+index 0000000..5cb2850
+--- /dev/null
++++ b/releasenotes/notes/fix-qos-policy-context-baa964df88ba4645.yaml
+@@ -0,0 +1,8 @@
++---
++security:
++  - |
++    Fixed QoS policy validation to use the user's request context when
++    checking if a QoS policy exists. Previously, the validation used
++    service credentials instead of the user's context, which could allow
++    a user to assign a QoS policy belonging to another tenant to their
++    load balancer.
diff -Nru octavia-16.0.0/debian/patches/series octavia-16.0.0/debian/patches/series
--- octavia-16.0.0/debian/patches/series	2025-08-22 16:56:10.000000000 +0200
+++ octavia-16.0.0/debian/patches/series	2026-08-20 14:22:30.000000000 +0200
@@ -4,3 +4,4 @@
 use-octavia-agent-lvs-masquerade-not-lvs-masquerade.sh.patch
 compat-python3-cryptography-bookworm.patch
 fix-requirements-to-allow-python3-cryptography-38.patch
+CVE-2026-74248_OSSA-2026-035_Fix_QoS_policy_validation_to_use_request_context.patch
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.