aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet
diff options
context:
space:
mode:
authorRémi Denis-Courmont <remi.denis-courmont@nokia.com>2010-09-15 08:19:53 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-16 00:31:31 -0400
commit6482f554e2b9cbe733d63124765104f29cf0c9ad (patch)
tree464efc6726b6c183f820152edd14f03dda4a59ad /net/phonet
parent7fedd7e5dfeb0f6bd69ee120b5c44a5e49892e47 (diff)
Phonet: remove dangling pipe if an endpoint is closed early
Closing a pipe endpoint is not normally allowed by the Phonet pipe, other than as a side after-effect of removing the pipe between two endpoints. But there is no way to prevent Linux userspace processes from being killed or suffering from bugs, so this can still happen. We might as well forcefully close Phonet pipe endpoints then. The cellular modem supports only a few existing pipes at a time. So we really should not leak them. This change instructs the modem to destroy the pipe if either of the pipe's endpoint (Linux socket) is closed too early. Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/phonet')
-rw-r--r--net/phonet/pep.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 04e34196c9de..d0e7eb24c8b9 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -620,6 +620,28 @@ drop:
620 return err; 620 return err;
621} 621}
622 622
623static int pipe_do_remove(struct sock *sk)
624{
625 struct pep_sock *pn = pep_sk(sk);
626 struct pnpipehdr *ph;
627 struct sk_buff *skb;
628
629 skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_KERNEL);
630 if (!skb)
631 return -ENOMEM;
632
633 skb_reserve(skb, MAX_PNPIPE_HEADER);
634 __skb_push(skb, sizeof(*ph));
635 skb_reset_transport_header(skb);
636 ph = pnp_hdr(skb);
637 ph->utid = 0;
638 ph->message_id = PNS_PIPE_REMOVE_REQ;
639 ph->pipe_handle = pn->pipe_handle;
640 ph->data[0] = PAD;
641
642 return pn_skb_send(sk, skb, &pipe_srv);
643}
644
623/* associated socket ceases to exist */ 645/* associated socket ceases to exist */
624static void pep_sock_close(struct sock *sk, long timeout) 646static void pep_sock_close(struct sock *sk, long timeout)
625{ 647{
@@ -638,7 +660,10 @@ static void pep_sock_close(struct sock *sk, long timeout)
638 sk_for_each_safe(sknode, p, n, &pn->ackq) 660 sk_for_each_safe(sknode, p, n, &pn->ackq)
639 sk_del_node_init(sknode); 661 sk_del_node_init(sknode);
640 sk->sk_state = TCP_CLOSE; 662 sk->sk_state = TCP_CLOSE;
641 } 663 } else if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED))
664 /* Forcefully remove dangling Phonet pipe */
665 pipe_do_remove(sk);
666
642 ifindex = pn->ifindex; 667 ifindex = pn->ifindex;
643 pn->ifindex = 0; 668 pn->ifindex = 0;
644 release_sock(sk); 669 release_sock(sk);