diff --git a/SOURCES/openvswitch-3.1.0.patch b/SOURCES/openvswitch-3.1.0.patch index b146f89..e50b34d 100644 --- a/SOURCES/openvswitch-3.1.0.patch +++ b/SOURCES/openvswitch-3.1.0.patch @@ -883,6 +883,269 @@ index 4c78c4816..09f6393f8 100644 return error; } +diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c +index 4592262bd..a5fa62487 100644 +--- a/lib/netdev-offload.c ++++ b/lib/netdev-offload.c +@@ -485,11 +485,13 @@ netdev_set_hw_info(struct netdev *netdev, int type, int val) + } + + /* Protects below port hashmaps. */ +-static struct ovs_rwlock netdev_hmap_rwlock = OVS_RWLOCK_INITIALIZER; ++static struct ovs_rwlock ifindex_to_port_rwlock = OVS_RWLOCK_INITIALIZER; ++static struct ovs_rwlock port_to_netdev_rwlock ++ OVS_ACQ_BEFORE(ifindex_to_port_rwlock) = OVS_RWLOCK_INITIALIZER; + +-static struct hmap port_to_netdev OVS_GUARDED_BY(netdev_hmap_rwlock) ++static struct hmap port_to_netdev OVS_GUARDED_BY(port_to_netdev_rwlock) + = HMAP_INITIALIZER(&port_to_netdev); +-static struct hmap ifindex_to_port OVS_GUARDED_BY(netdev_hmap_rwlock) ++static struct hmap ifindex_to_port OVS_GUARDED_BY(ifindex_to_port_rwlock) + = HMAP_INITIALIZER(&ifindex_to_port); + + struct port_to_netdev_data { +@@ -506,12 +508,12 @@ struct port_to_netdev_data { + */ + bool + netdev_any_oor(void) +- OVS_EXCLUDED(netdev_hmap_rwlock) ++ OVS_EXCLUDED(port_to_netdev_rwlock) + { + struct port_to_netdev_data *data; + bool oor = false; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + struct netdev *dev = data->netdev; + +@@ -520,7 +522,7 @@ netdev_any_oor(void) + break; + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + return oor; + } +@@ -594,13 +596,13 @@ netdev_ports_flow_flush(const char *dpif_type) + { + struct port_to_netdev_data *data; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type) { + netdev_flow_flush(data->netdev); + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + } + + void +@@ -610,7 +612,7 @@ netdev_ports_traverse(const char *dpif_type, + { + struct port_to_netdev_data *data; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type) { + if (cb(data->netdev, data->dpif_port.port_no, aux)) { +@@ -618,7 +620,7 @@ netdev_ports_traverse(const char *dpif_type, + } + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + } + + struct netdev_flow_dump ** +@@ -629,7 +631,7 @@ netdev_ports_flow_dump_create(const char *dpif_type, int *ports, bool terse) + int count = 0; + int i = 0; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type) { + count++; +@@ -648,7 +650,7 @@ netdev_ports_flow_dump_create(const char *dpif_type, int *ports, bool terse) + i++; + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + *ports = i; + return dumps; +@@ -660,15 +662,15 @@ netdev_ports_flow_del(const char *dpif_type, const ovs_u128 *ufid, + { + struct port_to_netdev_data *data; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type + && !netdev_flow_del(data->netdev, ufid, stats)) { +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + return 0; + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + return ENOENT; + } +@@ -681,16 +683,16 @@ netdev_ports_flow_get(const char *dpif_type, struct match *match, + { + struct port_to_netdev_data *data; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type + && !netdev_flow_get(data->netdev, match, actions, + ufid, stats, attrs, buf)) { +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + return 0; + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + return ENOENT; + } + +@@ -702,7 +704,7 @@ netdev_ports_hash(odp_port_t port, const char *dpif_type) + + static struct port_to_netdev_data * + netdev_ports_lookup(odp_port_t port_no, const char *dpif_type) +- OVS_REQ_RDLOCK(netdev_hmap_rwlock) ++ OVS_REQ_RDLOCK(port_to_netdev_rwlock) + { + struct port_to_netdev_data *data; + +@@ -726,9 +728,9 @@ netdev_ports_insert(struct netdev *netdev, struct dpif_port *dpif_port) + + ovs_assert(dpif_type); + +- ovs_rwlock_wrlock(&netdev_hmap_rwlock); ++ ovs_rwlock_wrlock(&port_to_netdev_rwlock); + if (netdev_ports_lookup(dpif_port->port_no, dpif_type)) { +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + return EEXIST; + } + +@@ -738,14 +740,16 @@ netdev_ports_insert(struct netdev *netdev, struct dpif_port *dpif_port) + + if (ifindex >= 0) { + data->ifindex = ifindex; ++ ovs_rwlock_wrlock(&ifindex_to_port_rwlock); + hmap_insert(&ifindex_to_port, &data->ifindex_node, ifindex); ++ ovs_rwlock_unlock(&ifindex_to_port_rwlock); + } else { + data->ifindex = -1; + } + + hmap_insert(&port_to_netdev, &data->portno_node, + netdev_ports_hash(dpif_port->port_no, dpif_type)); +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + netdev_init_flow_api(netdev); + +@@ -758,12 +762,12 @@ netdev_ports_get(odp_port_t port_no, const char *dpif_type) + struct port_to_netdev_data *data; + struct netdev *ret = NULL; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + data = netdev_ports_lookup(port_no, dpif_type); + if (data) { + ret = netdev_ref(data->netdev); + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + return ret; + } +@@ -774,19 +778,21 @@ netdev_ports_remove(odp_port_t port_no, const char *dpif_type) + struct port_to_netdev_data *data; + int ret = ENOENT; + +- ovs_rwlock_wrlock(&netdev_hmap_rwlock); ++ ovs_rwlock_wrlock(&port_to_netdev_rwlock); + data = netdev_ports_lookup(port_no, dpif_type); + if (data) { + dpif_port_destroy(&data->dpif_port); + netdev_close(data->netdev); /* unref and possibly close */ + hmap_remove(&port_to_netdev, &data->portno_node); + if (data->ifindex >= 0) { ++ ovs_rwlock_wrlock(&ifindex_to_port_rwlock); + hmap_remove(&ifindex_to_port, &data->ifindex_node); ++ ovs_rwlock_unlock(&ifindex_to_port_rwlock); + } + free(data); + ret = 0; + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + + return ret; + } +@@ -798,7 +804,7 @@ netdev_ports_get_n_flows(const char *dpif_type, odp_port_t port_no, + struct port_to_netdev_data *data; + int ret = EOPNOTSUPP; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + data = netdev_ports_lookup(port_no, dpif_type); + if (data) { + uint64_t thread_n_flows[MAX_OFFLOAD_THREAD_NB] = {0}; +@@ -812,7 +818,7 @@ netdev_ports_get_n_flows(const char *dpif_type, odp_port_t port_no, + } + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + return ret; + } + +@@ -822,14 +828,14 @@ netdev_ifindex_to_odp_port(int ifindex) + struct port_to_netdev_data *data; + odp_port_t ret = 0; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&ifindex_to_port_rwlock); + HMAP_FOR_EACH_WITH_HASH (data, ifindex_node, ifindex, &ifindex_to_port) { + if (data->ifindex == ifindex) { + ret = data->dpif_port.port_no; + break; + } + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&ifindex_to_port_rwlock); + + return ret; + } +@@ -847,11 +853,11 @@ netdev_ports_flow_init(void) + { + struct port_to_netdev_data *data; + +- ovs_rwlock_rdlock(&netdev_hmap_rwlock); ++ ovs_rwlock_rdlock(&port_to_netdev_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + netdev_init_flow_api(data->netdev); + } +- ovs_rwlock_unlock(&netdev_hmap_rwlock); ++ ovs_rwlock_unlock(&port_to_netdev_rwlock); + } + + void diff --git a/lib/netdev-windows.c b/lib/netdev-windows.c index 4ad45ffa1..3fad501e3 100644 --- a/lib/netdev-windows.c @@ -1442,10 +1705,38 @@ index e05ffe312..89df92242 100644 if (result != UKEY_KEEP) { /* Clears 'recircs' if filled by revalidate_ukey(). */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c -index a9cf3cbee..cffd733c5 100644 +index a9cf3cbee..10a5844d8 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c -@@ -5211,6 +5211,7 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids) +@@ -66,6 +66,7 @@ + #include "tunnel.h" + #include "util.h" + #include "uuid.h" ++#include "vlan-bitmap.h" + + COVERAGE_DEFINE(xlate_actions); + COVERAGE_DEFINE(xlate_actions_oversize); +@@ -1028,7 +1029,10 @@ xlate_xbundle_set(struct xbundle *xbundle, + xbundle->qinq_ethtype = qinq_ethtype; + xbundle->vlan = vlan; + xbundle->trunks = trunks; +- xbundle->cvlans = cvlans; ++ if (!vlan_bitmap_equal(xbundle->cvlans, cvlans)) { ++ free(xbundle->cvlans); ++ xbundle->cvlans = vlan_bitmap_clone(cvlans); ++ } + xbundle->use_priority_tags = use_priority_tags; + xbundle->floodable = floodable; + xbundle->protected = protected; +@@ -1380,6 +1384,7 @@ xlate_xbundle_remove(struct xlate_cfg *xcfg, struct xbundle *xbundle) + ovs_list_remove(&xbundle->list_node); + bond_unref(xbundle->bond); + lacp_unref(xbundle->lacp); ++ free(xbundle->cvlans); + free(xbundle->name); + free(xbundle); + } +@@ -5211,6 +5216,7 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids) } ctx->wc->masks.nw_ttl = 0xff; @@ -1453,7 +1744,7 @@ index a9cf3cbee..cffd733c5 100644 if (flow->nw_ttl > 1) { flow->nw_ttl--; return false; -@@ -7128,6 +7129,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7128,6 +7134,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IPV4_SRC: if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src); @@ -1461,7 +1752,7 @@ index a9cf3cbee..cffd733c5 100644 flow->nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4; } break; -@@ -7135,12 +7137,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7135,12 +7142,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IPV4_DST: if (flow->dl_type == htons(ETH_TYPE_IP)) { memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst); @@ -1476,7 +1767,7 @@ index a9cf3cbee..cffd733c5 100644 wc->masks.nw_tos |= IP_DSCP_MASK; flow->nw_tos &= ~IP_DSCP_MASK; flow->nw_tos |= ofpact_get_SET_IP_DSCP(a)->dscp; -@@ -7149,6 +7153,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7149,6 +7158,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IP_ECN: if (is_ip_any(flow)) { @@ -1484,7 +1775,7 @@ index a9cf3cbee..cffd733c5 100644 wc->masks.nw_tos |= IP_ECN_MASK; flow->nw_tos &= ~IP_ECN_MASK; flow->nw_tos |= ofpact_get_SET_IP_ECN(a)->ecn; -@@ -7157,6 +7162,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7157,6 +7167,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_SET_IP_TTL: if (is_ip_any(flow)) { @@ -1492,7 +1783,7 @@ index a9cf3cbee..cffd733c5 100644 wc->masks.nw_ttl = 0xff; flow->nw_ttl = ofpact_get_SET_IP_TTL(a)->ttl; } -@@ -7224,6 +7230,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7224,6 +7235,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, /* Set the field only if the packet actually has it. */ if (mf_are_prereqs_ok(mf, flow, wc)) { @@ -1500,7 +1791,7 @@ index a9cf3cbee..cffd733c5 100644 mf_mask_field_masked(mf, ofpact_set_field_mask(set_field), wc); mf_set_flow_value_masked(mf, set_field->value, ofpact_set_field_mask(set_field), -@@ -7280,6 +7287,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, +@@ -7280,6 +7292,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, case OFPACT_DEC_TTL: wc->masks.nw_ttl = 0xff; diff --git a/SPECS/openvswitch3.1.spec b/SPECS/openvswitch3.1.spec index f06dcb1..1d32fd2 100644 --- a/SPECS/openvswitch3.1.spec +++ b/SPECS/openvswitch3.1.spec @@ -63,7 +63,7 @@ Summary: Open vSwitch Group: System Environment/Daemons daemon/database/utilities URL: http://www.openvswitch.org/ Version: 3.1.0 -Release: 27%{?dist} +Release: 28%{?dist} # Nearly all of openvswitch is ASL 2.0. The bugtool is LGPLv2+, and the # lib/sflow*.[ch] files are SISSL @@ -757,6 +757,13 @@ exit 0 %endif %changelog +* Wed May 10 2023 Open vSwitch CI - 3.1.0-28 +- Merging upstream branch-3.1 [RH git: d7b0d724f2] + Commit list: + 9e27e8fe81 netdev-offload: Fix deadlock/recursive use of the netdev_hmap_rwlock rwlock. (#2182541) + 087439e416 ofproto-dpif-xlate: Fix use-after-free when xlate_actions(). + + * Fri May 05 2023 Open vSwitch CI - 3.1.0-27 - Merging upstream branch-3.1 [RH git: a0b74d148b] Commit list: