netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Hopps <chopps@chopps.org>
To: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Christian Hopps <chopps@chopps.org>,
	devel@linux-ipsec.org, netdev@vger.kernel.org,
	Florian Westphal <fw@strlen.de>,
	Sabrina Dubroca <sd@queasysnail.net>,
	Simon Horman <horms@kernel.org>,
	Antony Antony <antony@phenome.org>,
	Christian Hopps <chopps@labn.net>
Subject: Re: [PATCH ipsec-next v12 12/16] xfrm: iptfs: handle received fragmented inner packets
Date: Sat, 02 Nov 2024 16:01:42 +0000	[thread overview]
Message-ID: <m2r07tipr1.fsf@chopps.org> (raw)
In-Reply-To: <ZxYsWnWKPYyaoX79@gauss3.secunet.de>

[-- Attachment #1: Type: text/plain, Size: 5364 bytes --]


Steffen Klassert <steffen.klassert@secunet.com> writes:

> On Mon, Oct 07, 2024 at 09:59:24AM -0400, Christian Hopps wrote:
>> From: Christian Hopps <chopps@labn.net>
>>
>> +
>> +/**
>> + * __iptfs_iphlen() - return the v4/v6 header length using packet data.
>> + * @data: pointer at octet with version nibble
>> + *
>> + * The version data is expected to be valid (i.e., either 4 or 6).
>> + *
>> + * Return: the IP header size based on the IP version.
>> + */
>> +static u32 __iptfs_iphlen(u8 *data)
>> +{
>> +	struct iphdr *iph = (struct iphdr *)data;
>> +
>> +	if (iph->version == 0x4)
>> +		return sizeof(*iph);
>> +	WARN_ON_ONCE(iph->version != 0x6);
>> +	return sizeof(struct ipv6hdr);
>
> Better to return an error if this is not IPv6

The version is checked prior to calling to only be v4 or v6. Removed the WARN call and made the comment above saying this more explicit.

>> +}
>> +
>> +/**
>> + * __iptfs_iplen() - return the v4/v6 length using packet data.
>> + * @data: pointer to ip (v4/v6) packet header
>> + *
>> + * Grab the IPv4 or IPv6 length value in the start of the inner packet header
>> + * pointed to by `data`. Assumes data len is enough for the length field only.
>> + *
>> + * The version data is expected to be valid (i.e., either 4 or 6).
>> + *
>> + * Return: the length value.
>> + */
>> +static u32 __iptfs_iplen(u8 *data)
>> +{
>> +	struct iphdr *iph = (struct iphdr *)data;
>> +
>> +	if (iph->version == 0x4)
>> +		return ntohs(iph->tot_len);
>> +	WARN_ON_ONCE(iph->version != 0x6);
>> +	return ntohs(((struct ipv6hdr *)iph)->payload_len) +
>> +	       sizeof(struct ipv6hdr);
>
> Same here.

Same.

>> +
>> +		/* We have enough data to get the ip length value now,
>> +		 * allocate an in progress skb
>> +		 */
>> +		ipremain = __iptfs_iplen(xtfs->ra_runt);
>> +		if (ipremain < sizeof(xtfs->ra_runt)) {
>> +			/* length has to be at least runtsize large */
>> +			XFRM_INC_STATS(xs_net(xtfs->x),
>> +				       LINUX_MIB_XFRMINIPTFSERROR);
>> +			goto abandon;
>> +		}
>> +
>> +		/* For the runt case we don't attempt sharing currently. NOTE:
>> +		 * Currently, this IPTFS implementation will not create runts.
>> +		 */
>> +
>> +		newskb = iptfs_alloc_skb(skb, ipremain, false);
>
> As mentioned above, __iptfs_iplen needs error handling. Otherwise
> you might alocate a random amount of data here.
>
>> +		if (!newskb) {
>> +			XFRM_INC_STATS(xs_net(xtfs->x), LINUX_MIB_XFRMINERROR);
>> +			goto abandon;
>> +		}
>> +		xtfs->ra_newskb = newskb;
>> +
>> +		/* Copy the runt data into the buffer, but leave data
>> +		 * pointers the same as normal non-runt case. The extra `rrem`
>> +		 * recopied bytes are basically cacheline free. Allows using
>> +		 * same logic below to complete.
>> +		 */
>> +		memcpy(skb_put(newskb, runtlen), xtfs->ra_runt,
>> +		       sizeof(xtfs->ra_runt));
>> +	}
>> +
>> +	/* Continue reassembling the packet */
>> +	ipremain = __iptfs_iplen(newskb->data);
>> +	iphlen = __iptfs_iphlen(newskb->data);
>> +
>> +	/* Sanity check, we created the newskb knowing the IP length so the IP
>> +	 * length can't now be shorter.
>> +	 */
>> +	WARN_ON_ONCE(newskb->len > ipremain);
>> +
>> +	ipremain -= newskb->len;
>> +	if (blkoff < ipremain) {
>> +		/* Corrupt data, we don't have enough to complete the packet */
>> +		XFRM_INC_STATS(xs_net(xtfs->x), LINUX_MIB_XFRMINIPTFSERROR);
>> +		goto abandon;
>> +	}
>> +
>> +	/* We want the IP header in linear space */
>> +	if (newskb->len < iphlen) {
>> +		iphremain = iphlen - newskb->len;
>> +		if (blkoff < iphremain) {
>> +			XFRM_INC_STATS(xs_net(xtfs->x),
>> +				       LINUX_MIB_XFRMINIPTFSERROR);
>> +			goto abandon;
>> +		}
>> +		fraglen = min(blkoff, remaining);
>> +		copylen = min(fraglen, iphremain);
>> +		WARN_ON_ONCE(skb_tailroom(newskb) < copylen);
>
> This is also something that needs error handling. This WARN_ON_ONCE
> does not make much sense, as the next line will crash the machine
> anyway if this condition is true.
>
> This is also a general thing, there are a lot of WARN_ON_ONCE
> and you just continue after the warning. Whenever such a warn
> condition can happen, it needs audit why it can happen. Usually
> it can be either fixed or catched with an error. Warnings
> should be used very rarely.
>
> In this case you can either make sure to allocate the correct amount
> of data or extend the tailroom with pskb_expand_head().
>
> No need to crash the machine here :)
>
> Please audit your WARN_ON_ONCE calls, I guess most are either not
> needed or the condition can be handled otherwise somehow.

As we discussed offline, these uses were not where value can actually be wrong, they were all originally BUG_ON() and meant to document the code assumptions/assertions and to catch future coding/review bugs.

This is not a style that is used by/welcome in linux kernel code so I will remove it's use.

>
>> +		if (skb_copy_seq_read(st, data, skb_put(newskb, copylen),
>> +				      copylen)) {
>> +			XFRM_INC_STATS(xs_net(xtfs->x),
>> +				       LINUX_MIB_XFRMINBUFFERERROR);
>> +			goto abandon;
>> +		}
>
>> @@ -1286,7 +1729,11 @@ static int iptfs_copy_to_user(struct xfrm_state *x, struct sk_buff *skb)
>>  	int ret = 0;
>>  	u64 q;
>>
>> -	if (x->dir == XFRM_SA_DIR_OUT) {
>> +	if (x->dir == XFRM_SA_DIR_IN) {
>> +		q = xtfs->drop_time_ns;
>> +		(void)do_div(q, NSECS_IN_USEC);
>
> This cast is not needed.

Removed.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 857 bytes --]

  reply	other threads:[~2024-11-02 16:07 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-07 13:59 [PATCH ipsec-next v12 00/16] Add IP-TFS mode to xfrm Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 01/16] xfrm: config: add CONFIG_XFRM_IPTFS Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 02/16] include: uapi: add ip_tfs_*_hdr packet formats Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 03/16] include: uapi: add IPPROTO_AGGFRAG for AGGFRAG in ESP Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 04/16] xfrm: netlink: add config (netlink) options Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 05/16] xfrm: add mode_cbs module functionality Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 06/16] xfrm: add generic iptfs defines and functionality Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 07/16] xfrm: iptfs: add new iptfs xfrm mode impl Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 08/16] xfrm: iptfs: add user packet (tunnel ingress) handling Christian Hopps
2024-10-21  9:30   ` Steffen Klassert
2024-11-02 15:44     ` Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 09/16] xfrm: iptfs: share page fragments of inner packets Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 10/16] xfrm: iptfs: add fragmenting of larger than MTU user packets Christian Hopps
2024-10-21  9:38   ` Steffen Klassert
2024-11-02 15:50     ` Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 11/16] xfrm: iptfs: add basic receive packet (tunnel egress) handling Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 12/16] xfrm: iptfs: handle received fragmented inner packets Christian Hopps
2024-10-21 10:26   ` Steffen Klassert
2024-11-02 16:01     ` Christian Hopps [this message]
2024-10-07 13:59 ` [PATCH ipsec-next v12 13/16] xfrm: iptfs: add reusing received skb for the tunnel egress packet Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 14/16] xfrm: iptfs: add skb-fragment sharing code Christian Hopps
2024-10-21 10:39   ` Steffen Klassert
2024-11-02 16:26     ` Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 15/16] xfrm: iptfs: handle reordering of received packets Christian Hopps
2024-10-21  8:21   ` Steffen Klassert
2024-11-02 16:30     ` Christian Hopps
2024-10-07 13:59 ` [PATCH ipsec-next v12 16/16] xfrm: iptfs: add tracepoint functionality Christian Hopps

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=m2r07tipr1.fsf@chopps.org \
    --to=chopps@chopps.org \
    --cc=antony@phenome.org \
    --cc=chopps@labn.net \
    --cc=devel@linux-ipsec.org \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=sd@queasysnail.net \
    --cc=steffen.klassert@secunet.com \
    /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).