Compare commits
10 Commits
4bac8cea04
...
7bdf789913
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bdf789913 | ||
|
|
978d1a1bb4 | ||
|
|
ba5a606bf5 | ||
|
|
ccad8b61bb | ||
|
|
82db44f780 | ||
|
|
7c70c29ae0 | ||
|
|
15046ac5c0 | ||
|
|
de90fb1ecf | ||
|
|
3cf6929bd1 | ||
|
|
79453b9052 |
160
backport-0001-CVE-2023-3966.patch
Normal file
160
backport-0001-CVE-2023-3966.patch
Normal 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
|
||||
|
||||
90
backport-0002-CVE-2023-3966.patch
Normal file
90
backport-0002-CVE-2023-3966.patch
Normal 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
|
||||
|
||||
138
backport-0003-CVE-2023-3966.patch
Normal file
138
backport-0003-CVE-2023-3966.patch
Normal 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
|
||||
|
||||
36
backport-CVE-2022-2639.patch
Normal file
36
backport-CVE-2022-2639.patch
Normal 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
|
||||
|
||||
233
backport-CVE-2023-5366.patch
Normal file
233
backport-CVE-2023-5366.patch
Normal 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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user