netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Georg Kohmann (geokohma)" <geokohma@cisco.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: "netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"kadlec@netfilter.org" <kadlec@netfilter.org>,
	"fw@strlen.de" <fw@strlen.de>,
	"davem@davemloft.net" <davem@davemloft.net>,
	"kuznet@ms2.inr.ac.ru" <kuznet@ms2.inr.ac.ru>,
	"yoshfuji@linux-ipv6.org" <yoshfuji@linux-ipv6.org>,
	"kuba@kernel.org" <kuba@kernel.org>,
	"netfilter-devel@vger.kernel.org"
	<netfilter-devel@vger.kernel.org>,
	"coreteam@netfilter.org" <coreteam@netfilter.org>
Subject: Re: [PATCH net] ipv6/netfilter: Discard first fragment not including all headers
Date: Wed, 4 Nov 2020 14:17:31 +0000	[thread overview]
Message-ID: <1c9d2225-de09-0eb1-9d5f-20331458d9a0@cisco.com> (raw)
In-Reply-To: <20201104134118.GA28789@salvia>

On 04.11.2020 14:41, Pablo Neira Ayuso wrote:
> Hi,
>
> On Wed, Nov 04, 2020 at 02:01:28PM +0100, Georg Kohmann wrote:
>> Packets are processed even though the first fragment don't include all
>> headers through the upper layer header. This breaks TAHI IPv6 Core
>> Conformance Test v6LC.1.3.6.
>>
>> Referring to RFC8200 SECTION 4.5: "If the first fragment does not include
>> all headers through an Upper-Layer header, then that fragment should be
>> discarded and an ICMP Parameter Problem, Code 3, message should be sent to
>> the source of the fragment, with the Pointer field set to zero."
>>
>> Utilize the fragment offset returned by find_prev_fhdr() to let
>> ipv6_skip_exthdr() start it's traverse from the fragment header.
>> Apply the same logic for checking that all headers are included as used
>> in commit 2efdaaaf883a ("IPv6: reply ICMP error if the first fragment don't
>> include all headers"). Check that TCP, UDP and ICMP headers are completely
>> included in the fragment and all other headers are included with at least
>> one byte.
>>
>> Return 0 to drop the fragment. This is the same behaviour as used on other
>> protocol errors in this function, e.g. when nf_ct_frag6_queue() returns
>> -EPROTO. The Fragment will later be picked up by ipv6_frag_rcv() in
>> reassembly.c. ipv6_frag_rcv() will then send an appropriate ICMP Parameter
>> Problem message back to the source.
>>
>> References commit 2efdaaaf883a ("IPv6: reply ICMP error if the first
>> fragment don't include all headers")
>> Signed-off-by: Georg Kohmann <geokohma@cisco.com>
>> ---
>>  net/ipv6/netfilter/nf_conntrack_reasm.c | 28 +++++++++++++++++++++++++++-
>>  1 file changed, 27 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
>> index 054d287..dffa3a8 100644
>> --- a/net/ipv6/netfilter/nf_conntrack_reasm.c
>> +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
>> @@ -440,11 +440,13 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
>>  int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
>>  {
>>  	u16 savethdr = skb->transport_header;
>> -	int fhoff, nhoff, ret;
>> +	int fhoff, nhoff, ret, offset;
>>  	struct frag_hdr *fhdr;
>>  	struct frag_queue *fq;
>>  	struct ipv6hdr *hdr;
>>  	u8 prevhdr;
>> +	u8 nexthdr = NEXTHDR_FRAGMENT;
>> +	__be16 frag_off;
>>  
>>  	/* Jumbo payload inhibits frag. header */
>>  	if (ipv6_hdr(skb)->payload_len == 0) {
>> @@ -455,6 +457,30 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
>>  	if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0)
>>  		return 0;
>>  
>> +	/* Discard the first fragment if it does not include all headers
>> +	 * RFC 8200, Section 4.5
>> +	 */
>> +	offset = ipv6_skip_exthdr(skb, fhoff, &nexthdr, &frag_off);
>> +	if (offset >= 0 && !(frag_off & htons(IP6_OFFSET))) {
>> +		switch (nexthdr) {
>> +		case NEXTHDR_TCP:
>> +			offset += sizeof(struct tcphdr);
>> +			break;
>> +		case NEXTHDR_UDP:
>> +			offset += sizeof(struct udphdr);
>> +			break;
>> +		case NEXTHDR_ICMP:
>> +			offset += sizeof(struct icmp6hdr);
>> +			break;
>> +		default:
>> +			offset += 1;
>> +		}
>> +		if (offset > skb->len) {
>> +			pr_debug("Drop incomplete fragment\n");
>> +			return 0;
>> +		}
>> +	}
> This code looks very similar to 2efdaaaf883a.
>
> Would you wrap it in a function as call it use to reuse it? Something
> like this sketch?
>
> static bool ipv6_frag_validate(struct sk_buff *skb, ...)
> {
>         ...
>
> 	offset = ipv6_skip_exthdr(skb, fhoff, &nexthdr, &frag_off);
> 	if (offset >= 0 && !(frag_off & htons(IP6_OFFSET))) {
> 		switch (nexthdr) {
> 		case NEXTHDR_TCP:
> 			offset += sizeof(struct tcphdr);
> 			break;
> 		case NEXTHDR_UDP:
> 			offset += sizeof(struct udphdr);
> 			break;
> 		case NEXTHDR_ICMP:
> 			offset += sizeof(struct icmp6hdr);
> 			break;
> 		default:
> 			offset += 1;
> 		}
> 		if (offset > skb->len)
> 			return false;
> 	}
>
>         return true;
> }
>
> then, from ipv6:
>
>         if (!ipv6_frag_validate(skb, ...)) {
>                 __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
>                                         IPSTATS_MIB_INHDRERRORS);
>                 icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0);
>                 reurn -1;
>         }
>
> and from netfilter:
>
>         if (!ipv6_frag_validate(skb, ...))
>                 return -1;
>
> Thanks.
>
Thanks for feedback, I will do as suggested.

>>  	if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr)))
>>  		return -ENOMEM;
>>  
>> -- 
>> 2.10.2
>>


      reply	other threads:[~2020-11-04 14:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-04 13:01 [PATCH net] ipv6/netfilter: Discard first fragment not including all headers Georg Kohmann
2020-11-04 13:41 ` Pablo Neira Ayuso
2020-11-04 14:17   ` Georg Kohmann (geokohma) [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1c9d2225-de09-0eb1-9d5f-20331458d9a0@cisco.com \
    --to=geokohma@cisco.com \
    --cc=coreteam@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=fw@strlen.de \
    --cc=kadlec@netfilter.org \
    --cc=kuba@kernel.org \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).