From ad51075029c59dc4100c1a416bed17870b9be1b7 Mon Sep 17 00:00:00 2001 From: Matthew Smith Date: Tue, 10 Aug 2021 12:22:14 -0500 Subject: nat: handle ED in2out ICMP errors with workers Type: fix With endpoint dependent NAT44, When there are multiple workers we look for a flow which matches the packet in order to figure out which worker should handle the packet. If the packet is an ICMP error, it may be associated with an existing flow by inspecting the L3/L4 headers that are included in the message payload. This was not being done for in2out packets in nat44_ed_get_in2out_worker_index(), so some packets which were related to an open session were not being associated with that session and were being passed to a different thread than the one where the session was created. Later on, when the packet was processed by the fast path in2out node, the L3/L4 headers in the payload are inspected and the fast path node finds the existing session. Since that session is owned by a different thread than the one the packet is being processed by, the in2out fast path node can potentially access the wrong session and/or memory adjacent to the session pool. This can cause a SEGV. Make nat44_ed_get_in2out_worker_index() look at the inner headers when processing an ICMP error. THis is already done in nat44_ed_get_out2in_worker_index() and in the fast path in2out node. Change-Id: Icdc1abebcbce452ee7be7cb23fc563e09bf575f2 Signed-off-by: Matthew Smith --- src/plugins/nat/nat44-ed/nat44_ed.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src') diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index ad78dc2dd1f..b9dbe6ebeca 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -2854,6 +2854,28 @@ nat44_ed_get_in2out_worker_index (vlib_buffer_t *b, ip4_header_t *ip, } } + if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP)) + { + ip4_address_t lookup_saddr, lookup_daddr; + u16 lookup_sport, lookup_dport; + u8 lookup_protocol; + + if (!nat_get_icmp_session_lookup_values ( + b, ip, &lookup_saddr, &lookup_sport, &lookup_daddr, + &lookup_dport, &lookup_protocol)) + { + init_ed_k (&kv16, lookup_saddr, lookup_sport, lookup_daddr, + lookup_dport, rx_fib_index, lookup_protocol); + if (!clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)) + { + next_worker_index = ed_value_get_thread_index (&value16); + vnet_buffer2 (b)->nat.cached_session_index = + ed_value_get_session_index (&value16); + goto out; + } + } + } + init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, fib_index, ip->protocol); -- cgit 1.2.3-korg