netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
@ 2020-08-02 19:50 Xie He
  2020-08-03  9:49 ` Willem de Bruijn
  2020-08-04 12:43 ` Martin Schiller
  0 siblings, 2 replies; 8+ messages in thread
From: Xie He @ 2020-08-02 19:50 UTC (permalink / raw)
  To: David S. Miller, Jakub Kicinski, netdev, linux-kernel, linux-x25
  Cc: Xie He, Willem de Bruijn, Brian Norris

In net/packet/af_packet.c, the function packet_snd first reserves a
headroom of length (dev->hard_header_len + dev->needed_headroom).
Then if the socket is a SOCK_DGRAM socket, it calls dev_hard_header,
which calls dev->header_ops->create, to create the link layer header.
If the socket is a SOCK_RAW socket, it "un-reserves" a headroom of
length (dev->hard_header_len), and assumes the user to provide the
appropriate link layer header.

So according to the logic of af_packet.c, dev->hard_header_len should
be the length of the header that would be created by
dev->header_ops->create.

However, this driver doesn't provide dev->header_ops, so logically
dev->hard_header_len should be 0.

So we should use dev->needed_headroom instead of dev->hard_header_len
to request necessary headroom to be allocated.

This change fixes kernel panic when this driver is used with AF_PACKET
SOCK_RAW sockets. Call stack when panic:

[  168.399197] skbuff: skb_under_panic: text:ffffffff819d95fb len:20
put:14 head:ffff8882704c0a00 data:ffff8882704c09fd tail:0x11 end:0xc0
dev:veth0
...
[  168.399255] Call Trace:
[  168.399259]  skb_push.cold+0x14/0x24
[  168.399262]  eth_header+0x2b/0xc0
[  168.399267]  lapbeth_data_transmit+0x9a/0xb0 [lapbether]
[  168.399275]  lapb_data_transmit+0x22/0x2c [lapb]
[  168.399277]  lapb_transmit_buffer+0x71/0xb0 [lapb]
[  168.399279]  lapb_kick+0xe3/0x1c0 [lapb]
[  168.399281]  lapb_data_request+0x76/0xc0 [lapb]
[  168.399283]  lapbeth_xmit+0x56/0x90 [lapbether]
[  168.399286]  dev_hard_start_xmit+0x91/0x1f0
[  168.399289]  ? irq_init_percpu_irqstack+0xc0/0x100
[  168.399291]  __dev_queue_xmit+0x721/0x8e0
[  168.399295]  ? packet_parse_headers.isra.0+0xd2/0x110
[  168.399297]  dev_queue_xmit+0x10/0x20
[  168.399298]  packet_sendmsg+0xbf0/0x19b0
......

Additional change:
When sending, check skb->len to ensure the 1-byte pseudo header is
present before reading it.

Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Cc: Brian Norris <briannorris@chromium.org>
Signed-off-by: Xie He <xie.he.0141@gmail.com>
---

Change from v2:
Added skb->len check when sending.

Change from v1:
None

---
 drivers/net/wan/lapbether.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index b2868433718f..8a3f7ba36f7e 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -157,6 +157,9 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
 	if (!netif_running(dev))
 		goto drop;
 
+	if (skb->len < 1)
+		goto drop;
+
 	switch (skb->data[0]) {
 	case X25_IFACE_DATA:
 		break;
@@ -305,6 +308,7 @@ static void lapbeth_setup(struct net_device *dev)
 	dev->netdev_ops	     = &lapbeth_netdev_ops;
 	dev->needs_free_netdev = true;
 	dev->type            = ARPHRD_X25;
+	dev->hard_header_len = 0;
 	dev->mtu             = 1000;
 	dev->addr_len        = 0;
 }
@@ -331,7 +335,8 @@ static int lapbeth_new_device(struct net_device *dev)
 	 * then this driver prepends a length field of 2 bytes,
 	 * then the underlying Ethernet device prepends its own header.
 	 */
-	ndev->hard_header_len = -1 + 3 + 2 + dev->hard_header_len;
+	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
+					   + dev->needed_headroom;
 
 	lapbeth = netdev_priv(ndev);
 	lapbeth->axdev = ndev;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-02 19:50 [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len Xie He
@ 2020-08-03  9:49 ` Willem de Bruijn
  2020-08-03 17:25   ` Xie He
  2020-08-04 12:43 ` Martin Schiller
  1 sibling, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2020-08-03  9:49 UTC (permalink / raw)
  To: Xie He
  Cc: David S. Miller, Jakub Kicinski, Network Development,
	linux-kernel, Linux X25, Willem de Bruijn, Brian Norris

On Sun, Aug 2, 2020 at 9:51 PM Xie He <xie.he.0141@gmail.com> wrote:
>
> In net/packet/af_packet.c, the function packet_snd first reserves a
> headroom of length (dev->hard_header_len + dev->needed_headroom).
> Then if the socket is a SOCK_DGRAM socket, it calls dev_hard_header,
> which calls dev->header_ops->create, to create the link layer header.
> If the socket is a SOCK_RAW socket, it "un-reserves" a headroom of
> length (dev->hard_header_len), and assumes the user to provide the
> appropriate link layer header.
>
> So according to the logic of af_packet.c, dev->hard_header_len should
> be the length of the header that would be created by
> dev->header_ops->create.
>
> However, this driver doesn't provide dev->header_ops, so logically
> dev->hard_header_len should be 0.
>
> So we should use dev->needed_headroom instead of dev->hard_header_len
> to request necessary headroom to be allocated.
>
> This change fixes kernel panic when this driver is used with AF_PACKET
> SOCK_RAW sockets. Call stack when panic:
>
> [  168.399197] skbuff: skb_under_panic: text:ffffffff819d95fb len:20
> put:14 head:ffff8882704c0a00 data:ffff8882704c09fd tail:0x11 end:0xc0
> dev:veth0
> ...
> [  168.399255] Call Trace:
> [  168.399259]  skb_push.cold+0x14/0x24
> [  168.399262]  eth_header+0x2b/0xc0
> [  168.399267]  lapbeth_data_transmit+0x9a/0xb0 [lapbether]
> [  168.399275]  lapb_data_transmit+0x22/0x2c [lapb]
> [  168.399277]  lapb_transmit_buffer+0x71/0xb0 [lapb]
> [  168.399279]  lapb_kick+0xe3/0x1c0 [lapb]
> [  168.399281]  lapb_data_request+0x76/0xc0 [lapb]
> [  168.399283]  lapbeth_xmit+0x56/0x90 [lapbether]
> [  168.399286]  dev_hard_start_xmit+0x91/0x1f0
> [  168.399289]  ? irq_init_percpu_irqstack+0xc0/0x100
> [  168.399291]  __dev_queue_xmit+0x721/0x8e0
> [  168.399295]  ? packet_parse_headers.isra.0+0xd2/0x110
> [  168.399297]  dev_queue_xmit+0x10/0x20
> [  168.399298]  packet_sendmsg+0xbf0/0x19b0
> ......
>
> Additional change:
> When sending, check skb->len to ensure the 1-byte pseudo header is
> present before reading it.
>
> Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> Cc: Brian Norris <briannorris@chromium.org>
> Signed-off-by: Xie He <xie.he.0141@gmail.com>

Overall, looks great. A  few nits.

It's [PATCH net v3], not [net v3]

> diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
> index b2868433718f..8a3f7ba36f7e 100644
> --- a/drivers/net/wan/lapbether.c
> +++ b/drivers/net/wan/lapbether.c
> @@ -157,6 +157,9 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
>         if (!netif_running(dev))
>                 goto drop;
>
> +       if (skb->len < 1)
> +               goto drop;
> +

Might be worth a comment along the lines of: /* upper layers pass a
control byte. must validate pf_packet input */

>         switch (skb->data[0]) {
>         case X25_IFACE_DATA:
>                 break;
> @@ -305,6 +308,7 @@ static void lapbeth_setup(struct net_device *dev)
>         dev->netdev_ops      = &lapbeth_netdev_ops;
>         dev->needs_free_netdev = true;
>         dev->type            = ARPHRD_X25;
> +       dev->hard_header_len = 0;

Technically not needed. The struct is allocated with kvzalloc, z for
__GFP_ZERO. Fine to leave if intended as self-describing comment, of
course.

>         dev->mtu             = 1000;
>         dev->addr_len        = 0;
>  }
> @@ -331,7 +335,8 @@ static int lapbeth_new_device(struct net_device *dev)
>          * then this driver prepends a length field of 2 bytes,
>          * then the underlying Ethernet device prepends its own header.
>          */
> -       ndev->hard_header_len = -1 + 3 + 2 + dev->hard_header_len;
> +       ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
> +                                          + dev->needed_headroom;
>
>         lapbeth = netdev_priv(ndev);
>         lapbeth->axdev = ndev;
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-03  9:49 ` Willem de Bruijn
@ 2020-08-03 17:25   ` Xie He
  0 siblings, 0 replies; 8+ messages in thread
From: Xie He @ 2020-08-03 17:25 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: David S. Miller, Jakub Kicinski, Network Development,
	linux-kernel, Linux X25, Brian Norris

Thanks!

On Mon, Aug 3, 2020 at 2:50 AM Willem de Bruijn
<willemdebruijn.kernel@gmail.com> wrote:
>
> It's [PATCH net v3], not [net v3]

Sorry. My mistake. I'll pay attention next time.

I'm currently thinking about changing the subject to reflect that we
added a "skb->len" check. Should I number the new patch as v1 or
continue to number it as v4?

> > +       if (skb->len < 1)
> > +               goto drop;
> > +
>
> Might be worth a comment along the lines of: /* upper layers pass a
> control byte. must validate pf_packet input */

OK. I'll add the comment before it to make its meaning clearer.

> > +       dev->hard_header_len = 0;
>
> Technically not needed. The struct is allocated with kvzalloc, z for
> __GFP_ZERO. Fine to leave if intended as self-describing comment, of
> course.

Thanks for pointing out! I think I can leave it as a self-describing comment.

Thanks!

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-02 19:50 [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len Xie He
  2020-08-03  9:49 ` Willem de Bruijn
@ 2020-08-04 12:43 ` Martin Schiller
  2020-08-04 19:20   ` Xie He
  1 sibling, 1 reply; 8+ messages in thread
From: Martin Schiller @ 2020-08-04 12:43 UTC (permalink / raw)
  To: Xie He
  Cc: David S. Miller, Jakub Kicinski, netdev, linux-kernel, linux-x25,
	Willem de Bruijn, Brian Norris, netdev-owner

On 2020-08-02 21:50, Xie He wrote:
> In net/packet/af_packet.c, the function packet_snd first reserves a
> headroom of length (dev->hard_header_len + dev->needed_headroom).
> Then if the socket is a SOCK_DGRAM socket, it calls dev_hard_header,
> which calls dev->header_ops->create, to create the link layer header.
> If the socket is a SOCK_RAW socket, it "un-reserves" a headroom of
> length (dev->hard_header_len), and assumes the user to provide the
> appropriate link layer header.
> 
> So according to the logic of af_packet.c, dev->hard_header_len should
> be the length of the header that would be created by
> dev->header_ops->create.
> 
> However, this driver doesn't provide dev->header_ops, so logically
> dev->hard_header_len should be 0.
> 
> So we should use dev->needed_headroom instead of dev->hard_header_len
> to request necessary headroom to be allocated.

I'm not an expert in the field, but after reading the commit message and
the previous comments, I'd say that makes sense.

> 
> This change fixes kernel panic when this driver is used with AF_PACKET
> SOCK_RAW sockets. Call stack when panic:
> 
> [  168.399197] skbuff: skb_under_panic: text:ffffffff819d95fb len:20
> put:14 head:ffff8882704c0a00 data:ffff8882704c09fd tail:0x11 end:0xc0
> dev:veth0
> ...
> [  168.399255] Call Trace:
> [  168.399259]  skb_push.cold+0x14/0x24
> [  168.399262]  eth_header+0x2b/0xc0
> [  168.399267]  lapbeth_data_transmit+0x9a/0xb0 [lapbether]
> [  168.399275]  lapb_data_transmit+0x22/0x2c [lapb]
> [  168.399277]  lapb_transmit_buffer+0x71/0xb0 [lapb]
> [  168.399279]  lapb_kick+0xe3/0x1c0 [lapb]
> [  168.399281]  lapb_data_request+0x76/0xc0 [lapb]
> [  168.399283]  lapbeth_xmit+0x56/0x90 [lapbether]
> [  168.399286]  dev_hard_start_xmit+0x91/0x1f0
> [  168.399289]  ? irq_init_percpu_irqstack+0xc0/0x100
> [  168.399291]  __dev_queue_xmit+0x721/0x8e0
> [  168.399295]  ? packet_parse_headers.isra.0+0xd2/0x110
> [  168.399297]  dev_queue_xmit+0x10/0x20
> [  168.399298]  packet_sendmsg+0xbf0/0x19b0
> ......

Shouldn't this kernel panic be intercepted by a skb_cow() before the
skb_push() in lapbeth_data_transmit()?

> 
> Additional change:
> When sending, check skb->len to ensure the 1-byte pseudo header is
> present before reading it.
> 
> Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
> Cc: Brian Norris <briannorris@chromium.org>
> Signed-off-by: Xie He <xie.he.0141@gmail.com>
> ---
> 
> Change from v2:
> Added skb->len check when sending.
> 
> Change from v1:
> None
> 
> ---
>  drivers/net/wan/lapbether.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
> index b2868433718f..8a3f7ba36f7e 100644
> --- a/drivers/net/wan/lapbether.c
> +++ b/drivers/net/wan/lapbether.c
> @@ -157,6 +157,9 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff 
> *skb,
>  	if (!netif_running(dev))
>  		goto drop;
> 
> +	if (skb->len < 1)
> +		goto drop;
> +
>  	switch (skb->data[0]) {
>  	case X25_IFACE_DATA:
>  		break;
> @@ -305,6 +308,7 @@ static void lapbeth_setup(struct net_device *dev)
>  	dev->netdev_ops	     = &lapbeth_netdev_ops;
>  	dev->needs_free_netdev = true;
>  	dev->type            = ARPHRD_X25;
> +	dev->hard_header_len = 0;
>  	dev->mtu             = 1000;
>  	dev->addr_len        = 0;
>  }
> @@ -331,7 +335,8 @@ static int lapbeth_new_device(struct net_device 
> *dev)
>  	 * then this driver prepends a length field of 2 bytes,
>  	 * then the underlying Ethernet device prepends its own header.
>  	 */
> -	ndev->hard_header_len = -1 + 3 + 2 + dev->hard_header_len;
> +	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
> +					   + dev->needed_headroom;
> 
>  	lapbeth = netdev_priv(ndev);
>  	lapbeth->axdev = ndev;


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-04 12:43 ` Martin Schiller
@ 2020-08-04 19:20   ` Xie He
  2020-08-05  5:23     ` Martin Schiller
  0 siblings, 1 reply; 8+ messages in thread
From: Xie He @ 2020-08-04 19:20 UTC (permalink / raw)
  To: Martin Schiller
  Cc: David S. Miller, Jakub Kicinski, Linux Kernel Network Developers,
	LKML, Linux X25, Willem de Bruijn, Brian Norris, netdev-owner

On Tue, Aug 4, 2020 at 5:43 AM Martin Schiller <ms@dev.tdt.de> wrote:
>
> I'm not an expert in the field, but after reading the commit message and
> the previous comments, I'd say that makes sense.

Thanks!

> Shouldn't this kernel panic be intercepted by a skb_cow() before the
> skb_push() in lapbeth_data_transmit()?

When a skb is passing down a protocol stack for transmission, there
might be several different skb_push calls to prepend different
headers. It would be the best (in terms of performance) if we can
allocate the needed header space in advance, so that we don't need to
reallocate the skb every time a new header needs to be prepended.
Adding skb_cow before these skb_push calls would indeed help
preventing kernel panics, but that might not be the essential issue
here, and it might also prevent us from discovering the real issue. (I
guess this is also the reason skb_cow is not included in skb_push
itself.)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-04 19:20   ` Xie He
@ 2020-08-05  5:23     ` Martin Schiller
  2020-08-05  8:57       ` Xie He
  0 siblings, 1 reply; 8+ messages in thread
From: Martin Schiller @ 2020-08-05  5:23 UTC (permalink / raw)
  To: Xie He
  Cc: David S. Miller, Jakub Kicinski, Linux Kernel Network Developers,
	LKML, Linux X25, Willem de Bruijn, Brian Norris, netdev-owner

On 2020-08-04 21:20, Xie He wrote:
> On Tue, Aug 4, 2020 at 5:43 AM Martin Schiller <ms@dev.tdt.de> wrote:
>> 
>> I'm not an expert in the field, but after reading the commit message 
>> and
>> the previous comments, I'd say that makes sense.
> 
> Thanks!
> 
>> Shouldn't this kernel panic be intercepted by a skb_cow() before the
>> skb_push() in lapbeth_data_transmit()?
> 
> When a skb is passing down a protocol stack for transmission, there
> might be several different skb_push calls to prepend different
> headers. It would be the best (in terms of performance) if we can
> allocate the needed header space in advance, so that we don't need to
> reallocate the skb every time a new header needs to be prepended.

Yes, I agree.

> Adding skb_cow before these skb_push calls would indeed help
> preventing kernel panics, but that might not be the essential issue
> here, and it might also prevent us from discovering the real issue. (I
> guess this is also the reason skb_cow is not included in skb_push
> itself.)

Well, you are right that the panic is "useful" to discover the real
problem. But on the other hand, if it is possible to prevent a panic, I
think we should do so. Maybe with adding a warning, when skb_cow() needs
to reallocate memory.

But this is getting a little bit off topic. For this patch I can say:

LGTM.

Reviewed-by: Martin Schiller <ms@dev.tdt.de>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-05  5:23     ` Martin Schiller
@ 2020-08-05  8:57       ` Xie He
  2020-08-05  9:33         ` Willem de Bruijn
  0 siblings, 1 reply; 8+ messages in thread
From: Xie He @ 2020-08-05  8:57 UTC (permalink / raw)
  To: Martin Schiller
  Cc: David S. Miller, Jakub Kicinski, Linux Kernel Network Developers,
	LKML, Linux X25, Willem de Bruijn, Brian Norris, netdev-owner

On Tue, Aug 4, 2020 at 10:23 PM Martin Schiller <ms@dev.tdt.de> wrote:
>
> > Adding skb_cow before these skb_push calls would indeed help
> > preventing kernel panics, but that might not be the essential issue
> > here, and it might also prevent us from discovering the real issue. (I
> > guess this is also the reason skb_cow is not included in skb_push
> > itself.)
>
> Well, you are right that the panic is "useful" to discover the real
> problem. But on the other hand, if it is possible to prevent a panic, I
> think we should do so. Maybe with adding a warning, when skb_cow() needs
> to reallocate memory.
>
> But this is getting a little bit off topic. For this patch I can say:
>
> LGTM.
>
> Reviewed-by: Martin Schiller <ms@dev.tdt.de>

Thank you so much!

Yes, it might be better to use skb_cow with a warning so that we can
prevent kernel panic while still being able to discover the problem.
If we want to do this, there are 2 more places in addition to
lapbeth_data_transmit that need to be guarded with skb_cow:
lapb_send_iframe and lapb_transmit_buffer in net/lapb/lapb_out.c.
Maybe we can address this in a separate patch.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len
  2020-08-05  8:57       ` Xie He
@ 2020-08-05  9:33         ` Willem de Bruijn
  0 siblings, 0 replies; 8+ messages in thread
From: Willem de Bruijn @ 2020-08-05  9:33 UTC (permalink / raw)
  To: Xie He
  Cc: Martin Schiller, David S. Miller, Jakub Kicinski,
	Linux Kernel Network Developers, LKML, Linux X25,
	Willem de Bruijn, Brian Norris, netdev-owner

On Wed, Aug 5, 2020 at 10:57 AM Xie He <xie.he.0141@gmail.com> wrote:
>
> On Tue, Aug 4, 2020 at 10:23 PM Martin Schiller <ms@dev.tdt.de> wrote:
> >
> > > Adding skb_cow before these skb_push calls would indeed help
> > > preventing kernel panics, but that might not be the essential issue
> > > here, and it might also prevent us from discovering the real issue. (I
> > > guess this is also the reason skb_cow is not included in skb_push
> > > itself.)
> >
> > Well, you are right that the panic is "useful" to discover the real
> > problem. But on the other hand, if it is possible to prevent a panic, I
> > think we should do so. Maybe with adding a warning, when skb_cow() needs
> > to reallocate memory.
> >
> > But this is getting a little bit off topic. For this patch I can say:
> >
> > LGTM.
> >
> > Reviewed-by: Martin Schiller <ms@dev.tdt.de>
>
> Thank you so much!
>
> Yes, it might be better to use skb_cow with a warning so that we can
> prevent kernel panic while still being able to discover the problem.

Let's not add defenses to work around possibly buggy code. In the long
run that reduces code quality. Instead, fix bugs at the source.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-08-05  9:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-02 19:50 [net v3] drivers/net/wan/lapbether: Use needed_headroom instead of hard_header_len Xie He
2020-08-03  9:49 ` Willem de Bruijn
2020-08-03 17:25   ` Xie He
2020-08-04 12:43 ` Martin Schiller
2020-08-04 19:20   ` Xie He
2020-08-05  5:23     ` Martin Schiller
2020-08-05  8:57       ` Xie He
2020-08-05  9:33         ` Willem de Bruijn

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).