* [PATCH] net: fix GTP Tunnel parse out-of-bounds read
@ 2026-04-09 16:15 Stephen Hemminger
2026-06-01 12:59 ` Thomas Monjalon
2026-06-01 16:17 ` [PATCH v2] " Stephen Hemminger
0 siblings, 2 replies; 4+ messages in thread
From: Stephen Hemminger @ 2026-04-09 16:15 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Jie Hai
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@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
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;
+ uint8_t l3_copy, ip_ver;
+
+ l3_hdr = rte_pktmbuf_read(m, *off, sizeof(*l3_hdr), &l3_copy);
+ 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)
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] net: fix GTP Tunnel parse out-of-bounds read
2026-04-09 16:15 [PATCH] net: fix GTP Tunnel parse out-of-bounds read Stephen Hemminger
@ 2026-06-01 12:59 ` Thomas Monjalon
2026-06-01 14:27 ` Andrew Rybchenko
2026-06-01 16:17 ` [PATCH v2] " Stephen Hemminger
1 sibling, 1 reply; 4+ messages in thread
From: Thomas Monjalon @ 2026-06-01 12:59 UTC (permalink / raw)
To: dev, Andrew Rybchenko, Bruce Richardson, Jerin Jacob,
Hemant Agrawal
Cc: Stephen Hemminger, stable, Jie Hai
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@dpdk.org
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> 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;
> + uint8_t l3_copy, ip_ver;
> +
> + l3_hdr = rte_pktmbuf_read(m, *off, sizeof(*l3_hdr), &l3_copy);
> + 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)
>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] net: fix GTP Tunnel parse out-of-bounds read
2026-06-01 12:59 ` Thomas Monjalon
@ 2026-06-01 14:27 ` Andrew Rybchenko
0 siblings, 0 replies; 4+ messages in thread
From: Andrew Rybchenko @ 2026-06-01 14:27 UTC (permalink / raw)
To: Thomas Monjalon, dev, Bruce Richardson, Jerin Jacob,
Hemant Agrawal
Cc: Stephen Hemminger, stable, Jie Hai
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@dpdk.org
>>
>> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
The overall idea LGTM. However one nit in the code.
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@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)
>>
>
>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] net: fix GTP Tunnel parse out-of-bounds read
2026-04-09 16:15 [PATCH] net: fix GTP Tunnel parse out-of-bounds read Stephen Hemminger
2026-06-01 12:59 ` Thomas Monjalon
@ 2026-06-01 16:17 ` Stephen Hemminger
1 sibling, 0 replies; 4+ messages in thread
From: Stephen Hemminger @ 2026-06-01 16:17 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Andrew Rybchenko, Jie Hai
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@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
---
v2 - change variable name of l3 header byte
lib/net/rte_net.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index 458b4814a9..0a91e92ba0 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,17 @@ 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_byte;
+ uint8_t l3_copy, ip_ver;
+
+ /* read first byte of l3 header */
+ l3_byte = rte_pktmbuf_read(m, *off, sizeof(uint8_t), &l3_copy);
+ if (unlikely(l3_byte == NULL))
+ return 0;
+
+ ip_ver = *l3_byte & 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 +250,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)
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-01 16:17 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-09 16:15 [PATCH] net: fix GTP Tunnel parse out-of-bounds read Stephen Hemminger
2026-06-01 12:59 ` Thomas Monjalon
2026-06-01 14:27 ` Andrew Rybchenko
2026-06-01 16:17 ` [PATCH v2] " Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox