Skip to content

Commit 4cca766

Browse files
committed
netfilter: nf_ct_ftp: prefer skb_linearize
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2139501 commit c783a29 Author: Florian Westphal <fw@strlen.de> Date: Tue Aug 9 15:16:34 2022 +0200 netfilter: nf_ct_ftp: prefer skb_linearize This uses a pseudo-linearization scheme with a 64k global buffer, but BIG TCP arrival means IPv6 TCP stack can generate skbs that exceed this size. Use skb_linearize. It should be possible to rewrite this to properly deal with segmented skbs (i.e., only do small chunk-wise accesses), but this is going to be a lot more intrusive than this because every helper function needs to get the sk_buff instead of a pointer to a raw data buffer. In practice, provided we're really looking at FTP control channel packets, there should never be a case where we deal with huge packets. Fixes: 7c4e983 ("net: allow gso_max_size to exceed 65536") Fixes: 0fe79f2 ("net: allow gro_max_size to exceed 65536") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
1 parent 10f6670 commit 4cca766

File tree

1 file changed

+6
-18
lines changed

1 file changed

+6
-18
lines changed

net/netfilter/nf_conntrack_ftp.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,6 @@ MODULE_DESCRIPTION("ftp connection tracking helper");
3434
MODULE_ALIAS("ip_conntrack_ftp");
3535
MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
3636

37-
/* This is slow, but it's simple. --RR */
38-
static char *ftp_buffer;
39-
40-
static DEFINE_SPINLOCK(nf_ftp_lock);
41-
4237
#define MAX_PORTS 8
4338
static u_int16_t ports[MAX_PORTS];
4439
static unsigned int ports_c;
@@ -398,6 +393,9 @@ static int help(struct sk_buff *skb,
398393
return NF_ACCEPT;
399394
}
400395

396+
if (unlikely(skb_linearize(skb)))
397+
return NF_DROP;
398+
401399
th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
402400
if (th == NULL)
403401
return NF_ACCEPT;
@@ -411,12 +409,8 @@ static int help(struct sk_buff *skb,
411409
}
412410
datalen = skb->len - dataoff;
413411

414-
spin_lock_bh(&nf_ftp_lock);
415-
fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer);
416-
if (!fb_ptr) {
417-
spin_unlock_bh(&nf_ftp_lock);
418-
return NF_ACCEPT;
419-
}
412+
spin_lock_bh(&ct->lock);
413+
fb_ptr = skb->data + dataoff;
420414

421415
ends_in_nl = (fb_ptr[datalen - 1] == '\n');
422416
seq = ntohl(th->seq) + datalen;
@@ -544,7 +538,7 @@ static int help(struct sk_buff *skb,
544538
if (ends_in_nl)
545539
update_nl_seq(ct, seq, ct_ftp_info, dir, skb);
546540
out:
547-
spin_unlock_bh(&nf_ftp_lock);
541+
spin_unlock_bh(&ct->lock);
548542
return ret;
549543
}
550544

@@ -571,7 +565,6 @@ static const struct nf_conntrack_expect_policy ftp_exp_policy = {
571565
static void __exit nf_conntrack_ftp_fini(void)
572566
{
573567
nf_conntrack_helpers_unregister(ftp, ports_c * 2);
574-
kfree(ftp_buffer);
575568
}
576569

577570
static int __init nf_conntrack_ftp_init(void)
@@ -580,10 +573,6 @@ static int __init nf_conntrack_ftp_init(void)
580573

581574
NF_CT_HELPER_BUILD_BUG_ON(sizeof(struct nf_ct_ftp_master));
582575

583-
ftp_buffer = kmalloc(65536, GFP_KERNEL);
584-
if (!ftp_buffer)
585-
return -ENOMEM;
586-
587576
if (ports_c == 0)
588577
ports[ports_c++] = FTP_PORT;
589578

@@ -603,7 +592,6 @@ static int __init nf_conntrack_ftp_init(void)
603592
ret = nf_conntrack_helpers_register(ftp, ports_c * 2);
604593
if (ret < 0) {
605594
pr_err("failed to register helpers\n");
606-
kfree(ftp_buffer);
607595
return ret;
608596
}
609597

0 commit comments

Comments
 (0)