From f737708f45840a54d13d5a241980fca453a44b0c Mon Sep 17 00:00:00 2001 From: fanyang Date: Wed, 18 Feb 2026 00:04:30 +0800 Subject: [PATCH] fix: avoid panic on malformed short tunnel packets (#1904) --- easytier/src/tunnel/fake_tcp/mod.rs | 17 ++++- easytier/src/tunnel/packet_def.rs | 112 +++++++++++++++++----------- 2 files changed, 85 insertions(+), 44 deletions(-) diff --git a/easytier/src/tunnel/fake_tcp/mod.rs b/easytier/src/tunnel/fake_tcp/mod.rs index 7dc28fd9..8d606399 100644 --- a/easytier/src/tunnel/fake_tcp/mod.rs +++ b/easytier/src/tunnel/fake_tcp/mod.rs @@ -366,7 +366,9 @@ impl crate::tunnel::TunnelConnector for FakeTcpTunnelConnector { } } -use crate::tunnel::packet_def::{ZCPacket, ZCPacketType}; +use crate::tunnel::packet_def::{ + ZCPacket, ZCPacketType, PEER_MANAGER_HEADER_SIZE, TCP_TUNNEL_HEADER_SIZE, +}; use crate::tunnel::{SinkError, SinkItem, StreamItem}; use futures::{Sink, Stream}; use std::task::{Context as TaskContext, Poll}; @@ -407,7 +409,18 @@ impl Stream for FakeTcpStream { let packet = ZCPacket::new_from_buf(buf, ZCPacketType::TCP); if let Some(tcp_hdr) = packet.tcp_tunnel_header() { let expected_payload_len = tcp_hdr.len.get() as usize; - if expected_payload_len <= buf_len && expected_payload_len != 0 { + let min_packet_len = TCP_TUNNEL_HEADER_SIZE + PEER_MANAGER_HEADER_SIZE; + if expected_payload_len < min_packet_len { + tracing::warn!( + "drop fake tcp packet with invalid length: expected_payload_len={}, min_required={}", + expected_payload_len, + min_packet_len + ); + s.state = FakeTcpStreamState::Closed; + return Poll::Ready(None); + } + + if expected_payload_len <= buf_len { let mut buf = packet.inner(); let new_inner = buf.split_to(expected_payload_len); s.state = FakeTcpStreamState::ConsumingBuf(buf); diff --git a/easytier/src/tunnel/packet_def.rs b/easytier/src/tunnel/packet_def.rs index a59403d6..d5a464f1 100644 --- a/easytier/src/tunnel/packet_def.rs +++ b/easytier/src/tunnel/packet_def.rs @@ -437,6 +437,14 @@ pub struct ZCPacket { } impl ZCPacket { + fn bytes_from_offset(&self, offset: usize) -> Option<&[u8]> { + self.inner.get(offset..) + } + + fn mut_bytes_from_offset(&mut self, offset: usize) -> Option<&mut [u8]> { + self.inner.get_mut(offset..) + } + pub fn new_nic_packet() -> Self { Self { inner: BytesMut::new(), @@ -517,39 +525,39 @@ impl ZCPacket { } pub fn mut_peer_manager_header(&mut self) -> Option<&mut PeerManagerHeader> { - PeerManagerHeader::mut_from_prefix( - &mut self.inner[self - .packet_type - .get_packet_offsets() - .peer_manager_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .peer_manager_header_offset; + let bytes = self.mut_bytes_from_offset(offset)?; + PeerManagerHeader::mut_from_prefix(bytes) } pub fn mut_tcp_tunnel_header(&mut self) -> Option<&mut TCPTunnelHeader> { - TCPTunnelHeader::mut_from_prefix( - &mut self.inner[self - .packet_type - .get_packet_offsets() - .tcp_tunnel_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .tcp_tunnel_header_offset; + let bytes = self.mut_bytes_from_offset(offset)?; + TCPTunnelHeader::mut_from_prefix(bytes) } pub fn mut_udp_tunnel_header(&mut self) -> Option<&mut UDPTunnelHeader> { - UDPTunnelHeader::mut_from_prefix( - &mut self.inner[self - .packet_type - .get_packet_offsets() - .udp_tunnel_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .udp_tunnel_header_offset; + let bytes = self.mut_bytes_from_offset(offset)?; + UDPTunnelHeader::mut_from_prefix(bytes) } pub fn mut_wg_tunnel_header(&mut self) -> Option<&mut WGTunnelHeader> { - WGTunnelHeader::mut_from_prefix( - &mut self.inner[self - .packet_type - .get_packet_offsets() - .wg_tunnel_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .wg_tunnel_header_offset; + let bytes = self.mut_bytes_from_offset(offset)?; + WGTunnelHeader::mut_from_prefix(bytes) } // ref versions @@ -562,30 +570,30 @@ impl ZCPacket { } pub fn peer_manager_header(&self) -> Option<&PeerManagerHeader> { - PeerManagerHeader::ref_from_prefix( - &self.inner[self - .packet_type - .get_packet_offsets() - .peer_manager_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .peer_manager_header_offset; + let bytes = self.bytes_from_offset(offset)?; + PeerManagerHeader::ref_from_prefix(bytes) } pub fn tcp_tunnel_header(&self) -> Option<&TCPTunnelHeader> { - TCPTunnelHeader::ref_from_prefix( - &self.inner[self - .packet_type - .get_packet_offsets() - .tcp_tunnel_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .tcp_tunnel_header_offset; + let bytes = self.bytes_from_offset(offset)?; + TCPTunnelHeader::ref_from_prefix(bytes) } pub fn udp_tunnel_header(&self) -> Option<&UDPTunnelHeader> { - UDPTunnelHeader::ref_from_prefix( - &self.inner[self - .packet_type - .get_packet_offsets() - .udp_tunnel_header_offset..], - ) + let offset = self + .packet_type + .get_packet_offsets() + .udp_tunnel_header_offset; + let bytes = self.bytes_from_offset(offset)?; + UDPTunnelHeader::ref_from_prefix(bytes) } pub fn udp_payload(&self) -> &[u8] { @@ -751,4 +759,24 @@ mod tests { assert_eq!(&tcp_packet[..1], b"\x0b"); println!("{:?}", tcp_packet); } + + #[test] + fn test_short_tcp_packet_header_access_is_safe() { + let mut packet = ZCPacket::new_from_buf(BytesMut::from(&b"\x01"[..]), ZCPacketType::TCP); + + assert!(packet.peer_manager_header().is_none()); + assert!(packet.tcp_tunnel_header().is_none()); + assert!(packet.udp_tunnel_header().is_none()); + assert!(packet.mut_peer_manager_header().is_none()); + assert!(packet.mut_tcp_tunnel_header().is_none()); + assert!(packet.mut_udp_tunnel_header().is_none()); + assert!(packet.mut_wg_tunnel_header().is_none()); + } + + #[test] + fn test_invalid_converted_header_offset_is_safe() { + let mut packet = ZCPacket::new_from_buf(BytesMut::from(&b"\x01"[..]), ZCPacketType::UDP); + + assert!(packet.mut_wg_tunnel_header().is_none()); + } }