diff options
author | Yifeng Sun <pkusunyifeng@gmail.com> | 2020-04-09 11:37:38 -0700 |
---|---|---|
committer | William Tu <u9012063@gmail.com> | 2020-04-10 07:08:27 -0700 |
commit | 02f641e2c583799eb38d3b4a59ba5872da04c6d9 (patch) | |
tree | 85e35d8707eb0e278f176eb38b2ee20df0223865 /ofproto/ofproto-dpif-rid.h | |
parent | 9e6c00bca9af29031d0e160d33174b7ae99b9244 (diff) | |
download | openvswitch-02f641e2c583799eb38d3b4a59ba5872da04c6d9.tar.gz |
tun_metadata: Fix coredump caused by use-after-free bug
Tun_metadata can be referened by flow and frozen_state at the same
time. When ovs-vswitchd handles TLV table mod message, the involved
tun_metadata gets freed. The call trace to free tun_metadata is
shown as below:
ofproto_run
- handle_openflow
- handle_single_part_openflow
- handle_tlv_table_mod
- tun_metadata_table_mod
- tun_metadata_postpone_free
Unfortunately, this tun_metadata can be still used by some frozen_state,
and later on when frozen_state tries to access its tun_metadata table,
ovs-vswitchd crashes. The call trace to access tun_metadata from
frozen_state is shown as below:
udpif_upcall_handler
- recv_upcalls
- process_upcall
- frozen_metadata_to_flow
It is unsafe for frozen_state to reference tun_table because tun_table
is protected by RCU while the lifecycle of frozen_state can span several
RCU quiesce states. Current code violates OVS's RCU protection mechanism.
This patch fixes it by simply stopping frozen_state from referencing
tun_table. If frozen_state needs tun_table, the latest valid tun_table
can be found through ofproto_get_tun_tab() efficiently.
A previous commit seems fixing the samiliar issue:
254878c18874f6 (ofproto-dpif-xlate: Fix segmentation fault caused by tun_table)
VMware-BZ: #2526222
Signed-off-by: Yifeng Sun <pkusunyifeng@gmail.com>
Signed-off-by: William Tu <u9012063@gmail.com>
Diffstat (limited to 'ofproto/ofproto-dpif-rid.h')
-rw-r--r-- | ofproto/ofproto-dpif-rid.h | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h index e5d02caf2..30cd5275f 100644 --- a/ofproto/ofproto-dpif-rid.h +++ b/ofproto/ofproto-dpif-rid.h @@ -22,6 +22,7 @@ #include "cmap.h" #include "ofproto-dpif-mirror.h" +#include "ofproto/ofproto-provider.h" #include "openvswitch/list.h" #include "openvswitch/ofp-actions.h" #include "ovs-thread.h" @@ -115,16 +116,25 @@ frozen_metadata_from_flow(struct frozen_metadata *md, { memset(md, 0, sizeof *md); md->tunnel = flow->tunnel; + /* It is unsafe for frozen_state to reference tun_table because + * tun_table is protected by RCU while the lifecycle of frozen_state + * can span several RCU quiesce states. + * + * The latest valid tun_table can be found by ofproto_get_tun_tab() + * efficiently. */ + md->tunnel.metadata.tab = NULL; md->metadata = flow->metadata; memcpy(md->regs, flow->regs, sizeof md->regs); md->in_port = flow->in_port.ofp_port; } static inline void -frozen_metadata_to_flow(const struct frozen_metadata *md, +frozen_metadata_to_flow(struct ofproto *ofproto, + const struct frozen_metadata *md, struct flow *flow) { flow->tunnel = md->tunnel; + flow->tunnel.metadata.tab = ofproto_get_tun_tab(ofproto); flow->metadata = md->metadata; memcpy(flow->regs, md->regs, sizeof flow->regs); flow->in_port.ofp_port = md->in_port; |