From b2289d0b8cc6dfe09ab0e2089d479aa8e468c4eb Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 18 Jul 2024 10:23:49 +0200 Subject: [PATCH 1/3] Close TCP sockets if src ip no longer matches the interface IP address --- src/iface/interface/mod.rs | 18 ++++++++++++++++-- src/socket/tcp.rs | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index 7d6bdc820..235d9dcc4 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -599,6 +599,7 @@ impl Interface { enum EgressError { Exhausted, + MismatchingSrcIp, Dispatch(DispatchError), } @@ -614,6 +615,12 @@ impl Interface { let mut neighbor_addr = None; let mut respond = |inner: &mut InterfaceInner, meta: PacketMeta, response: Packet| { neighbor_addr = Some(response.ip_repr().dst_addr()); + + if !inner.has_ip_addr(response.ip_repr().src_addr()) { + net_debug!("failed to transmit IP: mismatched src addr"); + return Err(EgressError::MismatchingSrcIp); + } + let t = device.transmit(inner.now).ok_or_else(|| { net_debug!("failed to transmit IP: device exhausted"); EgressError::Exhausted @@ -663,13 +670,19 @@ impl Interface { }) } #[cfg(feature = "socket-tcp")] - Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| { + Socket::Tcp(socket) => match socket.dispatch(&mut self.inner, |inner, (ip, tcp)| { respond( inner, PacketMeta::default(), Packet::new(ip, IpPayload::Tcp(tcp)), ) - }), + }) { + Err(EgressError::MismatchingSrcIp) => { + socket.set_state(tcp::State::Closed); + Err(EgressError::MismatchingSrcIp) + } + r => r, + }, #[cfg(feature = "socket-dhcpv4")] Socket::Dhcpv4(socket) => { socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| { @@ -702,6 +715,7 @@ impl Interface { neighbor_addr.expect("non-IP response packet"), ); } + Err(EgressError::MismatchingSrcIp) => {} Ok(()) => {} } } diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index d7b85ab42..cf6f42da4 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -1204,7 +1204,7 @@ impl<'a> Socket<'a> { self.rx_buffer.len() } - fn set_state(&mut self, state: State) { + pub fn set_state(&mut self, state: State) { if self.state != state { tcp_trace!("state={}=>{}", self.state, state); } From 1bdf544377e831e1f15dbe3882a89ea1dd9486a1 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Aug 2024 10:03:17 +0200 Subject: [PATCH 2/3] Use socket.close instead of making set_state public --- src/iface/interface/mod.rs | 2 +- src/socket/tcp.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index f74dea29d..60ccc7de5 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -653,7 +653,7 @@ impl Interface { ) }) { Err(EgressError::MismatchingSrcIp) => { - socket.set_state(tcp::State::Closed); + socket.close(); Err(EgressError::MismatchingSrcIp) } r => r, diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 2b5e84269..946d6de88 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -1307,7 +1307,7 @@ impl<'a> Socket<'a> { self.rx_buffer.len() } - pub fn set_state(&mut self, state: State) { + fn set_state(&mut self, state: State) { if self.state != state { tcp_trace!("state={}=>{}", self.state, state); } From 8d6bdde7b87430ed17b7a798308fdee79b9aec29 Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Aug 2024 10:35:17 +0200 Subject: [PATCH 3/3] Completely reset the socket on MismatchedSrcIp --- src/iface/interface/mod.rs | 13 +++++++------ src/socket/tcp.rs | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/iface/interface/mod.rs b/src/iface/interface/mod.rs index 60ccc7de5..a2844b4cc 100644 --- a/src/iface/interface/mod.rs +++ b/src/iface/interface/mod.rs @@ -574,7 +574,7 @@ impl Interface { enum EgressError { Exhausted, - MismatchingSrcIp, + MismatchedSrcIp, Dispatch, } @@ -593,7 +593,7 @@ impl Interface { if !inner.has_ip_addr(response.ip_repr().src_addr()) { net_debug!("failed to transmit IP: mismatched src addr"); - return Err(EgressError::MismatchingSrcIp); + return Err(EgressError::MismatchedSrcIp); } let t = device.transmit(inner.now).ok_or_else(|| { @@ -652,9 +652,10 @@ impl Interface { Packet::new(ip, IpPayload::Tcp(tcp)), ) }) { - Err(EgressError::MismatchingSrcIp) => { - socket.close(); - Err(EgressError::MismatchingSrcIp) + Err(EgressError::MismatchedSrcIp) => { + // FIXME: Should this be `close()` or `abort()`? + socket.reset(); + Err(EgressError::MismatchedSrcIp) } r => r, }, @@ -690,7 +691,7 @@ impl Interface { neighbor_addr.expect("non-IP response packet"), ); } - Err(EgressError::MismatchingSrcIp) => {} + Err(EgressError::MismatchedSrcIp) => {}, Ok(()) => {} } } diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index 946d6de88..d8259f906 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -812,7 +812,7 @@ impl<'a> Socket<'a> { self.state } - fn reset(&mut self) { + pub fn reset(&mut self) { let rx_cap_log2 = mem::size_of::() * 8 - self.rx_buffer.capacity().leading_zeros() as usize;