From: Zhiling Zou nf_nat_h323's set_addr() chooses the TCP or UDP NAT mangler from the packet's current IPv4 protocol byte. H.323 conntrack helpers run later from the conntrack helper path, so a packet can be accepted and assigned to a UDP RAS or TCP signaling helper before another hook rewrites the IP protocol byte. When the current IP protocol no longer matches the helper's transport, the parser and NAT mangler use different transport-header bases. In the RAS case, ras_help() parses addresses relative to the UDP payload, while set_addr() can call the TCP mangler and use a forged TCP data offset. That can make the NAT match offset extend past the skb tail. Select the mangler from nf_ct_protonum(ct), the stable L4 protocol stored in the conntrack tuple, instead of the live IP header. H.245 parsing is TPKT/TCP based even though the registered H.245 helper can be bound to a UDP conntrack from userspace; ignore those non-TCP bindings before the TCP parser feeds offsets to NAT. Fixes: 5e35941d9901 ("[NETFILTER]: Add H.323 conntrack/NAT helper") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: Codex:gpt-5.4 Signed-off-by: Zhiling Zou Signed-off-by: Ren Wei --- net/ipv4/netfilter/nf_nat_h323.c | 9 +++++++-- net/netfilter/nf_conntrack_h323_main.c | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index 183e8a3ff2bab..98d50b3a6be2c 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c @@ -37,7 +37,8 @@ static int set_addr(struct sk_buff *skb, unsigned int protoff, buf.port = port; addroff += dataoff; - if (ip_hdr(skb)->protocol == IPPROTO_TCP) { + switch (nf_ct_protonum(ct)) { + case IPPROTO_TCP: if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, addroff, sizeof(buf), (char *) &buf, sizeof(buf))) { @@ -51,7 +52,8 @@ static int set_addr(struct sk_buff *skb, unsigned int protoff, if (th == NULL) return -1; *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; - } else { + break; + case IPPROTO_UDP: if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff, addroff, sizeof(buf), (char *) &buf, sizeof(buf))) { @@ -62,6 +64,9 @@ static int set_addr(struct sk_buff *skb, unsigned int protoff, * or pull everything in a linear buffer, so we can safely * use the skb pointers now */ *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); + break; + default: + return -1; } return 0; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 24931e379985b..9cac3e5ab39ef 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -539,6 +539,10 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) return NF_ACCEPT; + /* H.245 is TPKT/TCP; ignore manual bindings to other L4 protocols. */ + if (nf_ct_protonum(ct) != IPPROTO_TCP) + return NF_ACCEPT; + pr_debug("nf_ct_h245: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); -- 2.43.0