[PATCH] net: fix GTP Tunnel parse out-of-bounds read

Andrew Rybchenko andrew.rybchenko at oktetlabs.ru
Mon Jun 1 16:27:13 CEST 2026


On 6/1/26 3:59 PM, Thomas Monjalon wrote:
> Any comment about this fix?
> 
> 
> 09/04/2026 18:15, Stephen Hemminger:
>> If packet is fragmented across multiple mbufs or the packet
>> has only GTP header the code would reference outside
>> the incoming mbuf.
>>
>> Send GTP packet:
>> - Valid GTP header (8 bytes)
>> - msg_type = 0xff
>> - e=1, s=1, pn=1 (sets gtp_len = 12)
>> - Total packet size = 10 bytes
>>
>> Read at gh + 12 accesses 2 bytes beyond packet end.
>>
>> The fix is to use rte_pktmbuf_read in a manner similar
>> to the read of the GTP header.
>>
>> Fixes: 64ed7f854cf4 ("net: add tunnel packet type parsing")
>> Cc: stable at dpdk.org
>>
>> Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>

The overall idea LGTM. However one nit in the code.

Reviewed-by: Andrew Rybchenko <andrew.rybchenko at oktetlabs.ru>

>> ---
>>   lib/net/rte_net.c | 15 ++++++++++-----
>>   1 file changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
>> index 458b4814a9..da4018437b 100644
>> --- a/lib/net/rte_net.c
>> +++ b/lib/net/rte_net.c
>> @@ -219,8 +219,7 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m,
>>   	case RTE_GTPU_UDP_PORT: {
>>   		const struct rte_gtp_hdr *gh;
>>   		struct rte_gtp_hdr gh_copy;
>> -		uint8_t gtp_len;
>> -		uint8_t ip_ver;
>> +		uint32_t gtp_len;
>>   		gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
>>   		if (unlikely(gh == NULL))
>>   			return 0;
>> @@ -231,9 +230,16 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m,
>>   		 * Check message type. If message type is 0xff, it is
>>   		 * a GTP data packet. If not, it is a GTP control packet
>>   		 */
>> +		*off += gtp_len;
>>   		if (gh->msg_type == 0xff) {
>> -			ip_ver = *(const uint8_t *)((const char *)gh + gtp_len);
>> -			ip_ver = (ip_ver) & 0xf0;
>> +			const uint8_t *l3_hdr;

l3_hdr is confusing here. It sounds like a complete layer 3 header, but
it is just one first byte. May be it would be useful to highlight that
it is an inner Layer 3 header.

E.g. inner_l3_hdr_byte (I'm not fully happy with the name too, but
I hope idea is clear)

>> +			uint8_t l3_copy, ip_ver;
>> +
>> +			l3_hdr = rte_pktmbuf_read(m, *off, sizeof(*l3_hdr), &l3_copy);

sizeof(l3_copy) would be safer here.

>> +			if (unlikely(l3_hdr == NULL))
>> +				return 0;
>> +
>> +			ip_ver = *l3_hdr & 0xf0;
>>   			if (ip_ver == RTE_GTP_TYPE_IPV4)
>>   				*proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
>>   			else if (ip_ver == RTE_GTP_TYPE_IPV6)
>> @@ -243,7 +249,6 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m,
>>   		} else {
>>   			*proto = 0;
>>   		}
>> -		*off += gtp_len;
>>   		hdr_lens->inner_l2_len = gtp_len + sizeof(struct rte_udp_hdr);
>>   		hdr_lens->tunnel_len = gtp_len;
>>   		if (port_no == RTE_GTPC_UDP_PORT)
>>
> 
> 
> 
> 
> 



More information about the dev mailing list