All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vlad Yasevich <vyasevich@gmail.com>
To: "Michael S. Tsirkin" <mst@redhat.com>, Jason Wang <jasowang@redhat.com>
Cc: davem@davemloft.net, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Subject: Re: [PATCH net 1/2] tun: unbreak truncated packet signalling
Date: Mon, 09 Dec 2013 10:31:10 -0500	[thread overview]
Message-ID: <52A5E23E.9030604@gmail.com> (raw)
In-Reply-To: <20131209105529.GD15055@redhat.com>

On 12/09/2013 05:55 AM, Michael S. Tsirkin wrote:
> On Mon, Dec 09, 2013 at 06:25:16PM +0800, Jason Wang wrote:
>> Commit 6680ec68eff47d36f67b4351bc9836fd6cba9532
>> (tuntap: hardware vlan tx support) breaks the truncated packet signal
by never
>> return a length greater than iov length in tun_put_user(). This patch
fixes this
>> by always return the length of packet plus possible vlan header.
Caller can
>> detect the truncated packet by comparing the return value and the
size of iov
>> length.
>>
>> Reported-by: Vlad Yasevich <vyasevich@gmail.com>
>> Cc: Vlad Yasevich <vyasevich@gmail.com>
>> Cc: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
>> Signed-off-by: Jason Wang <jasowang@redhat.com>
>
> So writer gets back a value greater than what was written?
>
>> ---
>> The patch is needed for stable.
>> ---
>>  drivers/net/tun.c | 23 ++++++++++++-----------
>>  1 file changed, 12 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
>> index e26cbea..dd1bd7a 100644
>> --- a/drivers/net/tun.c
>> +++ b/drivers/net/tun.c
>> @@ -1183,7 +1183,11 @@ static ssize_t tun_put_user(struct tun_struct
*tun,
>>  			    const struct iovec *iv, int len)
>>  {
>>  	struct tun_pi pi = { 0, skb->protocol };
>> -	ssize_t total = 0;
>> +	struct {
>> +		__be16 h_vlan_proto;
>> +		__be16 h_vlan_TCI;
>> +	} veth;
>> +	ssize_t total = 0, off = 0;
>
> Why off = 0 here?
> We initialize it to total unconditionally, don't we?
>
>>  	int vlan_offset = 0;
>>
>>  	if (!(tun->flags & TUN_NO_PI)) {
>> @@ -1248,14 +1252,11 @@ static ssize_t tun_put_user(struct tun_struct
*tun,
>>  		total += tun->vnet_hdr_sz;
>>  	}
>>
>> +	off = total;
>>  	if (!vlan_tx_tag_present(skb)) {
>>  		len = min_t(int, skb->len, len);
>>  	} else {
>>  		int copy, ret;
>> -		struct {
>> -			__be16 h_vlan_proto;
>> -			__be16 h_vlan_TCI;
>> -		} veth;
>>
>>  		veth.h_vlan_proto = skb->vlan_proto;
>>  		veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
>> @@ -1264,22 +1265,22 @@ static ssize_t tun_put_user(struct tun_struct
*tun,
>>  		len = min_t(int, skb->len + VLAN_HLEN, len);
>>
>>  		copy = min_t(int, vlan_offset, len);
>> -		ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
>> +		ret = skb_copy_datagram_const_iovec(skb, 0, iv, off, copy);
>>  		len -= copy;
>> -		total += copy;
>> +		off += copy;
>>  		if (ret || !len)
>>  			goto done;
>>
>>  		copy = min_t(int, sizeof(veth), len);
>> -		ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
>> +		ret = memcpy_toiovecend(iv, (void *)&veth, off, copy);
>>  		len -= copy;
>> -		total += copy;
>> +		off += copy;
>>  		if (ret || !len)
>>  			goto done;
>
> This seems wrong: if one of the branches above is taken, total is
> never incremented.
>
>>  	}
>>
>> -	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
>> -	total += len;
>> +	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, off, len);
>> +	total += skb->len + (vlan_offset ? sizeof(veth) : 0);
>>
>>  done:
>>  	tun->dev->stats.tx_packets++;
>
> I also think it's inelegant that the veth struct is now in the
> outside scope, and the extra ? is also ugly.
>
> Here's a smaller patch to fix all these problems - what do you think?
>
>
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
> ---
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 782e38b..3297e41 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1183,7 +1183,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
>  			    const struct iovec *iv, int len)
>  {
>  	struct tun_pi pi = { 0, skb->protocol };
> -	ssize_t total = 0;
> +	ssize_t total = 0, offset;
>  	int vlan_offset = 0;
>
>  	if (!(tun->flags & TUN_NO_PI)) {
> @@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
>  		total += tun->vnet_hdr_sz;
>  	}
>
> +	offset = total;
> +	total += skb->len;
>  	if (!vlan_tx_tag_present(skb)) {
>  		len = min_t(int, skb->len, len);
>  	} else {
> @@ -1257,6 +1259,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
>  			__be16 h_vlan_TCI;
>  		} veth;
>
> +		total += sizeof(veth);
> +
>  		veth.h_vlan_proto = skb->vlan_proto;
>  		veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
>
> @@ -1279,7 +1283,6 @@ static ssize_t tun_put_user(struct tun_struct *tun,
>  	}
>
>  	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
> -	total += len;
>
>  done:
>  	tun->dev->stats.tx_packets++;
>


You have to use 'offset' instead of 'total' when doing skb_copy and
adjust offset as you write the vlan header.

I think something like this will fix it:

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 782e38b..d71c393 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1183,7 +1183,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 			    const struct iovec *iv, int len)
 {
 	struct tun_pi pi = { 0, skb->protocol };
-	ssize_t total = 0;
+	ssize_t total = 0, offset;
 	int vlan_offset = 0;

 	if (!(tun->flags & TUN_NO_PI)) {
@@ -1248,6 +1248,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 		total += tun->vnet_hdr_sz;
 	}

+	offset = total;
+	total += skb->len;
 	if (!vlan_tx_tag_present(skb)) {
 		len = min_t(int, skb->len, len);
 	} else {
@@ -1262,24 +1264,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,

 		vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
 		len = min_t(int, skb->len + VLAN_HLEN, len);
+		total += VLAN_HLEN;

 		copy = min_t(int, vlan_offset, len);
-		ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy);
+		ret = skb_copy_datagram_const_iovec(skb, 0, iv, offset, copy);
 		len -= copy;
-		total += copy;
+		offset += copy;
 		if (ret || !len)
 			goto done;

 		copy = min_t(int, sizeof(veth), len);
-		ret = memcpy_toiovecend(iv, (void *)&veth, total, copy);
+		ret = memcpy_toiovecend(iv, (void *)&veth, offset, copy);
 		len -= copy;
-		total += copy;
+		offset += copy;
 		if (ret || !len)
 			goto done;
 	}

-	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len);
-	total += len;
+	skb_copy_datagram_const_iovec(skb, vlan_offset, iv, offset, len);

 done:
 	tun->dev->stats.tx_packets++;

-vlad

  parent reply	other threads:[~2013-12-09 15:31 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-09 10:25 [PATCH net 1/2] tun: unbreak truncated packet signalling Jason Wang
2013-12-09 10:25 ` [PATCH net 2/2] macvtap: signal truncated packets Jason Wang
2013-12-09 11:02   ` Michael S. Tsirkin
2013-12-10  5:41     ` Jason Wang
2013-12-09 10:55 ` [PATCH net 1/2] tun: unbreak truncated packet signalling Michael S. Tsirkin
2013-12-09 10:56   ` Michael S. Tsirkin
2013-12-10  5:39     ` Jason Wang
2013-12-09 15:31   ` Vlad Yasevich [this message]
2013-12-10  5:40     ` Jason Wang

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=52A5E23E.9030604@gmail.com \
    --to=vyasevich@gmail.com \
    --cc=davem@davemloft.net \
    --cc=jasowang@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=wuzhy@linux.vnet.ibm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.