diff mbox

appletalk: Set skb with destructor

Message ID 1404647816-7564-1-git-send-email-andrey.krieger.utkin@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Andrey Utkin July 6, 2014, 11:56 a.m. UTC
The sock ref counting is off so there is a kernel panic when you run
`atalkd`.  See https://bugzilla.kernel.org/show_bug.cgi?id=79441
This fix is similar to 0ae89beb283a ('can: add destructor for self
generated skbs')

Reported-by: Ed Martin <edman007@edman007.com>
Signed-off-by: Andrey Utkin <andrey.krieger.utkin@gmail.com>
---
 net/appletalk/ddp.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Eric Dumazet July 6, 2014, 9:42 p.m. UTC | #1
On Sun, 2014-07-06 at 14:56 +0300, Andrey Utkin wrote:
> The sock ref counting is off so there is a kernel panic when you run
> `atalkd`.  See https://bugzilla.kernel.org/show_bug.cgi?id=79441
> This fix is similar to 0ae89beb283a ('can: add destructor for self
> generated skbs')
>  should
> Reported-by: Ed Martin <edman007@edman007.com>
> Signed-off-by: Andrey Utkin <andrey.krieger.utkin@gmail.com>
> ---
>  net/appletalk/ddp.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
> index 01a1082..3d8ab34 100644
> --- a/net/appletalk/ddp.c
> +++ b/net/appletalk/ddp.c
> @@ -1399,6 +1399,11 @@ drop:
>  	return NET_RX_DROP;
>  }
>  
> +static inline void atalk_skb_destructor(struct sk_buff *skb)
> +{
> +	sock_put(skb->sk);
> +}
> +
>  /**
>   *	atalk_rcv - Receive a packet (in skb) from device dev
>   *	@skb - packet received
> @@ -1489,6 +1494,8 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
>  		goto drop;
>  
>  	/* Queue packet (standard) */
> +	sock_hold(sock);
> +	skb->destructor = atalk_skb_destructor;
>  	skb->sk = sock;

This part is not needed : sock_queue_rcv_skb() already does the right
thing : It calls skb_set_owner_r(skb, sk);

You should therefore remove the "skb->sk = sock;" line

>  
>  	if (sock_queue_rcv_skb(sock, skb) < 0)
> @@ -1644,6 +1651,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
>  	if (!skb)
>  		goto out;
>  
> +	sock_hold(sk);
> +	skb->destructor = atalk_skb_destructor;
>  	skb->sk = sk;
>  	skb_reserve(skb, ddp_dl->header_length);
>  	skb_reserve(skb, dev->hard_header_len);


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andrey Utkin July 7, 2014, 8:03 a.m. UTC | #2
2014-07-07 0:42 GMT+03:00 Eric Dumazet <eric.dumazet@gmail.com>:
>>       /* Queue packet (standard) */
>> +     sock_hold(sock);
>> +     skb->destructor = atalk_skb_destructor;
>>       skb->sk = sock;
>
> This part is not needed : sock_queue_rcv_skb() already does the right
> thing : It calls skb_set_owner_r(skb, sk);
>
> You should therefore remove the "skb->sk = sock;" line

If it is so, i think this should be as another patch with its own reasoning.
Eric Dumazet July 7, 2014, 8:57 a.m. UTC | #3
On Mon, 2014-07-07 at 11:03 +0300, Andrey Utkin wrote:
> 2014-07-07 0:42 GMT+03:00 Eric Dumazet <eric.dumazet@gmail.com>:
> >>       /* Queue packet (standard) */
> >> +     sock_hold(sock);
> >> +     skb->destructor = atalk_skb_destructor;
> >>       skb->sk = sock;
> >
> > This part is not needed : sock_queue_rcv_skb() already does the right
> > thing : It calls skb_set_owner_r(skb, sk);
> >
> > You should therefore remove the "skb->sk = sock;" line
> 
> If it is so, i think this should be as another patch with its own reasoning.
> 

No it is not.

Its illegal to set skb->sk to a socket without taking proper reference.

But it is useless to do this before calling sock_queue_rcv_skb(), as I
explained to you.

This is adding two extra atomic operations for nothing: skb_orphan() is
called from sock_queue_rcv_skb(), so it is kind of stupid to set a
destructor that _will_ be immediately called.

We do not do defensive programming, we try to do logical things, and
only logical things.

Please re-spin your patch, by integrating my feedback.

Thanks !


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric Dumazet July 7, 2014, 9:26 a.m. UTC | #4
On Mon, 2014-07-07 at 10:57 +0200, Eric Dumazet wrote:
> On Mon, 2014-07-07 at 11:03 +0300, Andrey Utkin wrote:
> > 2014-07-07 0:42 GMT+03:00 Eric Dumazet <eric.dumazet@gmail.com>:
> > >>       /* Queue packet (standard) */
> > >> +     sock_hold(sock);
> > >> +     skb->destructor = atalk_skb_destructor;
> > >>       skb->sk = sock;
> > >
> > > This part is not needed : sock_queue_rcv_skb() already does the right
> > > thing : It calls skb_set_owner_r(skb, sk);
> > >
> > > You should therefore remove the "skb->sk = sock;" line
> > 
> > If it is so, i think this should be as another patch with its own reasoning.
> > 
> 
> No it is not.
> 
> Its illegal to set skb->sk to a socket without taking proper reference.
> 
> But it is useless to do this before calling sock_queue_rcv_skb(), as I
> explained to you.
> 
> This is adding two extra atomic operations for nothing: skb_orphan() is
> called from sock_queue_rcv_skb(), so it is kind of stupid to set a
> destructor that _will_ be immediately called.
> 
> We do not do defensive programming, we try to do logical things, and
> only logical things.
> 
> Please re-spin your patch, by integrating my feedback.
> 
> Thanks !

Reading again this code, I think all you need is to remove the 2 buggy
lines.

No need for setup destructors.



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andrey Utkin July 7, 2014, 10:02 a.m. UTC | #5
2014-07-07 12:26 GMT+03:00 Eric Dumazet <eric.dumazet@gmail.com>:
> Reading again this code, I think all you need is to remove the 2 buggy
> lines.
>
> No need for setup destructors.

Reviewing the code again, i find you're right and adding a destructor
in that place is stupid, and just not setting skb->sk would make bug
disappear, assuming skb->sk is previously NULL.
And what about the second case, at ddp.c near line 1650? Is destructor
needed here?
diff mbox

Patch

diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 01a1082..3d8ab34 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1399,6 +1399,11 @@  drop:
 	return NET_RX_DROP;
 }
 
+static inline void atalk_skb_destructor(struct sk_buff *skb)
+{
+	sock_put(skb->sk);
+}
+
 /**
  *	atalk_rcv - Receive a packet (in skb) from device dev
  *	@skb - packet received
@@ -1489,6 +1494,8 @@  static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
 		goto drop;
 
 	/* Queue packet (standard) */
+	sock_hold(sock);
+	skb->destructor = atalk_skb_destructor;
 	skb->sk = sock;
 
 	if (sock_queue_rcv_skb(sock, skb) < 0)
@@ -1644,6 +1651,8 @@  static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	if (!skb)
 		goto out;
 
+	sock_hold(sk);
+	skb->destructor = atalk_skb_destructor;
 	skb->sk = sk;
 	skb_reserve(skb, ddp_dl->header_length);
 	skb_reserve(skb, dev->hard_header_len);