diff mbox series

[Trusty,SRU,CVE-2016-8633] firewire: net: guard against rx buffer overflows

Message ID 20170907130233.30902-1-kleber.souza@canonical.com
State New
Headers show
Series [Trusty,SRU,CVE-2016-8633] firewire: net: guard against rx buffer overflows | expand

Commit Message

Kleber Sacilotto de Souza Sept. 7, 2017, 1:02 p.m. UTC
From: Stefan Richter <stefanr@s5r6.in-berlin.de>

CVE-2016-8633

The IP-over-1394 driver firewire-net lacked input validation when
handling incoming fragmented datagrams.  A maliciously formed fragment
with a respectively large datagram_offset would cause a memcpy past the
datagram buffer.

So, drop any packets carrying a fragment with offset + length larger
than datagram_size.

In addition, ensure that
  - GASP header, unfragmented encapsulation header, or fragment
    encapsulation header actually exists before we access it,
  - the encapsulated datagram or fragment is of nonzero size.

Reported-by: Eyal Itkin <eyal.itkin@gmail.com>
Reviewed-by: Eyal Itkin <eyal.itkin@gmail.com>
Fixes: CVE 2016-8633
Cc: stable@vger.kernel.org
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
(cherry picked from commit 667121ace9dbafb368618dbabcf07901c962ddac)
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
---

Notes:
    Only Trusty still needs the fix for this CVE. Cherry pick applies cleanly,
    compile tested.
    
    Kleber

 drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 35 insertions(+), 16 deletions(-)

Comments

Stefan Bader Sept. 11, 2017, 11:29 a.m. UTC | #1
On 07.09.2017 15:02, Kleber Sacilotto de Souza wrote:
> From: Stefan Richter <stefanr@s5r6.in-berlin.de>
> 
> CVE-2016-8633
> 
> The IP-over-1394 driver firewire-net lacked input validation when
> handling incoming fragmented datagrams.  A maliciously formed fragment
> with a respectively large datagram_offset would cause a memcpy past the
> datagram buffer.
> 
> So, drop any packets carrying a fragment with offset + length larger
> than datagram_size.
> 
> In addition, ensure that
>   - GASP header, unfragmented encapsulation header, or fragment
>     encapsulation header actually exists before we access it,
>   - the encapsulated datagram or fragment is of nonzero size.
> 
> Reported-by: Eyal Itkin <eyal.itkin@gmail.com>
> Reviewed-by: Eyal Itkin <eyal.itkin@gmail.com>
> Fixes: CVE 2016-8633
> Cc: stable@vger.kernel.org
> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> (cherry picked from commit 667121ace9dbafb368618dbabcf07901c962ddac)
> Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>

> ---
> 
> Notes:
>     Only Trusty still needs the fix for this CVE. Cherry pick applies cleanly,
>     compile tested.
>     
>     Kleber
> 
>  drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 35 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
> index 4af0a7bad7f2..641eeab43c57 100644
> --- a/drivers/firewire/net.c
> +++ b/drivers/firewire/net.c
> @@ -591,6 +591,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	int retval;
>  	u16 ether_type;
>  
> +	if (len <= RFC2374_UNFRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w0 = be32_to_cpu(buf[0]);
>  	lf = fwnet_get_hdr_lf(&hdr);
>  	if (lf == RFC2374_HDR_UNFRAG) {
> @@ -615,7 +618,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  		return fwnet_finish_incoming_packet(net, skb, source_node_id,
>  						    is_broadcast, ether_type);
>  	}
> +
>  	/* A datagram fragment has been received, now the fun begins. */
> +
> +	if (len <= RFC2374_FRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w1 = ntohl(buf[1]);
>  	buf += 2;
>  	len -= RFC2374_FRAG_HDR_SIZE;
> @@ -629,6 +637,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	datagram_label = fwnet_get_hdr_dgl(&hdr);
>  	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
>  
> +	if (fg_off + len > dg_size)
> +		return 0;
> +
>  	spin_lock_irqsave(&dev->lock, flags);
>  
>  	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
> @@ -735,6 +746,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
>  	fw_send_response(card, r, rcode);
>  }
>  
> +static int gasp_source_id(__be32 *p)
> +{
> +	return be32_to_cpu(p[0]) >> 16;
> +}
> +
> +static u32 gasp_specifier_id(__be32 *p)
> +{
> +	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
> +	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
> +}
> +
> +static u32 gasp_version(__be32 *p)
> +{
> +	return be32_to_cpu(p[1]) & 0xffffff;
> +}
> +
>  static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  		u32 cycle, size_t header_length, void *header, void *data)
>  {
> @@ -744,9 +771,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  	__be32 *buf_ptr;
>  	int retval;
>  	u32 length;
> -	u16 source_node_id;
> -	u32 specifier_id;
> -	u32 ver;
>  	unsigned long offset;
>  	unsigned long flags;
>  
> @@ -763,22 +787,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  
>  	spin_unlock_irqrestore(&dev->lock, flags);
>  
> -	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
> -			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
> -	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
> -	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
> -
> -	if (specifier_id == IANA_SPECIFIER_ID &&
> -	    (ver == RFC2734_SW_VERSION
> +	if (length > IEEE1394_GASP_HDR_SIZE &&
> +	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
> +	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
>  #if IS_ENABLED(CONFIG_IPV6)
> -	     || ver == RFC3146_SW_VERSION
> +	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
>  #endif
> -	    )) {
> -		buf_ptr += 2;
> -		length -= IEEE1394_GASP_HDR_SIZE;
> -		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
> +	    ))
> +		fwnet_incoming_packet(dev, buf_ptr + 2,
> +				      length - IEEE1394_GASP_HDR_SIZE,
> +				      gasp_source_id(buf_ptr),
>  				      context->card->generation, true);
> -	}
>  
>  	packet.payload_length = dev->rcv_buffer_size;
>  	packet.interrupt = 1;
>
Colin Ian King Sept. 11, 2017, 12:56 p.m. UTC | #2
On 07/09/17 14:02, Kleber Sacilotto de Souza wrote:
> From: Stefan Richter <stefanr@s5r6.in-berlin.de>
> 
> CVE-2016-8633
> 
> The IP-over-1394 driver firewire-net lacked input validation when
> handling incoming fragmented datagrams.  A maliciously formed fragment
> with a respectively large datagram_offset would cause a memcpy past the
> datagram buffer.
> 
> So, drop any packets carrying a fragment with offset + length larger
> than datagram_size.
> 
> In addition, ensure that
>   - GASP header, unfragmented encapsulation header, or fragment
>     encapsulation header actually exists before we access it,
>   - the encapsulated datagram or fragment is of nonzero size.
> 
> Reported-by: Eyal Itkin <eyal.itkin@gmail.com>
> Reviewed-by: Eyal Itkin <eyal.itkin@gmail.com>
> Fixes: CVE 2016-8633
> Cc: stable@vger.kernel.org
> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> (cherry picked from commit 667121ace9dbafb368618dbabcf07901c962ddac)
> Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
> ---
> 
> Notes:
>     Only Trusty still needs the fix for this CVE. Cherry pick applies cleanly,
>     compile tested.
>     
>     Kleber
> 
>  drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 35 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
> index 4af0a7bad7f2..641eeab43c57 100644
> --- a/drivers/firewire/net.c
> +++ b/drivers/firewire/net.c
> @@ -591,6 +591,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	int retval;
>  	u16 ether_type;
>  
> +	if (len <= RFC2374_UNFRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w0 = be32_to_cpu(buf[0]);
>  	lf = fwnet_get_hdr_lf(&hdr);
>  	if (lf == RFC2374_HDR_UNFRAG) {
> @@ -615,7 +618,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  		return fwnet_finish_incoming_packet(net, skb, source_node_id,
>  						    is_broadcast, ether_type);
>  	}
> +
>  	/* A datagram fragment has been received, now the fun begins. */
> +
> +	if (len <= RFC2374_FRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w1 = ntohl(buf[1]);
>  	buf += 2;
>  	len -= RFC2374_FRAG_HDR_SIZE;
> @@ -629,6 +637,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	datagram_label = fwnet_get_hdr_dgl(&hdr);
>  	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
>  
> +	if (fg_off + len > dg_size)
> +		return 0;
> +
>  	spin_lock_irqsave(&dev->lock, flags);
>  
>  	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
> @@ -735,6 +746,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
>  	fw_send_response(card, r, rcode);
>  }
>  
> +static int gasp_source_id(__be32 *p)
> +{
> +	return be32_to_cpu(p[0]) >> 16;
> +}
> +
> +static u32 gasp_specifier_id(__be32 *p)
> +{
> +	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
> +	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
> +}
> +
> +static u32 gasp_version(__be32 *p)
> +{
> +	return be32_to_cpu(p[1]) & 0xffffff;
> +}
> +
>  static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  		u32 cycle, size_t header_length, void *header, void *data)
>  {
> @@ -744,9 +771,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  	__be32 *buf_ptr;
>  	int retval;
>  	u32 length;
> -	u16 source_node_id;
> -	u32 specifier_id;
> -	u32 ver;
>  	unsigned long offset;
>  	unsigned long flags;
>  
> @@ -763,22 +787,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  
>  	spin_unlock_irqrestore(&dev->lock, flags);
>  
> -	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
> -			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
> -	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
> -	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
> -
> -	if (specifier_id == IANA_SPECIFIER_ID &&
> -	    (ver == RFC2734_SW_VERSION
> +	if (length > IEEE1394_GASP_HDR_SIZE &&
> +	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
> +	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
>  #if IS_ENABLED(CONFIG_IPV6)
> -	     || ver == RFC3146_SW_VERSION
> +	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
>  #endif
> -	    )) {
> -		buf_ptr += 2;
> -		length -= IEEE1394_GASP_HDR_SIZE;
> -		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
> +	    ))
> +		fwnet_incoming_packet(dev, buf_ptr + 2,
> +				      length - IEEE1394_GASP_HDR_SIZE,
> +				      gasp_source_id(buf_ptr),
>  				      context->card->generation, true);
> -	}
>  
>  	packet.payload_length = dev->rcv_buffer_size;
>  	packet.interrupt = 1;
> 
Clean cherry pick

Acked-by: Colin Ian King <colin.king@canonical.com>
Stefan Bader Sept. 15, 2017, 1:45 p.m. UTC | #3
On 07.09.2017 15:02, Kleber Sacilotto de Souza wrote:
> From: Stefan Richter <stefanr@s5r6.in-berlin.de>
> 
> CVE-2016-8633
> 
> The IP-over-1394 driver firewire-net lacked input validation when
> handling incoming fragmented datagrams.  A maliciously formed fragment
> with a respectively large datagram_offset would cause a memcpy past the
> datagram buffer.
> 
> So, drop any packets carrying a fragment with offset + length larger
> than datagram_size.
> 
> In addition, ensure that
>   - GASP header, unfragmented encapsulation header, or fragment
>     encapsulation header actually exists before we access it,
>   - the encapsulated datagram or fragment is of nonzero size.
> 
> Reported-by: Eyal Itkin <eyal.itkin@gmail.com>
> Reviewed-by: Eyal Itkin <eyal.itkin@gmail.com>
> Fixes: CVE 2016-8633
> Cc: stable@vger.kernel.org
> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
> (cherry picked from commit 667121ace9dbafb368618dbabcf07901c962ddac)
> Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
> ---
> 
> Notes:
>     Only Trusty still needs the fix for this CVE. Cherry pick applies cleanly,
>     compile tested.
>     
>     Kleber
> 
>  drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 35 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
> index 4af0a7bad7f2..641eeab43c57 100644
> --- a/drivers/firewire/net.c
> +++ b/drivers/firewire/net.c
> @@ -591,6 +591,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	int retval;
>  	u16 ether_type;
>  
> +	if (len <= RFC2374_UNFRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w0 = be32_to_cpu(buf[0]);
>  	lf = fwnet_get_hdr_lf(&hdr);
>  	if (lf == RFC2374_HDR_UNFRAG) {
> @@ -615,7 +618,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  		return fwnet_finish_incoming_packet(net, skb, source_node_id,
>  						    is_broadcast, ether_type);
>  	}
> +
>  	/* A datagram fragment has been received, now the fun begins. */
> +
> +	if (len <= RFC2374_FRAG_HDR_SIZE)
> +		return 0;
> +
>  	hdr.w1 = ntohl(buf[1]);
>  	buf += 2;
>  	len -= RFC2374_FRAG_HDR_SIZE;
> @@ -629,6 +637,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
>  	datagram_label = fwnet_get_hdr_dgl(&hdr);
>  	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
>  
> +	if (fg_off + len > dg_size)
> +		return 0;
> +
>  	spin_lock_irqsave(&dev->lock, flags);
>  
>  	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
> @@ -735,6 +746,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
>  	fw_send_response(card, r, rcode);
>  }
>  
> +static int gasp_source_id(__be32 *p)
> +{
> +	return be32_to_cpu(p[0]) >> 16;
> +}
> +
> +static u32 gasp_specifier_id(__be32 *p)
> +{
> +	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
> +	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
> +}
> +
> +static u32 gasp_version(__be32 *p)
> +{
> +	return be32_to_cpu(p[1]) & 0xffffff;
> +}
> +
>  static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  		u32 cycle, size_t header_length, void *header, void *data)
>  {
> @@ -744,9 +771,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  	__be32 *buf_ptr;
>  	int retval;
>  	u32 length;
> -	u16 source_node_id;
> -	u32 specifier_id;
> -	u32 ver;
>  	unsigned long offset;
>  	unsigned long flags;
>  
> @@ -763,22 +787,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
>  
>  	spin_unlock_irqrestore(&dev->lock, flags);
>  
> -	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
> -			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
> -	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
> -	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
> -
> -	if (specifier_id == IANA_SPECIFIER_ID &&
> -	    (ver == RFC2734_SW_VERSION
> +	if (length > IEEE1394_GASP_HDR_SIZE &&
> +	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
> +	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
>  #if IS_ENABLED(CONFIG_IPV6)
> -	     || ver == RFC3146_SW_VERSION
> +	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
>  #endif
> -	    )) {
> -		buf_ptr += 2;
> -		length -= IEEE1394_GASP_HDR_SIZE;
> -		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
> +	    ))
> +		fwnet_incoming_packet(dev, buf_ptr + 2,
> +				      length - IEEE1394_GASP_HDR_SIZE,
> +				      gasp_source_id(buf_ptr),
>  				      context->card->generation, true);
> -	}
>  
>  	packet.payload_length = dev->rcv_buffer_size;
>  	packet.interrupt = 1;
> 
Applied to Trusty master-next
diff mbox series

Patch

diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 4af0a7bad7f2..641eeab43c57 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -591,6 +591,9 @@  static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
 	int retval;
 	u16 ether_type;
 
+	if (len <= RFC2374_UNFRAG_HDR_SIZE)
+		return 0;
+
 	hdr.w0 = be32_to_cpu(buf[0]);
 	lf = fwnet_get_hdr_lf(&hdr);
 	if (lf == RFC2374_HDR_UNFRAG) {
@@ -615,7 +618,12 @@  static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
 		return fwnet_finish_incoming_packet(net, skb, source_node_id,
 						    is_broadcast, ether_type);
 	}
+
 	/* A datagram fragment has been received, now the fun begins. */
+
+	if (len <= RFC2374_FRAG_HDR_SIZE)
+		return 0;
+
 	hdr.w1 = ntohl(buf[1]);
 	buf += 2;
 	len -= RFC2374_FRAG_HDR_SIZE;
@@ -629,6 +637,9 @@  static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
 	datagram_label = fwnet_get_hdr_dgl(&hdr);
 	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */
 
+	if (fg_off + len > dg_size)
+		return 0;
+
 	spin_lock_irqsave(&dev->lock, flags);
 
 	peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation);
@@ -735,6 +746,22 @@  static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,
 	fw_send_response(card, r, rcode);
 }
 
+static int gasp_source_id(__be32 *p)
+{
+	return be32_to_cpu(p[0]) >> 16;
+}
+
+static u32 gasp_specifier_id(__be32 *p)
+{
+	return (be32_to_cpu(p[0]) & 0xffff) << 8 |
+	       (be32_to_cpu(p[1]) & 0xff000000) >> 24;
+}
+
+static u32 gasp_version(__be32 *p)
+{
+	return be32_to_cpu(p[1]) & 0xffffff;
+}
+
 static void fwnet_receive_broadcast(struct fw_iso_context *context,
 		u32 cycle, size_t header_length, void *header, void *data)
 {
@@ -744,9 +771,6 @@  static void fwnet_receive_broadcast(struct fw_iso_context *context,
 	__be32 *buf_ptr;
 	int retval;
 	u32 length;
-	u16 source_node_id;
-	u32 specifier_id;
-	u32 ver;
 	unsigned long offset;
 	unsigned long flags;
 
@@ -763,22 +787,17 @@  static void fwnet_receive_broadcast(struct fw_iso_context *context,
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8
-			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24;
-	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff;
-	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16;
-
-	if (specifier_id == IANA_SPECIFIER_ID &&
-	    (ver == RFC2734_SW_VERSION
+	if (length > IEEE1394_GASP_HDR_SIZE &&
+	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID &&
+	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION
 #if IS_ENABLED(CONFIG_IPV6)
-	     || ver == RFC3146_SW_VERSION
+	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION
 #endif
-	    )) {
-		buf_ptr += 2;
-		length -= IEEE1394_GASP_HDR_SIZE;
-		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id,
+	    ))
+		fwnet_incoming_packet(dev, buf_ptr + 2,
+				      length - IEEE1394_GASP_HDR_SIZE,
+				      gasp_source_id(buf_ptr),
 				      context->card->generation, true);
-	}
 
 	packet.payload_length = dev->rcv_buffer_size;
 	packet.interrupt = 1;