]>
Commit | Line | Data |
---|---|---|
aa8edcb9 CW |
1 | From 6000afc70ddd62a24cf3aa636b066f518157998c Mon Sep 17 00:00:00 2001 |
2 | Message-Id: <20080609.134337.193698173.davem@davemloft.net> | |
3 | From: James Chapman <jchapman@katalix.com> | |
4 | Date: Mon, 9 Jun 2008 13:34:39 -0700 | |
5 | Subject: l2tp: Fix possible WARN_ON from socket code when UDP socket is closed | |
6 | ||
7 | From: James Chapman <jchapman@katalix.com> | |
8 | ||
9 | [ upstream commit: 199f7d24ae59894243687a234a909f44a8724506 ] | |
10 | ||
11 | If an L2TP daemon closes a tunnel socket while packets are queued in | |
12 | the tunnel's reorder queue, a kernel warning is logged because the | |
13 | socket is closed while skbs are still referencing it. The fix is to | |
14 | purge the queue in the socket's release handler. | |
15 | ||
16 | WARNING: at include/net/sock.h:351 udp_lib_unhash+0x41/0x68() | |
17 | Pid: 12998, comm: openl2tpd Not tainted 2.6.25 #8 | |
18 | [<c0423c58>] warn_on_slowpath+0x41/0x51 | |
19 | [<c05d33a7>] udp_lib_unhash+0x41/0x68 | |
20 | [<c059424d>] sk_common_release+0x23/0x90 | |
21 | [<c05d16be>] udp_lib_close+0x8/0xa | |
22 | [<c05d8684>] inet_release+0x42/0x48 | |
23 | [<c0592599>] sock_release+0x14/0x60 | |
24 | [<c059299f>] sock_close+0x29/0x30 | |
25 | [<c046ef52>] __fput+0xad/0x15b | |
26 | [<c046f1d9>] fput+0x17/0x19 | |
27 | [<c046c8c4>] filp_close+0x50/0x5a | |
28 | [<c046da06>] sys_close+0x69/0x9f | |
29 | [<c04048ce>] syscall_call+0x7/0xb | |
30 | ||
31 | Signed-off-by: James Chapman <jchapman@katalix.com> | |
32 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
33 | Signed-off-by: Chris Wright <chrisw@sous-sol.org> | |
34 | --- | |
35 | drivers/net/pppol2tp.c | 10 ++++++++++ | |
36 | 1 file changed, 10 insertions(+) | |
37 | ||
38 | --- a/drivers/net/pppol2tp.c | |
39 | +++ b/drivers/net/pppol2tp.c | |
40 | @@ -1279,6 +1279,7 @@ out: | |
41 | static int pppol2tp_release(struct socket *sock) | |
42 | { | |
43 | struct sock *sk = sock->sk; | |
44 | + struct pppol2tp_session *session; | |
45 | int error; | |
46 | ||
47 | if (!sk) | |
48 | @@ -1296,9 +1297,18 @@ static int pppol2tp_release(struct socke | |
49 | sock_orphan(sk); | |
50 | sock->sk = NULL; | |
51 | ||
52 | + session = pppol2tp_sock_to_session(sk); | |
53 | + | |
54 | /* Purge any queued data */ | |
55 | skb_queue_purge(&sk->sk_receive_queue); | |
56 | skb_queue_purge(&sk->sk_write_queue); | |
57 | + if (session != NULL) { | |
58 | + struct sk_buff *skb; | |
59 | + while ((skb = skb_dequeue(&session->reorder_q))) { | |
60 | + kfree_skb(skb); | |
61 | + sock_put(sk); | |
62 | + } | |
63 | + } | |
64 | ||
65 | release_sock(sk); | |
66 |