From 3b75af34e82b6a968e899fcb1e11bef7e1bb286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Fri, 16 Jan 2026 08:58:20 +0000 Subject: [PATCH] ensure packets with incompatible versions are rejected (#6326) --- common/nym-lp/src/codec.rs | 46 ++++++++++---------- common/nym-lp/src/error.rs | 8 ++++ common/nym-lp/src/lib.rs | 12 ++--- common/nym-lp/src/message.rs | 2 +- common/nym-lp/src/packet.rs | 39 ++++++++++++++--- common/nym-lp/src/session_integration/mod.rs | 2 +- gateway/src/node/lp_listener/handler.rs | 14 +++--- 7 files changed, 79 insertions(+), 44 deletions(-) diff --git a/common/nym-lp/src/codec.rs b/common/nym-lp/src/codec.rs index 1a6b0e05ad..8d6e0ccdd9 100644 --- a/common/nym-lp/src/codec.rs +++ b/common/nym-lp/src/codec.rs @@ -164,7 +164,7 @@ pub fn parse_lp_packet(src: &[u8], outer_key: Option<&OuterAeadKey>) -> Result) -> Result Self { Self { - protocol_version: 1, - reserved: 0, + protocol_version: version::CURRENT, + reserved: [0u8; 3], receiver_idx, counter, } @@ -211,7 +217,7 @@ impl LpHeader { dst.put_u8(self.protocol_version); // reserved - dst.put_slice(&[0, 0, 0]); + dst.put_slice(&self.reserved); // sender index dst.put_slice(&self.receiver_idx.to_le_bytes()); @@ -226,7 +232,28 @@ impl LpHeader { } let protocol_version = src[0]; - // Skip reserved bytes [1..4] + + // Ensure we are using compatible protocol + // right now only support a single version + if protocol_version > version::CURRENT { + return Err(LpError::IncompatibleFuturePacketVersion { + got: protocol_version, + highest_supported: version::CURRENT, + }); + } + + if protocol_version < version::CURRENT { + return Err(LpError::IncompatibleLegacyPacketVersion { + got: protocol_version, + lowest_supported: version::CURRENT, + }); + } + + // skip reserved bytes, but log if they're different from the expected zeroes + let reserved = [src[1], src[2], src[3]]; + if reserved != [0u8; 3] { + warn!("received non-zero reserved bytes. got: {reserved:?}"); + } let mut receiver_idx_bytes = [0u8; 4]; receiver_idx_bytes.copy_from_slice(&src[4..8]); @@ -238,7 +265,7 @@ impl LpHeader { Ok(LpHeader { protocol_version, - reserved: 0, + reserved: [0u8; 3], receiver_idx, counter, }) diff --git a/common/nym-lp/src/session_integration/mod.rs b/common/nym-lp/src/session_integration/mod.rs index ceafc3f81f..a3b58f2575 100644 --- a/common/nym-lp/src/session_integration/mod.rs +++ b/common/nym-lp/src/session_integration/mod.rs @@ -21,7 +21,7 @@ mod tests { // Create the header let header = LpHeader { protocol_version, - reserved: 0u16, // reserved + reserved: [0u8; 3], // reserved receiver_idx, counter, }; diff --git a/gateway/src/node/lp_listener/handler.rs b/gateway/src/node/lp_listener/handler.rs index d30eb3600e..7960d4f026 100644 --- a/gateway/src/node/lp_listener/handler.rs +++ b/gateway/src/node/lp_listener/handler.rs @@ -1520,7 +1520,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 42, counter: 0, }, @@ -1586,7 +1586,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 99, counter: 5, }, @@ -1626,7 +1626,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 100, counter: 10, }, @@ -1667,7 +1667,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 200, counter: 20, }, @@ -1719,7 +1719,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 300, counter: 30, }, @@ -1784,7 +1784,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 0, counter: 0, }, @@ -1854,7 +1854,7 @@ mod tests { let packet = LpPacket::new( LpHeader { protocol_version: 1, - reserved: 0, + reserved: [0u8; 3], receiver_idx: 0, counter: 0, },