* [PATCH net 1/2] netfilter: nf_conntrack_h323: do not bypass NAT helpers when tuple source matches reply destination
2026-09-23 4:20 [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode Subham Pal
@ 2026-09-23 4:23 ` Subham Pal
2026-09-23 4:25 ` [PATCH net 2/2] netfilter: nf_conntrack_h323: check extension bitmap before decoding components Subham Pal
2026-09-23 8:46 ` [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode Pablo Neira Ayuso
2 siblings, 0 replies; 10+ messages in thread
From: Subham Pal @ 2026-09-23 4:23 UTC (permalink / raw)
To: pablo, fw
Cc: phil, kaber, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, netdev, stable
[-- Attachment #1: Type: text/plain, Size: 1389 bytes --]
The expectation helpers (expect_h245, expect_rtp_rtcp, expect_t120, and
expect_callforwarding) test whether NAT is required by comparing the
forward source IP against the reverse destination IP:
memcmp(&ct->tuplehash[dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
sizeof(ct->tuplehash[dir].tuple.src.u3))
This check is broken for multiple reasons:
1. It incorrectly evaluates to 0 in the reply direction
(dir == IP_CT_DIR_REPLY) even under SNAT, because tuplehash[REPLY].src
and tuplehash[ORIGINAL].dst both represent the remote peer's address.
2. In Destination NAT (DNAT) and hairpin setups, the sender's source IP
is never modified, causing this check to evaluate to false even though
NAT payload rewriting is necessary.
As a result, NAT payload mangling is bypassed, leaving internal addresses
untranslated inside the signaling packets and leading to call setup and
media stream failures.
Remove the redundant memcmp() checks across all four expectation helpers.
Verifying that nathook is present and that ct->status matches IPS_NAT_MASK
is sufficient to determine whether NAT handling should execute.
Fixes: f587de0e2feb ("[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port")
Cc: stable@vger.kernel.org
Signed-off-by: Subham Pal <subhampal789@gmail.com>
---
[Note: Raw patch attached to avoid webmail tab/whitespace corruption]
[-- Attachment #2: 0001-netfilter-nf_conntrack_h323-do-not-bypass-NAT-helper.patch --]
[-- Type: text/x-patch, Size: 3991 bytes --]
From eb78748cc3cb6032566a649ceeadf99c788f4573 Mon Sep 17 00:00:00 2001
From: Subham Pal <subhampal789@gmail.com>
Date: Tue, 22 Sep 2026 16:19:05 +0530
Subject: [PATCH net 1/2] netfilter: nf_conntrack_h323: do not bypass NAT
helpers when tuple source matches reply destination
The expectation helpers (expect_h245, expect_rtp_rtcp, expect_t120, and
expect_callforwarding) test whether NAT is required by comparing the
forward source IP against the reverse destination IP:
memcmp(&ct->tuplehash[dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
sizeof(ct->tuplehash[dir].tuple.src.u3))
This check is broken for multiple reasons:
1. It incorrectly evaluates to 0 in the reply direction
(dir == IP_CT_DIR_REPLY) even under SNAT, because tuplehash[REPLY].src
and tuplehash[ORIGINAL].dst both represent the remote peer's address.
2. In Destination NAT (DNAT) and hairpin setups, the sender's source IP
is never modified, causing this check to evaluate to false even though
NAT payload rewriting is necessary.
As a result, NAT payload mangling is bypassed, leaving internal addresses
untranslated inside the signaling packets and leading to call setup and
media stream failures.
Remove the redundant memcmp() checks across all four expectation helpers.
Verifying that nathook is present and that ct->status matches IPS_NAT_MASK
is sufficient to determine whether NAT handling should execute.
Fixes: f587de0e2feb ("[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port")
Cc: stable@vger.kernel.org
Signed-off-by: Subham Pal <subhampal789@gmail.com>
---
net/netfilter/nf_conntrack_h323_main.c | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 4cb1665bba02..0c2aa608ae60 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -250,12 +250,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
IPPROTO_UDP, NULL, &rtcp_port);
nathook = rcu_dereference(nfct_h323_nat_hook);
- if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
- nathook &&
- nf_ct_l3num(ct) == NFPROTO_IPV4 &&
- ct->status & IPS_NAT_MASK) {
+ if (nathook &&
+ nf_ct_l3num(ct) == NFPROTO_IPV4 &&
+ ct->status & IPS_NAT_MASK) {
/* NAT needed */
ret = nathook->nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
taddr, port, rtp_port, rtp_exp, rtcp_exp);
@@ -310,10 +307,7 @@ static int expect_t120(struct sk_buff *skb,
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */
nathook = rcu_dereference(nfct_h323_nat_hook);
- if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
- nathook &&
+ if (nathook &&
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
ct->status & IPS_NAT_MASK) {
/* NAT needed */
@@ -643,10 +637,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_h245_ptr);
nathook = rcu_dereference(nfct_h323_nat_hook);
- if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
- nathook &&
+ if (nathook &&
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
ct->status & IPS_NAT_MASK) {
/* NAT needed */
@@ -770,10 +761,7 @@ static int expect_callforwarding(struct sk_buff *skb,
rcu_assign_pointer(exp->assign_helper, nf_conntrack_helper_q931_ptr[0]);
nathook = rcu_dereference(nfct_h323_nat_hook);
- if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
- nathook &&
+ if (nathook &&
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
ct->status & IPS_NAT_MASK) {
/* Need NAT */
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH net 2/2] netfilter: nf_conntrack_h323: check extension bitmap before decoding components
2026-09-23 4:20 [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode Subham Pal
2026-09-23 4:23 ` [PATCH net 1/2] netfilter: nf_conntrack_h323: do not bypass NAT helpers when tuple source matches reply destination Subham Pal
@ 2026-09-23 4:25 ` Subham Pal
2026-09-23 8:46 ` [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode Pablo Neira Ayuso
2 siblings, 0 replies; 10+ messages in thread
From: Subham Pal @ 2026-09-23 4:25 UTC (permalink / raw)
To: pablo, fw
Cc: phil, kaber, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, netdev, stable
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
In decode_seq(), the extension components loop iterates through bmp2_len
bits. However, it evaluates whether the component index exceeds the known
upper bound (`i >= f->ub`) and whether it contains a STOP attribute before
checking if the field is actually present in `bmp2`:
if (i >= f->ub) {
...
len = get_len(bs);
...
}
if (son->attr & STOP)
return H323_ERROR_STOP;
if (!((0x80000000 >> opt) & bmp2))
continue;
If an unknown extension is marked absent in the bitmap (`bit == 0`), the
parser erroneously attempts to read a non-existent open type length from
the bitstream and advances `bs->cur` by garbage bytes. Furthermore, if a
known field has the STOP attribute but is absent from the transmission,
decoding aborts prematurely.
Move the presence bitmap check to the beginning of the loop body so absent
extensions are skipped immediately before attempting to decode or inspect
attributes. Also append a 'U' suffix to 0x80000000 to prevent signed shift
overflow.
Fixes: f587de0e2feb ("[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port")
Cc: stable@vger.kernel.org
Signed-off-by: Subham Pal <subhampal789@gmail.com>
---
[Note: Raw patch attached to avoid webmail tab/whitespace corruption]
[-- Attachment #2: 0002-netfilter-nf_conntrack_h323-check-extension-bitmap-b.patch --]
[-- Type: text/x-patch, Size: 2428 bytes --]
From 46835631e6949ed936a44cd8e4648b1adf7304ec Mon Sep 17 00:00:00 2001
From: Subham Pal <subhampal789@gmail.com>
Date: Tue, 22 Sep 2026 16:35:08 +0530
Subject: [PATCH net 2/2] netfilter: nf_conntrack_h323: check extension bitmap
before decoding components
In decode_seq(), the extension components loop iterates through bmp2_len
bits. However, it evaluates whether the component index exceeds the known
upper bound (`i >= f->ub`) and whether it contains a STOP attribute before
checking if the field is actually present in `bmp2`:
if (i >= f->ub) {
...
len = get_len(bs);
...
}
if (son->attr & STOP)
return H323_ERROR_STOP;
if (!((0x80000000 >> opt) & bmp2))
continue;
If an unknown extension is marked absent in the bitmap (`bit == 0`), the
parser erroneously attempts to read a non-existent open type length from
the bitstream and advances `bs->cur` by garbage bytes. Furthermore, if a
known field has the STOP attribute but is absent from the transmission,
decoding aborts prematurely.
Move the presence bitmap check to the beginning of the loop body so absent
extensions are skipped immediately before attempting to decode or inspect
attributes. Also append a 'U' suffix to 0x80000000 to prevent signed shift
overflow.
Fixes: f587de0e2feb ("[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port")
Cc: stable@vger.kernel.org
Signed-off-by: Subham Pal <subhampal789@gmail.com>
---
net/netfilter/nf_conntrack_h323_asn1.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index 6830c9da3507..57317a28212b 100644
--- a/net/netfilter/nf_conntrack_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -596,6 +596,9 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
/* Decode the extension components */
for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
+ if (!((0x80000000U >> opt) & bmp2)) /* Not present */
+ continue;
+
/* Check Range */
if (i >= f->ub) { /* Newer Version? */
if (nf_h323_error_boundary(bs, 2, 0))
@@ -613,9 +616,6 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f,
return H323_ERROR_STOP;
}
- if (!((0x80000000 >> opt) & bmp2)) /* Not present */
- continue;
-
if (nf_h323_error_boundary(bs, 2, 0))
return H323_ERROR_BOUND;
len = get_len(bs);
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode
2026-09-23 4:20 [PATCH net 0/2] netfilter: nf_conntrack_h323: fixes for NAT bypass and ASN.1 decode Subham Pal
2026-09-23 4:23 ` [PATCH net 1/2] netfilter: nf_conntrack_h323: do not bypass NAT helpers when tuple source matches reply destination Subham Pal
2026-09-23 4:25 ` [PATCH net 2/2] netfilter: nf_conntrack_h323: check extension bitmap before decoding components Subham Pal
@ 2026-09-23 8:46 ` Pablo Neira Ayuso
2026-09-23 10:46 ` Subham Pal
2 siblings, 1 reply; 10+ messages in thread
From: Pablo Neira Ayuso @ 2026-09-23 8:46 UTC (permalink / raw)
To: Subham Pal
Cc: fw, phil, kaber, davem, edumazet, kuba, pabeni, horms,
netfilter-devel, netdev, stable
Hi,
On Wed, Sep 23, 2026 at 09:50:22AM +0530, Subham Pal wrote:
> This series resolves two separate issues in the Netfilter H.323 helper:
>
> 1. Overly restrictive tuple comparisons across expectation helpers
> (expect_h245, expect_rtp_rtcp, expect_t120, expect_callforwarding)
> that bypass NAT payload mangling under DNAT, hairpin routing, and
> reverse/reply traffic directions.
> 2. An ASN.1 PER decoding bug in decode_seq() where absent extension fields
> are processed before verifying their presence in the extension bitmap,
> leading to packet bitstream desynchronization or premature aborts.
I understand these are correctness fixes.
Do you have a reproducer/PoC? Do you tests for this?
> Subham Pal (2):
> netfilter: nf_conntrack_h323: do not bypass NAT helpers when tuple
> source matches reply destination
> netfilter: nf_conntrack_h323: check extension bitmap before decoding
> components
>
> net/netfilter/nf_conntrack_h323_asn1.c | 6 +++---
> net/netfilter/nf_conntrack_h323_main.c | 24 ++++++------------------
> 2 files changed, 9 insertions(+), 21 deletions(-)
^ permalink raw reply [flat|nested] 10+ messages in thread