RE: [PATCH nf 3/4] netfilter: conntrack_ftp: prefer skb_linearize

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Florian Westphal <fw@xxxxxxxxx>
> Sent: Tuesday, August 9, 2022 6:17 AM
> To: netfilter-devel@xxxxxxxxxxxxxxx
> Cc: Alexander Duyck <alexanderduyck@xxxxxx>; edumazet@xxxxxxxxxx;
> Florian Westphal <fw@xxxxxxxxx>
> Subject: [PATCH nf 3/4] netfilter: conntrack_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: 7c4e983c4f3c ("net: allow gso_max_size to exceed 65536")
> Fixes: 0fe79f28bfaf ("net: allow gro_max_size to exceed 65536")
> Signed-off-by: Florian Westphal <fw@xxxxxxxxx>
> ---
>  net/netfilter/nf_conntrack_ftp.c | 24 ++++++------------------
>  1 file changed, 6 insertions(+), 18 deletions(-)
> 
> diff --git a/net/netfilter/nf_conntrack_ftp.c
> b/net/netfilter/nf_conntrack_ftp.c
> index a414274338cf..0d9332e9cf71 100644
> --- a/net/netfilter/nf_conntrack_ftp.c
> +++ b/net/netfilter/nf_conntrack_ftp.c
> @@ -34,11 +34,6 @@ MODULE_DESCRIPTION("ftp connection tracking
> helper");  MODULE_ALIAS("ip_conntrack_ftp");
> MODULE_ALIAS_NFCT_HELPER(HELPER_NAME);
> 
> -/* This is slow, but it's simple. --RR */ -static char *ftp_buffer;
> -
> -static DEFINE_SPINLOCK(nf_ftp_lock);
> -
>  #define MAX_PORTS 8
>  static u_int16_t ports[MAX_PORTS];
>  static unsigned int ports_c;
> @@ -398,6 +393,9 @@ static int help(struct sk_buff *skb,
>  		return NF_ACCEPT;
>  	}
> 
> +	if (unlikely(skb_linearize(skb)))
> +		return NF_DROP;
> +
>  	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
>  	if (th == NULL)
>  		return NF_ACCEPT;

Doing a full linearize seems like it would be much more expensive than it needs to be for a full frame.

> @@ -411,12 +409,8 @@ static int help(struct sk_buff *skb,
>  	}
>  	datalen = skb->len - dataoff;
> 
> -	spin_lock_bh(&nf_ftp_lock);
> -	fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer);
> -	if (!fb_ptr) {
> -		spin_unlock_bh(&nf_ftp_lock);
> -		return NF_ACCEPT;
> -	}
> +	spin_lock_bh(&ct->lock);
> +	fb_ptr = skb->data + dataoff;
> 
>  	ends_in_nl = (fb_ptr[datalen - 1] == '\n');
>  	seq = ntohl(th->seq) + datalen;

Rather than using skb_header_pointer/skb_linearize is there any reason why you couldn't use pskb_may_pull? It seems like that would be much closer to what you are looking for here rather than linearizing the entire buffer. With that you would have access to all the same headers you did with the skb_header_pointer approach and in most cases the copy should just be skipped since the headlen is already in the skb->data buffer.




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux