130 lines
4.8 KiB
Diff
130 lines
4.8 KiB
Diff
From 70efac04ab3034e729e6d42c2c2d7f5687f98fb2 Mon Sep 17 00:00:00 2001
|
|
From: Clemens Famulla-Conrad <cfamullaconrad@suse.com>
|
|
Date: Tue, 18 Nov 2025 12:12:28 +0100
|
|
Subject: [PATCH] bsc#1236353 (CVE-2025-0650) ovn: egress ACLs may be bypassed
|
|
via specially crafted UDP packet
|
|
Reference: bsc#1236353
|
|
Upstream: 4140fead049ecef6a6b0f90e74f5de7d5a40fd5d
|
|
|
|
Backported upstream fix 4140fead0 without tests.
|
|
|
|
---
|
|
|
|
[PATCH 1/1] Skip only OVN DNS responder packets from OUT_ACL.
|
|
|
|
When OVN's DNS caching feature is enabled, due to the OpenFlow rules
|
|
that OVN installs in Open vSwitch, it is possible for an attacker to
|
|
craft a UDP packet that can bypass egress ACL rules configured on the
|
|
same switch that has DNS caching configured.
|
|
|
|
This patch fixes the issue by setting a register bit when OVN's DNS
|
|
responder replies to an incoming request. Then the flow that allows
|
|
egress ACL bypass only applies to packets that have this register bit
|
|
set. This gives the intended effect of allowing internally-generated DNS
|
|
responses to not be blocked by user-defined ACLs without potentially
|
|
compromising the security of the switch.
|
|
|
|
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
Signed-off-by: Mark Michelson <mmichels@redhat.com>
|
|
Acked-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
|
---
|
|
controller/pinctrl.c | 27 +++++++++++++++++++++++++++
|
|
include/ovn/logical-fields.h | 1 +
|
|
lib/logical-fields.c | 3 +++
|
|
northd/northd.c | 3 ++-
|
|
4 files changed, 33 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
|
|
index 633b73d6a..1e08bb6b9 100644
|
|
--- a/controller/pinctrl.c
|
|
+++ b/controller/pinctrl.c
|
|
@@ -383,6 +383,8 @@ static void pinctrl_handle_put_fdb(const struct flow *md,
|
|
const struct flow *headers)
|
|
OVS_REQUIRES(pinctrl_mutex);
|
|
|
|
+static void set_from_ctrl_flag_in_pkt_metadata(struct ofputil_packet_in *);
|
|
+
|
|
COVERAGE_DEFINE(pinctrl_drop_put_mac_binding);
|
|
COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map);
|
|
COVERAGE_DEFINE(pinctrl_drop_controller_event);
|
|
@@ -3203,6 +3205,10 @@ exit:
|
|
union mf_subvalue sv;
|
|
sv.u8_val = success;
|
|
mf_write_subfield(&dst, &sv, &pin->flow_metadata);
|
|
+
|
|
+ /* Indicate that this packet is from ovn-controller. */
|
|
+ set_from_ctrl_flag_in_pkt_metadata(pin);
|
|
+
|
|
}
|
|
queue_msg(swconn, ofputil_encode_resume(pin, continuation, proto));
|
|
dp_packet_uninit(pkt_out_ptr);
|
|
@@ -8366,3 +8372,24 @@ pinctrl_handle_put_fdb(const struct flow *md, const struct flow *headers)
|
|
ovn_fdb_add(&put_fdbs, dp_key, headers->dl_src, port_key);
|
|
notify_pinctrl_main();
|
|
}
|
|
+
|
|
+/* This function sets the register bit 'MLF_FROM_CTRL_BIT'
|
|
+ * in the register 'MFF_LOG_FLAGS' to indicate that this packet
|
|
+ * is generated/sent by ovn-controller.
|
|
+ * ovn-northd can add logical flows to match on "flags.from_ctrl".
|
|
+ */
|
|
+static void
|
|
+set_from_ctrl_flag_in_pkt_metadata(struct ofputil_packet_in *pin)
|
|
+{
|
|
+ const struct mf_field *f = mf_from_id(MFF_LOG_FLAGS);
|
|
+
|
|
+ struct mf_subfield dst = {
|
|
+ .field = f,
|
|
+ .ofs = MLF_FROM_CTRL_BIT,
|
|
+ .n_bits = 1,
|
|
+ };
|
|
+
|
|
+ union mf_subvalue sv;
|
|
+ sv.u8_val = 1;
|
|
+ mf_write_subfield(&dst, &sv, &pin->flow_metadata);
|
|
+}
|
|
diff --git a/include/ovn/logical-fields.h b/include/ovn/logical-fields.h
|
|
index 272277ec4..2770705e3 100644
|
|
--- a/include/ovn/logical-fields.h
|
|
+++ b/include/ovn/logical-fields.h
|
|
@@ -78,6 +78,7 @@ enum mff_log_flags_bits {
|
|
MLF_LOOKUP_COMMIT_ECMP_NH_BIT = 13,
|
|
MLF_USE_LB_AFF_SESSION_BIT = 14,
|
|
MLF_LOCALNET_BIT = 15,
|
|
+ MLF_FROM_CTRL_BIT = 16,
|
|
};
|
|
|
|
/* MFF_LOG_FLAGS_REG flag assignments */
|
|
diff --git a/lib/logical-fields.c b/lib/logical-fields.c
|
|
index 7a1e66d0a..4069e6a82 100644
|
|
--- a/lib/logical-fields.c
|
|
+++ b/lib/logical-fields.c
|
|
@@ -134,6 +134,9 @@ ovn_init_symtab(struct shash *symtab)
|
|
expr_symtab_add_subfield(symtab, "flags.localnet", NULL,
|
|
flags_str);
|
|
|
|
+ snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_FROM_CTRL_BIT);
|
|
+ expr_symtab_add_subfield(symtab, "flags.from_ctrl", NULL, flags_str);
|
|
+
|
|
/* Connection tracking state. */
|
|
expr_symtab_add_field_scoped(symtab, "ct_mark", MFF_CT_MARK, NULL, false,
|
|
WR_CT_COMMIT);
|
|
diff --git a/northd/northd.c b/northd/northd.c
|
|
index 39b5d5ccb..dc67779f9 100644
|
|
--- a/northd/northd.c
|
|
+++ b/northd/northd.c
|
|
@@ -6979,7 +6979,8 @@ build_acls(struct ovn_datapath *od, const struct chassis_features *features,
|
|
if (ls_has_dns_records(od->nbs)) {
|
|
const char *dns_actions = has_stateful ? "ct_commit; next;" : "next;";
|
|
ovn_lflow_add(
|
|
- lflows, od, S_SWITCH_OUT_ACL, 34000, "udp.src == 53",
|
|
+ lflows, od, S_SWITCH_OUT_ACL, 34000,
|
|
+ "flags.from_ctrl && udp.src == 53",
|
|
dns_actions);
|
|
}
|
|
|
|
--
|
|
2.51.0
|
|
|