Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
7bdf789913
!195 [sync] PR-191: fix CVE-2022-2639
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2024-03-30 01:56:15 +00:00
yangl777
978d1a1bb4 fix CVE-2022-2639
(cherry picked from commit 2f402806186fa272296c8d8aa112c822625310f8)
2024-03-29 15:18:15 +08:00
openeuler-ci-bot
ba5a606bf5
!188 [sync] PR-185: fix CVE-2023-3966
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2024-02-21 01:09:58 +00:00
zppzhangpan
ccad8b61bb fix CVE-2023-3966
(cherry picked from commit c99552111ab98cfd61d0714873fed83d8780dd00)
2024-02-20 19:48:41 +08:00
openeuler-ci-bot
82db44f780
!179 [sync] PR-173: fix file conflicts
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2023-12-20 06:49:20 +00:00
zhouwenpei
7c70c29ae0 fix file conflicts
(cherry picked from commit 0048a0f3fd9ab9d0ff2205cc2a3f3528e2ed98b5)
2023-12-18 14:45:49 +08:00
openeuler-ci-bot
15046ac5c0
!169 [sync] PR-168: 【轻量级 PR】:sync add loongarch64 and sw_64 support
From: @openeuler-sync-bot 
Reviewed-by: @sunsuwan 
Signed-off-by: @sunsuwan
2023-10-13 08:38:42 +00:00
周文培
de90fb1ecf sync add loongarch64 and sw_64 support
Signed-off-by: 周文培 <zhouwenpei050@chinasoftinc.com>
(cherry picked from commit 79ef4d55596c44aef9b88993427f1ef9def48a67)
2023-10-13 14:42:10 +08:00
openeuler-ci-bot
3cf6929bd1
!167 [sync] PR-162: fix CVE-2023-5366
From: @openeuler-sync-bot 
Reviewed-by: @sunsuwan 
Signed-off-by: @sunsuwan
2023-10-13 06:41:33 +00:00
zhouwenpei
79453b9052 fix CVE-2023-5366
(cherry picked from commit dc8f6989742914b7c72d798f7f30d427332aaa4b)
2023-10-09 16:00:20 +08:00
6 changed files with 695 additions and 4 deletions

View File

@ -0,0 +1,160 @@
From 87f191a3a398ae495fa55d70ca5fe5d813bd284f Mon Sep 17 00:00:00 2001
From: Ilya Maximets <i.maximets@ovn.org>
Date: Sun, 14 Aug 2022 16:45:59 +0200
Subject: [PATCH] netdev-offload-tc: Fix the mask for tunnel metadata length.
'wc.masks.tunnel.metadata.present.len' must be a mask for the same
field in the flow key, but in the tc_flower structure it's the real
length of metadata masks.
That is correctly handled for the individual opt->length, setting all
the masks to 0x1f like it's done in the tun_metadata_to_geneve_mask__(),
but not handled for the main 'len' field.
Fix that by setting the mask to 0xff like it's done during the flow
translation in xlate_actions() and during the flow dump in the
tun_metadata_from_geneve_nlattr().
Also, flower always has an exact match on the present.len field
regardless of its value and regardless of this field being masked
by OVS flow translation layer while installing the flow. Hence,
all tunnel flows dumped from TC should have an exact match on
present.len and also UDPIF flag, because present.len doesn't make
sense without that flag. Without the change, zero-length options
match is incorrectly reported as a wildcard match. The side effect
though is that zero-length match on geneve options is reported even
for other tunnel types, e.g. vxlan. But that should be fairly
harmless. To avoid reporting a match on empty geneve options for
vxlan/etc. tunnels we'll need to check the tunnel port type, there
is no enough information in the TUNNEL attribute itself.
Extra checks and comments added around the code to better explain
what is going on.
Fixes: a468645c6d33 ("lib/tc: add geneve with option match offload")
Reviewed-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reference:https://github.com/openvswitch/ovs/commit/87f191a3a398ae495fa55d70ca5fe5d813bd284f
Conflict:Context adaptation
---
lib/netdev-offload-tc.c | 33 +++++++++++++++++++++++----------
lib/tc.c | 13 ++++++++++---
2 files changed, 33 insertions(+), 13 deletions(-)
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 68c4c7e..2383fe2 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -476,30 +476,42 @@ flower_tun_opt_to_match(struct match *match, struct tc_flower *flower)
struct geneve_opt *opt, *opt_mask;
int len, cnt = 0;
+ /* Options are always in UDPIF format in the 'flower'. */
+ match->flow.tunnel.flags |= FLOW_TNL_F_UDPIF;
+ match->wc.masks.tunnel.flags |= FLOW_TNL_F_UDPIF;
+
+ match->flow.tunnel.metadata.present.len =
+ flower->key.tunnel.metadata.present.len;
+ /* In the 'flower' mask len is an actual length, not a mask. But in the
+ * 'match' it is an actual mask, so should be an exact match, because TC
+ * will always match on the exact value. */
+ match->wc.masks.tunnel.metadata.present.len = 0xff;
+
+ if (!flower->key.tunnel.metadata.present.len) {
+ /* No options present. */
+ return;
+ }
+
memcpy(match->flow.tunnel.metadata.opts.gnv,
flower->key.tunnel.metadata.opts.gnv,
flower->key.tunnel.metadata.present.len);
- match->flow.tunnel.metadata.present.len =
- flower->key.tunnel.metadata.present.len;
- match->flow.tunnel.flags |= FLOW_TNL_F_UDPIF;
memcpy(match->wc.masks.tunnel.metadata.opts.gnv,
flower->mask.tunnel.metadata.opts.gnv,
flower->mask.tunnel.metadata.present.len);
+ /* Fixing up 'length' fields of particular options, since these are
+ * also not masks, but actual lengths in the 'flower' structure. */
len = flower->key.tunnel.metadata.present.len;
while (len) {
opt = &match->flow.tunnel.metadata.opts.gnv[cnt];
opt_mask = &match->wc.masks.tunnel.metadata.opts.gnv[cnt];
+ /* "Exact" match as set in tun_metadata_to_geneve_mask__(). */
opt_mask->length = 0x1f;
cnt += sizeof(struct geneve_opt) / 4 + opt->length;
len -= sizeof(struct geneve_opt) + opt->length * 4;
}
-
- match->wc.masks.tunnel.metadata.present.len =
- flower->mask.tunnel.metadata.present.len;
- match->wc.masks.tunnel.flags |= FLOW_TNL_F_UDPIF;
}
static int
@@ -621,9 +633,8 @@ parse_tc_flower_to_match(struct tc_flower *flower,
if (flower->key.tunnel.tp_dst) {
match_set_tun_tp_dst(match, flower->key.tunnel.tp_dst);
}
- if (flower->key.tunnel.metadata.present.len) {
- flower_tun_opt_to_match(match, flower);
- }
+
+ flower_tun_opt_to_match(match, flower);
}
act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS);
@@ -1079,6 +1090,8 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
len -= sizeof(struct geneve_opt) + opt->length * 4;
}
+ /* Copying from the key and not from the mask, since in the 'flower'
+ * the length for a mask is not a mask, but the actual length. */
flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len;
}
diff --git a/lib/tc.c b/lib/tc.c
index 1e9810f..ef6138f 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -588,15 +588,17 @@ flower_tun_geneve_opt_check_len(struct tun_metadata *key,
const struct geneve_opt *opt, *opt_mask;
int len, cnt = 0;
+ if (key->present.len != mask->present.len) {
+ goto bad_length;
+ }
+
len = key->present.len;
while (len) {
opt = &key->opts.gnv[cnt];
opt_mask = &mask->opts.gnv[cnt];
if (opt->length != opt_mask->length) {
- VLOG_ERR_RL(&error_rl,
- "failed to parse tun options; key/mask length differ");
- return EINVAL;
+ goto bad_length;
}
cnt += sizeof(struct geneve_opt) / 4 + opt->length;
@@ -604,6 +606,11 @@ flower_tun_geneve_opt_check_len(struct tun_metadata *key,
}
return 0;
+
+bad_length:
+ VLOG_ERR_RL(&error_rl,
+ "failed to parse tun options; key/mask length differ");
+ return EINVAL;
}
static int
--
2.33.0

View File

@ -0,0 +1,90 @@
From 6f322ccf8a9989905b7c29420239d5f6d81f0002 Mon Sep 17 00:00:00 2001
From: Ilya Maximets <i.maximets@ovn.org>
Date: Fri, 19 Aug 2022 21:51:27 +0200
Subject: [PATCH] netdev-offload-tc: Parse tunnel options only for geneve
ports.
Cited commit correctly fixed the issue of incorrect reporting
of zero-length geneve option matches as wildcarded. But as a
side effect, exact match on the metadata length was added to
every tunnel flow match, even if the tunnel is not geneve.
That doesn't generate any functional issues, but it maybe
confusing to see 'tunnel(...,geneve(),...)' while looking at
datapath flow dumps for, e.g., vxlan tunnel flows.
Fix that by checking the port type before parsing geneve options.
tunnel() attribute itself doesn't have enough information to
figure out the tunnel type.
Fixes: 7a6c8074c5d2 ("netdev-offload-tc: Fix the mask for tunnel metadata length.")
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reference:https://github.com/openvswitch/ovs/commit/6f322ccf8a9989905b7c29420239d5f6d81f0002
Conflict: Implement terse dump support: The parse_tc_flower_to_match function has an extra parameter.
---
lib/netdev-offload-tc.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 2383fe2..b8c3738 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -515,7 +515,8 @@ flower_tun_opt_to_match(struct match *match, struct tc_flower *flower)
}
static int
-parse_tc_flower_to_match(struct tc_flower *flower,
+parse_tc_flower_to_match(const struct netdev *netdev,
+ struct tc_flower *flower,
struct match *match,
struct nlattr **actions,
struct dpif_flow_stats *stats,
@@ -634,7 +635,9 @@ parse_tc_flower_to_match(struct tc_flower *flower,
match_set_tun_tp_dst(match, flower->key.tunnel.tp_dst);
}
- flower_tun_opt_to_match(match, flower);
+ if (!strcmp(netdev_get_type(netdev), "geneve")) {
+ flower_tun_opt_to_match(match, flower);
+ }
}
act_off = nl_msg_start_nested(buf, OVS_FLOW_ATTR_ACTIONS);
@@ -760,8 +763,8 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
continue;
}
- if (parse_tc_flower_to_match(&flower, match, actions, stats, attrs,
- wbuffer)) {
+ if (parse_tc_flower_to_match(netdev, &flower, match, actions,
+ stats, attrs, wbuffer)) {
continue;
}
@@ -1145,7 +1148,9 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
flower.mask.tunnel.tos = tnl_mask->ip_tos;
flower.mask.tunnel.ttl = tnl_mask->ip_ttl;
flower.mask.tunnel.id = (tnl->flags & FLOW_TNL_F_KEY) ? tnl_mask->tun_id : 0;
- flower_match_to_tun_opt(&flower, tnl, tnl_mask);
+ if (!strcmp(netdev_get_type(netdev), "geneve")) {
+ flower_match_to_tun_opt(&flower, tnl, tnl_mask);
+ }
flower.tunnel = true;
}
memset(&mask->tunnel, 0, sizeof mask->tunnel);
@@ -1458,7 +1463,8 @@ netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED,
}
in_port = netdev_ifindex_to_odp_port(ifindex);
- parse_tc_flower_to_match(&flower, match, actions, stats, attrs, buf);
+ parse_tc_flower_to_match(netdev, &flower, match, actions,
+ stats, attrs, buf);
match->wc.masks.in_port.odp_port = u32_to_odp(UINT32_MAX);
match->flow.in_port.odp_port = in_port;
--
2.33.0

View File

@ -0,0 +1,138 @@
From b8657dada9641fbd2bd3a3f882e0862448d60910 Mon Sep 17 00:00:00 2001
From: Timothy Redaelli <tredaelli@redhat.com>
Date: Thu, 23 Nov 2023 19:47:54 +0100
Subject: [PATCH] netdev-offload-tc: Check geneve metadata length.
Currently ovs-vswitchd crashes, with hw offloading enabled, if a geneve
packet with corrupted metadata is received, because the metadata header
is not verified correctly.
This commit adds a check for geneve metadata length and, if the header
is wrong, the packet is not sent to flower.
It also includes a system-traffic test for geneve packets with corrupted
metadata.
Fixes: a468645c6d33 ("lib/tc: add geneve with option match offload")
Reported-by: Haresh Khandelwal <hakhande@redhat.com>
Signed-off-by: Timothy Redaelli <tredaelli@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Reference:https://github.com/openvswitch/ovs/commit/b8657dada9641fbd2bd3a3f882e0862448d60910
Conflict:The return value is not modified in flower_match_to_tun_opt function
---
lib/netdev-offload-tc.c | 21 +++++++++++++++++---
tests/system-offloads-traffic.at | 34 ++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index b8c3738..e248d0b 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -42,6 +42,7 @@
VLOG_DEFINE_THIS_MODULE(netdev_offload_tc);
static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
+static struct vlog_rate_limit warn_rl = VLOG_RATE_LIMIT_INIT(10, 2);
static struct hmap ufid_tc = HMAP_INITIALIZER(&ufid_tc);
static bool multi_mask_per_prio = false;
@@ -1068,12 +1069,12 @@ test_key_and_mask(struct match *match)
return 0;
}
-static void
+static int
flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
const struct flow_tnl *tnl_mask)
{
struct geneve_opt *opt, *opt_mask;
- int len, cnt = 0;
+ int tot_opt_len, len, cnt = 0;
memcpy(flower->key.tunnel.metadata.opts.gnv, tnl->metadata.opts.gnv,
tnl->metadata.present.len);
@@ -1084,7 +1085,16 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
len = flower->key.tunnel.metadata.present.len;
while (len) {
+ if (len < sizeof *opt) {
+ return EOPNOTSUPP;
+ }
+
opt = &flower->key.tunnel.metadata.opts.gnv[cnt];
+ tot_opt_len = sizeof *opt + opt->length * 4;
+ if (len < tot_opt_len) {
+ return EOPNOTSUPP;
+ }
+
opt_mask = &flower->mask.tunnel.metadata.opts.gnv[cnt];
opt_mask->length = opt->length;
@@ -1096,6 +1106,7 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
/* Copying from the key and not from the mask, since in the 'flower'
* the length for a mask is not a mask, but the actual length. */
flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len;
+ return 0;
}
static int
@@ -1149,7 +1160,11 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
flower.mask.tunnel.ttl = tnl_mask->ip_ttl;
flower.mask.tunnel.id = (tnl->flags & FLOW_TNL_F_KEY) ? tnl_mask->tun_id : 0;
if (!strcmp(netdev_get_type(netdev), "geneve")) {
- flower_match_to_tun_opt(&flower, tnl, tnl_mask);
+ err = flower_match_to_tun_opt(&flower, tnl, tnl_mask);
+ if (err) {
+ VLOG_WARN_RL(&warn_rl, "Unable to parse geneve options");
+ return err;
+ }
}
flower.tunnel = true;
}
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
index bfad66e..9643535 100644
--- a/tests/system-offloads-traffic.at
+++ b/tests/system-offloads-traffic.at
@@ -116,3 +116,37 @@ matchall
])
OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([offloads - handling of geneve corrupted metadata - offloads enabled])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START(
+ [_ADD_BR([br-underlay]) -- \
+ set bridge br0 other-config:hwaddr=f2:ff:00:00:00:01 -- \
+ set bridge br-underlay other-config:hwaddr=f2:ff:00:00:00:02])
+
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
+
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24", f2:ff:00:00:00:03)
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+ [vni 0], [address f2:ff:00:00:00:04])
+
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 03 08 00 45 00 00 52 00 01 00 00 40 11 1f f7 ac 1f 01 01 ac 1f 01 64 de c1 17 c1 00 3e 59 e9 01 00 65 58 00 00 00 00 00 03 00 02 f2 ff 00 00 00 01 f2 ff 00 00 00 04 08 00 45 00 00 1c 00 01 00 00 40 01 64 7a 0a 01 01 01 0a 01 01 64 08 00 f7 ff 00 00 00 00 > /dev/null])
+
+OVS_WAIT_UNTIL([grep -q 'Invalid Geneve tunnel metadata' ovs-vswitchd.log])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/Invalid Geneve tunnel metadata on bridge br0 while processing icmp,in_port=1,vlan_tci=0x0000,dl_src=f2:ff:00:00:00:04,dl_dst=f2:ff:00:00:00:01,nw_src=10.1.1.1,nw_dst=10.1.1.100,nw_tos=0,nw_ecn=0,nw_ttl=64,nw_frag=no,icmp_type=8,icmp_code=0/d
+/Unable to parse geneve options/d"])
+AT_CLEANUP
--
2.33.0

View File

@ -0,0 +1,36 @@
From cefa91b2332d7009bc0be5d951d6cbbf349f90f8 Mon Sep 17 00:00:00 2001
From: Paolo Valerio <pvalerio@redhat.com>
Date: Fri, 15 Apr 2022 10:08:41 +0200
Subject: [PATCH] openvswitch: fix OOB access in reserve_sfa_size()
Given a sufficiently large number of actions, while copying and
reserving memory for a new action of a new flow, if next_offset is
greater than MAX_ACTIONS_BUFSIZE, the function reserve_sfa_size() does
not return -EMSGSIZE as expected, but it allocates MAX_ACTIONS_BUFSIZE
bytes increasing actions_len by req_size. This can then lead to an OOB
write access, especially when further actions need to be copied.
Fix it by rearranging the flow action size check.
Conflict:NA
Reference:https://github.com/torvalds/linux/commit/cefa91b2332d7009bc0be5d951d6cbbf349f90f8
---
datapath/flow_netlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 0f7ab53..1f04072 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -2322,7 +2322,7 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
new_acts_size = max(next_offset + req_size, ksize(*sfa) * 2);
if (new_acts_size > MAX_ACTIONS_BUFSIZE) {
- if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) {
+ if ((next_offset + req_size) > MAX_ACTIONS_BUFSIZE) {
OVS_NLERR(log, "Flow action size exceeds max %u",
MAX_ACTIONS_BUFSIZE);
return ERR_PTR(-EMSGSIZE);
--
2.33.0

View File

@ -0,0 +1,233 @@
From 489553b1c21692063931a9f50b6849b23128443c Mon Sep 17 00:00:00 2001
From: Ilya Maximets <i.maximets@ovn.org>
Date: Fri, 17 Feb 2023 21:09:59 +0100
Subject: [PATCH] classifier: Fix missing masks on a final stage with ports
trie.
Flow lookup doesn't include masks of the final stage in a resulting
flow wildcards in case that stage had L4 ports match. Only the result
of ports trie lookup is added to the mask. It might be sufficient in
many cases, but it's not correct, because ports trie is not how we
decided that the packet didn't match in this subtable. In fact, we
used a full subtable mask in order to determine that, so all the
subtable mask bits has to be added.
Ports trie can still be used to adjust ports' mask, but it is not
sufficient to determine that the packet didn't match.
Assuming we have following 2 OpenFlow rules on the bridge:
table=0, priority=10,tcp,tp_dst=80,tcp_flags=+psh actions=drop
table=0, priority=0 actions=output(1)
The first high priority rule supposed to drop all the TCP data traffic
sent on port 80. The handshake, however, is allowed for forwarding.
Both 'tcp_flags' and 'tp_dst' are on the final stage in the flow.
Since the stage mask from that stage is not incorporated into the flow
wildcards and only ports mask is getting updated, we have the following
megaflow for the SYN packet that has no match on 'tcp_flags':
$ ovs-appctl ofproto/trace br0 "in_port=br0,tcp,tp_dst=80,tcp_flags=syn"
Megaflow: recirc_id=0,eth,tcp,in_port=LOCAL,nw_frag=no,tp_dst=80
Datapath actions: 1
If this flow is getting installed into datapath flow table, all the
packets for port 80, regardless of TCP flags, will be forwarded.
Incorporating all the looked at bits from the final stage into the
stages map in order to get all the necessary wildcards. Ports mask
has to be updated as a last step, because it doesn't cover the full
64-bit slot in the flowmap.
With this change, in the example above, OVS is producing correct
flow wildcards including match on TCP flags:
Megaflow: recirc_id=0,eth,tcp,in_port=LOCAL,nw_frag=no,tp_dst=80,tcp_flags=-psh
Datapath actions: 1
This way only -psh packets will be forwarded, as expected.
This issue affects all other fields on stage 4, not only TCP flags.
Tests included to cover tcp_flags, nd_target and ct_tp_src/dst.
First two are frequently used, ct ones are sharing the same flowmap
slot with L4 ports, so important to test.
Before the pre-computation of stage masks, flow wildcards were updated
during lookup, so there was no issue. The bits of the final stage was
lost with introduction of 'stages_map'.
Recent adjustment of segment boundaries exposed 'tcp_flags' to the issue.
Reported-at: https://github.com/openvswitch/ovs-issues/issues/272
Fixes: ca44218515f0 ("classifier: Adjust segment boundary to execute prerequisite processing.")
Fixes: fa2fdbf8d0c1 ("classifier: Pre-compute stage masks.")
Acked-by: Aaron Conole <aconole@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
---
lib/classifier.c | 25 ++++++++++---
tests/classifier.at | 88 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+), 5 deletions(-)
diff --git a/lib/classifier.c b/lib/classifier.c
index 0a89626cc30..18dbfc83ad4 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -1695,6 +1695,8 @@ find_match_wc(const struct cls_subtable *subtable, ovs_version_t version,
const struct cls_match *rule = NULL;
struct flowmap stages_map = FLOWMAP_EMPTY_INITIALIZER;
unsigned int mask_offset = 0;
+ bool adjust_ports_mask = false;
+ ovs_be32 ports_mask;
int i;
/* Try to finish early by checking fields in segments. */
@@ -1722,6 +1724,9 @@ find_match_wc(const struct cls_subtable *subtable, ovs_version_t version,
subtable->index_maps[i], flow, wc)) {
goto no_match;
}
+ /* Accumulate the map used so far. */
+ stages_map = flowmap_or(stages_map, subtable->index_maps[i]);
+
hash = flow_hash_in_minimask_range(flow, &subtable->mask,
subtable->index_maps[i],
&mask_offset, &basis);
@@ -1731,14 +1736,16 @@ find_match_wc(const struct cls_subtable *subtable, ovs_version_t version,
* unwildcarding all the ports bits, use the ports trie to figure out a
* smaller set of bits to unwildcard. */
unsigned int mbits;
- ovs_be32 value, plens, mask;
+ ovs_be32 value, plens;
- mask = miniflow_get_ports(&subtable->mask.masks);
- value = ((OVS_FORCE ovs_be32 *)flow)[TP_PORTS_OFS32] & mask;
+ ports_mask = miniflow_get_ports(&subtable->mask.masks);
+ value = ((OVS_FORCE ovs_be32 *) flow)[TP_PORTS_OFS32] & ports_mask;
mbits = trie_lookup_value(&subtable->ports_trie, &value, &plens, 32);
- ((OVS_FORCE ovs_be32 *)&wc->masks)[TP_PORTS_OFS32] |=
- mask & be32_prefix_mask(mbits);
+ ports_mask &= be32_prefix_mask(mbits);
+ ports_mask |= ((OVS_FORCE ovs_be32 *) &wc->masks)[TP_PORTS_OFS32];
+
+ adjust_ports_mask = true;
goto no_match;
}
@@ -1751,6 +1758,14 @@ find_match_wc(const struct cls_subtable *subtable, ovs_version_t version,
/* Unwildcard the bits in stages so far, as they were used in determining
* there is no match. */
flow_wildcards_fold_minimask_in_map(wc, &subtable->mask, stages_map);
+ if (adjust_ports_mask) {
+ /* This has to be done after updating flow wildcards to overwrite
+ * the ports mask back. We can't simply disable the corresponding bit
+ * in the stages map, because it has 64-bit resolution, i.e. one
+ * bit covers not only tp_src/dst, but also ct_tp_src/dst, which are
+ * not covered by the trie. */
+ ((OVS_FORCE ovs_be32 *) &wc->masks)[TP_PORTS_OFS32] = ports_mask;
+ }
return NULL;
}
diff --git a/tests/classifier.at b/tests/classifier.at
index f652b59837b..de2705653e0 100644
--- a/tests/classifier.at
+++ b/tests/classifier.at
@@ -65,6 +65,94 @@ Datapath actions: 2
OVS_VSWITCHD_STOP
AT_CLEANUP
+AT_SETUP([flow classifier - lookup segmentation - final stage])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2 3
+AT_DATA([flows.txt], [dnl
+table=0 in_port=1 priority=33,tcp,tp_dst=80,tcp_flags=+psh,action=output(2)
+table=0 in_port=1 priority=0,ip,action=drop
+table=0 in_port=2 priority=16,icmp6,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=1000::1 ,action=output(1)
+table=0 in_port=2 priority=0,ip,action=drop
+table=0 in_port=3 action=resubmit(,1)
+table=1 in_port=3 priority=45,ct_state=+trk+rpl,ct_nw_proto=6,ct_tp_src=3/0x1,tcp,tp_dst=80,tcp_flags=+psh,action=output(2)
+table=1 in_port=3 priority=10,ip,action=drop
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=80,tcp_flags=syn'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=80,tcp_flags=-psh
+Datapath actions: drop
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=80,tcp_flags=syn|ack'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=80,tcp_flags=-psh
+Datapath actions: drop
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=80,tcp_flags=ack|psh'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=80,tcp_flags=+psh
+Datapath actions: 2
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=80'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=80,tcp_flags=-psh
+Datapath actions: drop
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=79'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=0x40/0xfff0,tcp_flags=-psh
+Datapath actions: drop
+])
+
+dnl Having both the port and the tcp flags in the resulting megaflow below
+dnl is redundant, but that is how ports trie logic is implemented.
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=81'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,tcp,in_port=1,nw_frag=no,tp_dst=81,tcp_flags=-psh
+Datapath actions: drop
+])
+
+dnl nd_target is redundant in the megaflow below and it is also not relevant
+dnl for an icmp reply. Datapath may discard that match, but it is OK as long
+dnl as we have prerequisites (icmp_type) in the match as well.
+AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,eth_src=f6:d2:b0:19:5e:7b,eth_dst=d2:49:19:91:78:fe,dl_type=0x86dd,ipv6_src=1000::3,ipv6_dst=1000::4,nw_proto=58,nw_ttl=255,icmpv6_type=128,icmpv6_code=0"], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,icmp6,in_port=2,nw_ttl=255,nw_frag=no,icmp_type=0x80/0xfc,nd_target=::
+Datapath actions: drop
+])
+
+AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,eth_src=f6:d2:b0:19:5e:7b,eth_dst=d2:49:19:91:78:fe,dl_type=0x86dd,ipv6_src=1000::3,ipv6_dst=1000::4,nw_proto=58,nw_ttl=255,icmpv6_type=135,icmpv6_code=0"], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,icmp6,in_port=2,nw_ttl=255,nw_frag=no,icmp_type=0x87/0xff,icmp_code=0x0/0xff,nd_target=::
+Datapath actions: drop
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,eth_src=f6:d2:b0:19:5e:7b,eth_dst=d2:49:19:91:78:fe,dl_type=0x86dd,ipv6_src=1000::3,ipv6_dst=1000::4,nw_proto=58,nw_ttl=255,icmpv6_type=135,icmpv6_code=0,nd_target=1000::1"], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,icmp6,in_port=2,nw_ttl=255,nw_frag=no,icmp_type=0x87/0xff,icmp_code=0x0/0xff,nd_target=1000::1
+Datapath actions: 1
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 "in_port=2,eth_src=f6:d2:b0:19:5e:7b,eth_dst=d2:49:19:91:78:fe,dl_type=0x86dd,ipv6_src=1000::3,ipv6_dst=1000::4,nw_proto=58,nw_ttl=255,icmpv6_type=135,icmpv6_code=0,nd_target=1000::2"], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,eth,icmp6,in_port=2,nw_ttl=255,nw_frag=no,icmp_type=0x87/0xff,icmp_code=0x0/0xff,nd_target=1000::2
+Datapath actions: drop
+])
+
+dnl Check that ports' mask doesn't affect ct ports.
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=3,ct_state=trk|rpl,ct_nw_proto=6,ct_tp_src=3,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=80,tcp_flags=psh'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,ct_state=+rpl+trk,ct_nw_proto=6,ct_tp_src=0x1/0x1,eth,tcp,in_port=3,nw_frag=no,tp_dst=80,tcp_flags=+psh
+Datapath actions: 2
+])
+AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=3,ct_state=trk|rpl,ct_nw_proto=6,ct_tp_src=3,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=6,nw_tos=0,nw_ttl=128,tp_src=8,tp_dst=79,tcp_flags=psh'], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+ [Megaflow: recirc_id=0,ct_state=+rpl+trk,ct_nw_proto=6,ct_tp_src=0x1/0x1,eth,tcp,in_port=3,nw_frag=no,tp_dst=0x40/0xfff0,tcp_flags=+psh
+Datapath actions: drop
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
AT_BANNER([flow classifier prefix lookup])
AT_SETUP([flow classifier - prefix lookup])
OVS_VSWITCHD_START

View File

@ -1,19 +1,28 @@
# This is enabled by default for versions of the distribution that
# have Python 3 by default.
%ifarch sw_64
%define _binaries_in_noarch_packages_terminate_build 0
%endif
Name: openvswitch
Summary: Production Quality, Multilayer Open Virtual Switch
URL: http://www.openvswitch.org/
Version: 2.12.4
License: ASL 2.0 and ISC
Release: 3
Release: 8
Source: https://www.openvswitch.org/releases/openvswitch-%{version}.tar.gz
Buildroot: /tmp/openvswitch-rpm
Patch0000: 0000-openvswitch-add-stack-protector-strong.patch
Patch0002: 0002-Remove-unsupported-permission-names.patch
Patch0003: 0003-Fallback-to-read-proc-net-dev-on-linux.patch
Patch0004: backport-CVE-2022-4338.patch
Patch0005: backport-CVE-2023-1668.patch
Patch6000: backport-CVE-2022-4338.patch
Patch6001: backport-CVE-2023-1668.patch
Patch6002: backport-CVE-2023-5366.patch
Patch6003: backport-0001-CVE-2023-3966.patch
Patch6004: backport-0002-CVE-2023-3966.patch
Patch6005: backport-0003-CVE-2023-3966.patch
Patch6006: backport-CVE-2022-2639.patch
Patch9000: fix-selinux-err.patch
@ -49,6 +58,7 @@ License: ASL 2.0
BuildArch: noarch
Requires: python3
Requires: python3-six
Conflicts: openvswitch < 2.12.4-6
%{?python_provide:%python_provide python3-openvswitch = %{version}-%{release}}
%description -n python3-openvswitch
@ -56,6 +66,10 @@ Python bindings for the Open vSwitch database
%prep
%autosetup -p1
%ifarch loongarch64 sw_64
%_update_config_guess
%_update_config_sub
%endif
%build
autoreconf
@ -238,7 +252,6 @@ exit 0
%{_libdir}/lib*.so.*
/usr/sbin/ovs-vswitchd
/usr/sbin/ovsdb-server
%{python3_sitelib}/ovs
%{python3_sitelib}/ovstest
%{python3_sitearch}/ovs
/usr/share/openvswitch/scripts/ovs-check-dead-ifs
@ -286,6 +299,27 @@ exit 0
%doc README.rst NEWS rhel/README.RHEL.rst
%changelog
* Fri Mar 29 2024 yanglu <yanglu72@h-partners.com> - 2.12.4-8
- Type:CVE
- Id:CVE-2022-2639
- SUG:NA
- DESC:fix CVE-2022-2639
* Tue Feb 20 2024 zhangpan <zhangpan103@h-pattners.com> - 2.12.4-7
- fix CVE-2023-3966
* Thu Dec 14 2023 zhouwenpei <zhouwenpei1@h-partners.com> - 2.12.4-6
- Type:bugfix
- Id:NA
- SUG:NA
- DESC:fix file conflicts
* Fri Oct 13 2023 zhouwenpei <zhouwenpei1@h-partners.com.cn> - 2.12.4-5
- sync add loongarch64 and sw_64 support
* Sat Oct 07 2023 zhouwenpei <zhouwenpei1@h-partners.com> - 2.12.4-4
- fix CVE-2023-5366
* Thu Apr 13 2023 zhangpan <zhangpan103@h-pattners.com> - 2.12.4-3
- fix CVE-2023-1668