* [PATCH net 1/6] netfilter: conntrack: don't refresh sctp entries in closed state
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
@ 2022-02-04 15:18 ` Pablo Neira Ayuso
2022-02-04 17:40 ` patchwork-bot+netdevbpf
2022-02-04 15:18 ` [PATCH nf-next] netfilter: nft_cmp: optimize comparison for up to 16-bytes Pablo Neira Ayuso
` (5 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
Vivek Thrivikraman reported:
An SCTP server application which is accessed continuously by client
application.
When the session disconnects the client retries to establish a connection.
After restart of SCTP server application the session is not established
because of stale conntrack entry with connection state CLOSED as below.
(removing this entry manually established new connection):
sctp 9 CLOSED src=10.141.189.233 [..] [ASSURED]
Just skip timeout update of closed entries, we don't want them to
stay around forever.
Reported-and-tested-by: Vivek Thrivikraman <vivek.thrivikraman@est.tech>
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1579
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_proto_sctp.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 2394238d01c9..5a936334b517 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -489,6 +489,15 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
pr_debug("Setting vtag %x for dir %d\n",
ih->init_tag, !dir);
ct->proto.sctp.vtag[!dir] = ih->init_tag;
+
+ /* don't renew timeout on init retransmit so
+ * port reuse by client or NAT middlebox cannot
+ * keep entry alive indefinitely (incl. nat info).
+ */
+ if (new_state == SCTP_CONNTRACK_CLOSED &&
+ old_state == SCTP_CONNTRACK_CLOSED &&
+ nf_ct_is_confirmed(ct))
+ ignore = true;
}
ct->proto.sctp.state = new_state;
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH net 1/6] netfilter: conntrack: don't refresh sctp entries in closed state
2022-02-04 15:18 ` [PATCH net 1/6] netfilter: conntrack: don't refresh sctp entries in closed state Pablo Neira Ayuso
@ 2022-02-04 17:40 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-02-04 17:40 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, davem, netdev, kuba
Hello:
This series was applied to netdev/net.git (master)
by Pablo Neira Ayuso <pablo@netfilter.org>:
On Fri, 4 Feb 2022 16:18:57 +0100 you wrote:
> From: Florian Westphal <fw@strlen.de>
>
> Vivek Thrivikraman reported:
> An SCTP server application which is accessed continuously by client
> application.
> When the session disconnects the client retries to establish a connection.
> After restart of SCTP server application the session is not established
> because of stale conntrack entry with connection state CLOSED as below.
>
> [...]
Here is the summary with links:
- [net,1/6] netfilter: conntrack: don't refresh sctp entries in closed state
https://git.kernel.org/netdev/net/c/77b337196a9d
- [net,2/6] netfilter: nft_payload: don't allow th access for fragments
https://git.kernel.org/netdev/net/c/a9e8503def0f
- [net,3/6] netfilter: conntrack: move synack init code to helper
https://git.kernel.org/netdev/net/c/cc4f9d62037e
- [net,4/6] netfilter: conntrack: re-init state for retransmitted syn-ack
https://git.kernel.org/netdev/net/c/82b72cb94666
- [net,5/6] MAINTAINERS: netfilter: update git links
https://git.kernel.org/netdev/net/c/1f6339e034d5
- [net,6/6] netfilter: ctnetlink: disable helper autoassign
https://git.kernel.org/netdev/net/c/d1ca60efc53d
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH nf-next] netfilter: nft_cmp: optimize comparison for up to 16-bytes
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
2022-02-04 15:18 ` [PATCH net 1/6] netfilter: conntrack: don't refresh sctp entries in closed state Pablo Neira Ayuso
@ 2022-02-04 15:18 ` Pablo Neira Ayuso
2022-02-05 1:17 ` kernel test robot
2022-02-04 15:18 ` [PATCH net 2/6] netfilter: nft_payload: don't allow th access for fragments Pablo Neira Ayuso
` (4 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
Allow up to 16-byte comparisons with the cmp fast version. Use two
64-bit words and calculate the mask representing the bits to be
compared. Make sure the comparison is 64-bit aligned and avoid
out-of-bound memory access.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_tables_core.h | 4 +--
net/netfilter/nf_tables_core.c | 6 +++-
net/netfilter/nft_cmp.c | 48 +++++++++++++++++---------
3 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index b6fb1fdff9b2..52395e216ecc 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -35,8 +35,8 @@ struct nft_bitwise_fast_expr {
};
struct nft_cmp_fast_expr {
- u32 data;
- u32 mask;
+ struct nft_data data;
+ struct nft_data mask;
u8 sreg;
u8 len;
bool inv;
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 36e73f9828c5..000c598cbc13 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -61,8 +61,12 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr,
struct nft_regs *regs)
{
const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
+ const u64 *reg_data = (const u64 *)®s->data[priv->sreg];
+ const u64 *mask = (const u64 *)&priv->mask;
+ const u64 *data = (const u64 *)&priv->data;
- if (((regs->data[priv->sreg] & priv->mask) == priv->data) ^ priv->inv)
+ if (((reg_data[0] & mask[0]) == data[0] &&
+ ((reg_data[1] & mask[1]) == data[1])) ^ priv->inv)
return;
regs->verdict.code = NFT_BREAK;
}
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 47b6d05f1ae6..ea9dcb380cac 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -76,6 +76,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
struct nft_data_desc desc;
int err;
+ memset(&priv->data, 0, sizeof(priv->data));
err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &desc,
tb[NFTA_CMP_DATA]);
if (err < 0)
@@ -196,16 +197,32 @@ static const struct nft_expr_ops nft_cmp_ops = {
.offload = nft_cmp_offload,
};
+static void nft_cmp16_fast_mask(struct nft_data *data, unsigned int bitlen)
+{
+ int len = bitlen / BITS_PER_BYTE;
+ int i, words = len / sizeof(u32);
+
+ for (i = 0; i < words; i++) {
+ data->data[i] = 0xffffffff;
+ bitlen -= sizeof(u32) * BITS_PER_BYTE;
+ }
+
+ if (len % sizeof(u32))
+ data->data[i++] = cpu_to_le32(~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen));
+
+ for (; i < 4; i++)
+ data->data[i] = 0;
+}
+
static int nft_cmp_fast_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
struct nft_data_desc desc;
- struct nft_data data;
int err;
- err = nft_data_init(NULL, &data, sizeof(data), &desc,
+ err = nft_data_init(NULL, &priv->data, sizeof(priv->data), &desc,
tb[NFTA_CMP_DATA]);
if (err < 0)
return err;
@@ -214,12 +231,10 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
if (err < 0)
return err;
- desc.len *= BITS_PER_BYTE;
-
- priv->mask = nft_cmp_fast_mask(desc.len);
- priv->data = data.data[0] & priv->mask;
priv->len = desc.len;
priv->inv = ntohl(nla_get_be32(tb[NFTA_CMP_OP])) != NFT_CMP_EQ;
+ nft_cmp16_fast_mask(&priv->mask, desc.len * BITS_PER_BYTE);
+
return 0;
}
@@ -229,13 +244,9 @@ static int nft_cmp_fast_offload(struct nft_offload_ctx *ctx,
{
const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
struct nft_cmp_expr cmp = {
- .data = {
- .data = {
- [0] = priv->data,
- },
- },
+ .data = priv->data,
.sreg = priv->sreg,
- .len = priv->len / BITS_PER_BYTE,
+ .len = priv->len,
.op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ,
};
@@ -246,16 +257,14 @@ static int nft_cmp_fast_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
enum nft_cmp_ops op = priv->inv ? NFT_CMP_NEQ : NFT_CMP_EQ;
- struct nft_data data;
if (nft_dump_register(skb, NFTA_CMP_SREG, priv->sreg))
goto nla_put_failure;
if (nla_put_be32(skb, NFTA_CMP_OP, htonl(op)))
goto nla_put_failure;
- data.data[0] = priv->data;
- if (nft_data_dump(skb, NFTA_CMP_DATA, &data,
- NFT_DATA_VALUE, priv->len / BITS_PER_BYTE) < 0)
+ if (nft_data_dump(skb, NFTA_CMP_DATA, &priv->data,
+ NFT_DATA_VALUE, priv->len) < 0)
goto nla_put_failure;
return 0;
@@ -278,6 +287,7 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
struct nft_data_desc desc;
struct nft_data data;
enum nft_cmp_ops op;
+ u8 sreg;
int err;
if (tb[NFTA_CMP_SREG] == NULL ||
@@ -306,7 +316,11 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
if (desc.type != NFT_DATA_VALUE)
goto err1;
- if (desc.len <= sizeof(u32) && (op == NFT_CMP_EQ || op == NFT_CMP_NEQ))
+ sreg = ntohl(nla_get_be32(tb[NFTA_CMP_SREG]));
+
+ if (sreg >= NFT_REG_1 && sreg <= NFT_REG32_12 &&
+ (sreg <= NFT_REG_4 || sreg % 2 == 0) &&
+ (op == NFT_CMP_EQ || op == NFT_CMP_NEQ))
return &nft_cmp_fast_ops;
return &nft_cmp_ops;
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH nf-next] netfilter: nft_cmp: optimize comparison for up to 16-bytes
2022-02-04 15:18 ` [PATCH nf-next] netfilter: nft_cmp: optimize comparison for up to 16-bytes Pablo Neira Ayuso
@ 2022-02-05 1:17 ` kernel test robot
0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2022-02-05 1:17 UTC (permalink / raw)
To: Pablo Neira Ayuso, netfilter-devel; +Cc: kbuild-all, davem, netdev, kuba
Hi Pablo,
I love your patch! Perhaps something to improve:
[auto build test WARNING on nf-next/master]
url: https://github.com/0day-ci/linux/commits/Pablo-Neira-Ayuso/netfilter-nft_cmp-optimize-comparison-for-up-to-16-bytes/20220204-232030
base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master
config: x86_64-rhel-8.3-kselftests (https://download.01.org/0day-ci/archive/20220205/202202050944.nFxizuBh-lkp@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.4-dirty
# https://github.com/0day-ci/linux/commit/91cb7a051c24382b5a7252e59fc5a6a6e2d62332
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Pablo-Neira-Ayuso/netfilter-nft_cmp-optimize-comparison-for-up-to-16-bytes/20220204-232030
git checkout 91cb7a051c24382b5a7252e59fc5a6a6e2d62332
# save the config file to linux build tree
mkdir build_dir
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash net/netfilter/
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
net/netfilter/nft_cmp.c:129:31: sparse: sparse: cast to restricted __be16
net/netfilter/nft_cmp.c:132:31: sparse: sparse: cast to restricted __be32
net/netfilter/nft_cmp.c:135:31: sparse: sparse: cast to restricted __be64
>> net/netfilter/nft_cmp.c:211:33: sparse: sparse: incorrect type in assignment (different base types) @@ expected unsigned int @@ got restricted __le32 [usertype] @@
net/netfilter/nft_cmp.c:211:33: sparse: expected unsigned int
net/netfilter/nft_cmp.c:211:33: sparse: got restricted __le32 [usertype]
vim +211 net/netfilter/nft_cmp.c
199
200 static void nft_cmp16_fast_mask(struct nft_data *data, unsigned int bitlen)
201 {
202 int len = bitlen / BITS_PER_BYTE;
203 int i, words = len / sizeof(u32);
204
205 for (i = 0; i < words; i++) {
206 data->data[i] = 0xffffffff;
207 bitlen -= sizeof(u32) * BITS_PER_BYTE;
208 }
209
210 if (len % sizeof(u32))
> 211 data->data[i++] = cpu_to_le32(~0U >> (sizeof(u32) * BITS_PER_BYTE - bitlen));
212
213 for (; i < 4; i++)
214 data->data[i] = 0;
215 }
216
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net 2/6] netfilter: nft_payload: don't allow th access for fragments
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
2022-02-04 15:18 ` [PATCH net 1/6] netfilter: conntrack: don't refresh sctp entries in closed state Pablo Neira Ayuso
2022-02-04 15:18 ` [PATCH nf-next] netfilter: nft_cmp: optimize comparison for up to 16-bytes Pablo Neira Ayuso
@ 2022-02-04 15:18 ` Pablo Neira Ayuso
2022-02-04 15:19 ` [PATCH net 3/6] netfilter: conntrack: move synack init code to helper Pablo Neira Ayuso
` (3 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
Loads relative to ->thoff naturally expect that this points to the
transport header, but this is only true if pkt->fragoff == 0.
This has little effect for rulesets with connection tracking/nat because
these enable ip defra. For other rulesets this prevents false matches.
Fixes: 96518518cc41 ("netfilter: add nftables")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_exthdr.c | 2 +-
net/netfilter/nft_payload.c | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c
index dbe1f2e7dd9e..9e927ab4df15 100644
--- a/net/netfilter/nft_exthdr.c
+++ b/net/netfilter/nft_exthdr.c
@@ -167,7 +167,7 @@ nft_tcp_header_pointer(const struct nft_pktinfo *pkt,
{
struct tcphdr *tcph;
- if (pkt->tprot != IPPROTO_TCP)
+ if (pkt->tprot != IPPROTO_TCP || pkt->fragoff)
return NULL;
tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt), sizeof(*tcph), buffer);
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 940fed9a760b..5cc06aef4345 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -83,7 +83,7 @@ static int __nft_payload_inner_offset(struct nft_pktinfo *pkt)
{
unsigned int thoff = nft_thoff(pkt);
- if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
+ if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff)
return -1;
switch (pkt->tprot) {
@@ -147,7 +147,7 @@ void nft_payload_eval(const struct nft_expr *expr,
offset = skb_network_offset(skb);
break;
case NFT_PAYLOAD_TRANSPORT_HEADER:
- if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
+ if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff)
goto err;
offset = nft_thoff(pkt);
break;
@@ -688,7 +688,7 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
offset = skb_network_offset(skb);
break;
case NFT_PAYLOAD_TRANSPORT_HEADER:
- if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
+ if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff)
goto err;
offset = nft_thoff(pkt);
break;
@@ -728,7 +728,8 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP &&
pkt->tprot == IPPROTO_SCTP &&
skb->ip_summed != CHECKSUM_PARTIAL) {
- if (nft_payload_csum_sctp(skb, nft_thoff(pkt)))
+ if (pkt->fragoff == 0 &&
+ nft_payload_csum_sctp(skb, nft_thoff(pkt)))
goto err;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 3/6] netfilter: conntrack: move synack init code to helper
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
` (2 preceding siblings ...)
2022-02-04 15:18 ` [PATCH net 2/6] netfilter: nft_payload: don't allow th access for fragments Pablo Neira Ayuso
@ 2022-02-04 15:19 ` Pablo Neira Ayuso
2022-02-04 15:19 ` [PATCH net 4/6] netfilter: conntrack: re-init state for retransmitted syn-ack Pablo Neira Ayuso
` (2 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
It seems more readable to use a common helper in the followup fix rather
than copypaste or goto.
No functional change intended. The function is only called for syn-ack
or syn in repy direction in case of simultaneous open.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_proto_tcp.c | 47 ++++++++++++++++----------
1 file changed, 29 insertions(+), 18 deletions(-)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index af5115e127cf..88c89e97d8a2 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -446,6 +446,32 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
}
}
+static void tcp_init_sender(struct ip_ct_tcp_state *sender,
+ struct ip_ct_tcp_state *receiver,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ const struct tcphdr *tcph,
+ u32 end, u32 win)
+{
+ /* SYN-ACK in reply to a SYN
+ * or SYN from reply direction in simultaneous open.
+ */
+ sender->td_end =
+ sender->td_maxend = end;
+ sender->td_maxwin = (win == 0 ? 1 : win);
+
+ tcp_options(skb, dataoff, tcph, sender);
+ /* RFC 1323:
+ * Both sides must send the Window Scale option
+ * to enable window scaling in either direction.
+ */
+ if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
+ receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE)) {
+ sender->td_scale = 0;
+ receiver->td_scale = 0;
+ }
+}
+
static bool tcp_in_window(struct nf_conn *ct,
enum ip_conntrack_dir dir,
unsigned int index,
@@ -499,24 +525,9 @@ static bool tcp_in_window(struct nf_conn *ct,
* Initialize sender data.
*/
if (tcph->syn) {
- /*
- * SYN-ACK in reply to a SYN
- * or SYN from reply direction in simultaneous open.
- */
- sender->td_end =
- sender->td_maxend = end;
- sender->td_maxwin = (win == 0 ? 1 : win);
-
- tcp_options(skb, dataoff, tcph, sender);
- /*
- * RFC 1323:
- * Both sides must send the Window Scale option
- * to enable window scaling in either direction.
- */
- if (!(sender->flags & IP_CT_TCP_FLAG_WINDOW_SCALE
- && receiver->flags & IP_CT_TCP_FLAG_WINDOW_SCALE))
- sender->td_scale =
- receiver->td_scale = 0;
+ tcp_init_sender(sender, receiver,
+ skb, dataoff, tcph,
+ end, win);
if (!tcph->ack)
/* Simultaneous open */
return true;
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 4/6] netfilter: conntrack: re-init state for retransmitted syn-ack
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
` (3 preceding siblings ...)
2022-02-04 15:19 ` [PATCH net 3/6] netfilter: conntrack: move synack init code to helper Pablo Neira Ayuso
@ 2022-02-04 15:19 ` Pablo Neira Ayuso
2022-02-04 15:19 ` [PATCH net 5/6] MAINTAINERS: netfilter: update git links Pablo Neira Ayuso
2022-02-04 15:19 ` [PATCH net 6/6] netfilter: ctnetlink: disable helper autoassign Pablo Neira Ayuso
6 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
TCP conntrack assumes that a syn-ack retransmit is identical to the
previous syn-ack. This isn't correct and causes stuck 3whs in some more
esoteric scenarios. tcpdump to illustrate the problem:
client > server: Flags [S] seq 1365731894, win 29200, [mss 1460,sackOK,TS val 2083035583 ecr 0,wscale 7]
server > client: Flags [S.] seq 145824453, ack 643160523, win 65535, [mss 8952,wscale 5,TS val 3215367629 ecr 2082921663]
Note the invalid/outdated synack ack number.
Conntrack marks this syn-ack as out-of-window/invalid, but it did
initialize the reply direction parameters based on this packets content.
client > server: Flags [S] seq 1365731894, win 29200, [mss 1460,sackOK,TS val 2083036623 ecr 0,wscale 7]
... retransmit...
server > client: Flags [S.], seq 145824453, ack 643160523, win 65535, [mss 8952,wscale 5,TS val 3215368644 ecr 2082921663]
and another bogus synack. This repeats, then client re-uses for a new
attempt:
client > server: Flags [S], seq 2375731741, win 29200, [mss 1460,sackOK,TS val 2083100223 ecr 0,wscale 7]
server > client: Flags [S.], seq 145824453, ack 643160523, win 65535, [mss 8952,wscale 5,TS val 3215430754 ecr 2082921663]
... but still gets a invalid syn-ack.
This repeats until:
server > client: Flags [S.], seq 145824453, ack 643160523, win 65535, [mss 8952,wscale 5,TS val 3215437785 ecr 2082921663]
server > client: Flags [R.], seq 145824454, ack 643160523, win 65535, [mss 8952,wscale 5,TS val 3215443451 ecr 2082921663]
client > server: Flags [S], seq 2375731741, win 29200, [mss 1460,sackOK,TS val 2083115583 ecr 0,wscale 7]
server > client: Flags [S.], seq 162602410, ack 2375731742, win 65535, [mss 8952,wscale 5,TS val 3215445754 ecr 2083115583]
This syn-ack has the correct ack number, but conntrack flags it as
invalid: The internal state was created from the first syn-ack seen
so the sequence number of the syn-ack is treated as being outside of
the announced window.
Don't assume that retransmitted syn-ack is identical to previous one.
Treat it like the first syn-ack and reinit state.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_conntrack_proto_tcp.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 88c89e97d8a2..d1582b888c0d 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -571,6 +571,18 @@ static bool tcp_in_window(struct nf_conn *ct,
sender->td_maxwin = (win == 0 ? 1 : win);
tcp_options(skb, dataoff, tcph, sender);
+ } else if (tcph->syn && dir == IP_CT_DIR_REPLY &&
+ state->state == TCP_CONNTRACK_SYN_SENT) {
+ /* Retransmitted syn-ack, or syn (simultaneous open).
+ *
+ * Re-init state for this direction, just like for the first
+ * syn(-ack) reply, it might differ in seq, ack or tcp options.
+ */
+ tcp_init_sender(sender, receiver,
+ skb, dataoff, tcph,
+ end, win);
+ if (!tcph->ack)
+ return true;
}
if (!(tcph->ack)) {
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 5/6] MAINTAINERS: netfilter: update git links
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
` (4 preceding siblings ...)
2022-02-04 15:19 ` [PATCH net 4/6] netfilter: conntrack: re-init state for retransmitted syn-ack Pablo Neira Ayuso
@ 2022-02-04 15:19 ` Pablo Neira Ayuso
2022-02-04 15:19 ` [PATCH net 6/6] netfilter: ctnetlink: disable helper autoassign Pablo Neira Ayuso
6 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
nf and nf-next have a new location.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
MAINTAINERS | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index bb83dcbcb619..3a9cb567d47c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13297,8 +13297,8 @@ W: http://www.iptables.org/
W: http://www.nftables.org/
Q: http://patchwork.ozlabs.org/project/netfilter-devel/list/
C: irc://irc.libera.chat/netfilter
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next.git
F: include/linux/netfilter*
F: include/linux/netfilter/
F: include/net/netfilter/
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH net 6/6] netfilter: ctnetlink: disable helper autoassign
2022-02-04 15:18 [PATCH net 0/6] Netfilter fixes for net Pablo Neira Ayuso
` (5 preceding siblings ...)
2022-02-04 15:19 ` [PATCH net 5/6] MAINTAINERS: netfilter: update git links Pablo Neira Ayuso
@ 2022-02-04 15:19 ` Pablo Neira Ayuso
6 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2022-02-04 15:19 UTC (permalink / raw)
To: netfilter-devel; +Cc: davem, netdev, kuba
From: Florian Westphal <fw@strlen.de>
When userspace, e.g. conntrackd, inserts an entry with a specified helper,
its possible that the helper is lost immediately after its added:
ctnetlink_create_conntrack
-> nf_ct_helper_ext_add + assign helper
-> ctnetlink_setup_nat
-> ctnetlink_parse_nat_setup
-> parse_nat_setup -> nfnetlink_parse_nat_setup
-> nf_nat_setup_info
-> nf_conntrack_alter_reply
-> __nf_ct_try_assign_helper
... and __nf_ct_try_assign_helper will zero the helper again.
Set IPS_HELPER bit to bypass auto-assign logic, its unwanted, just like
when helper is assigned via ruleset.
Dropped old 'not strictly necessary' comment, it referred to use of
rcu_assign_pointer() before it got replaced by RCU_INIT_POINTER().
NB: Fixes tag intentionally incorrect, this extends the referenced commit,
but this change won't build without IPS_HELPER introduced there.
Fixes: 6714cf5465d280 ("netfilter: nf_conntrack: fix explicit helper attachment and NAT")
Reported-by: Pham Thanh Tuyen <phamtyn@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/uapi/linux/netfilter/nf_conntrack_common.h | 2 +-
net/netfilter/nf_conntrack_netlink.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 4b3395082d15..26071021e986 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -106,7 +106,7 @@ enum ip_conntrack_status {
IPS_NAT_CLASH = IPS_UNTRACKED,
#endif
- /* Conntrack got a helper explicitly attached via CT target. */
+ /* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */
IPS_HELPER_BIT = 13,
IPS_HELPER = (1 << IPS_HELPER_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ac438370f94a..7032402ffd33 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2311,7 +2311,8 @@ ctnetlink_create_conntrack(struct net *net,
if (helper->from_nlattr)
helper->from_nlattr(helpinfo, ct);
- /* not in hash table yet so not strictly necessary */
+ /* disable helper auto-assignment for this entry */
+ ct->status |= IPS_HELPER;
RCU_INIT_POINTER(help->helper, helper);
}
} else {
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread