fix: avoid panic on malformed short tunnel packets (#1904)

This commit is contained in:
fanyang
2026-02-18 00:04:30 +08:00
committed by GitHub
parent aa24d09aa2
commit f737708f45
2 changed files with 85 additions and 44 deletions
+15 -2
View File
@@ -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 crate::tunnel::{SinkError, SinkItem, StreamItem};
use futures::{Sink, Stream}; use futures::{Sink, Stream};
use std::task::{Context as TaskContext, Poll}; use std::task::{Context as TaskContext, Poll};
@@ -407,7 +409,18 @@ impl Stream for FakeTcpStream {
let packet = ZCPacket::new_from_buf(buf, ZCPacketType::TCP); let packet = ZCPacket::new_from_buf(buf, ZCPacketType::TCP);
if let Some(tcp_hdr) = packet.tcp_tunnel_header() { if let Some(tcp_hdr) = packet.tcp_tunnel_header() {
let expected_payload_len = tcp_hdr.len.get() as usize; 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 mut buf = packet.inner();
let new_inner = buf.split_to(expected_payload_len); let new_inner = buf.split_to(expected_payload_len);
s.state = FakeTcpStreamState::ConsumingBuf(buf); s.state = FakeTcpStreamState::ConsumingBuf(buf);
+70 -42
View File
@@ -437,6 +437,14 @@ pub struct ZCPacket {
} }
impl 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 { pub fn new_nic_packet() -> Self {
Self { Self {
inner: BytesMut::new(), inner: BytesMut::new(),
@@ -517,39 +525,39 @@ impl ZCPacket {
} }
pub fn mut_peer_manager_header(&mut self) -> Option<&mut PeerManagerHeader> { pub fn mut_peer_manager_header(&mut self) -> Option<&mut PeerManagerHeader> {
PeerManagerHeader::mut_from_prefix( let offset = self
&mut self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .peer_manager_header_offset;
.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> { pub fn mut_tcp_tunnel_header(&mut self) -> Option<&mut TCPTunnelHeader> {
TCPTunnelHeader::mut_from_prefix( let offset = self
&mut self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .tcp_tunnel_header_offset;
.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> { pub fn mut_udp_tunnel_header(&mut self) -> Option<&mut UDPTunnelHeader> {
UDPTunnelHeader::mut_from_prefix( let offset = self
&mut self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .udp_tunnel_header_offset;
.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> { pub fn mut_wg_tunnel_header(&mut self) -> Option<&mut WGTunnelHeader> {
WGTunnelHeader::mut_from_prefix( let offset = self
&mut self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .wg_tunnel_header_offset;
.wg_tunnel_header_offset..], let bytes = self.mut_bytes_from_offset(offset)?;
) WGTunnelHeader::mut_from_prefix(bytes)
} }
// ref versions // ref versions
@@ -562,30 +570,30 @@ impl ZCPacket {
} }
pub fn peer_manager_header(&self) -> Option<&PeerManagerHeader> { pub fn peer_manager_header(&self) -> Option<&PeerManagerHeader> {
PeerManagerHeader::ref_from_prefix( let offset = self
&self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .peer_manager_header_offset;
.peer_manager_header_offset..], let bytes = self.bytes_from_offset(offset)?;
) PeerManagerHeader::ref_from_prefix(bytes)
} }
pub fn tcp_tunnel_header(&self) -> Option<&TCPTunnelHeader> { pub fn tcp_tunnel_header(&self) -> Option<&TCPTunnelHeader> {
TCPTunnelHeader::ref_from_prefix( let offset = self
&self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .tcp_tunnel_header_offset;
.tcp_tunnel_header_offset..], let bytes = self.bytes_from_offset(offset)?;
) TCPTunnelHeader::ref_from_prefix(bytes)
} }
pub fn udp_tunnel_header(&self) -> Option<&UDPTunnelHeader> { pub fn udp_tunnel_header(&self) -> Option<&UDPTunnelHeader> {
UDPTunnelHeader::ref_from_prefix( let offset = self
&self.inner[self .packet_type
.packet_type .get_packet_offsets()
.get_packet_offsets() .udp_tunnel_header_offset;
.udp_tunnel_header_offset..], let bytes = self.bytes_from_offset(offset)?;
) UDPTunnelHeader::ref_from_prefix(bytes)
} }
pub fn udp_payload(&self) -> &[u8] { pub fn udp_payload(&self) -> &[u8] {
@@ -751,4 +759,24 @@ mod tests {
assert_eq!(&tcp_packet[..1], b"\x0b"); assert_eq!(&tcp_packet[..1], b"\x0b");
println!("{:?}", tcp_packet); 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());
}
} }