msm: ipc: Fix SKB ownership for failure case

When a client writes to IPC Router and if the write fails, then in
certain scenarios both the client and IPC Router take up the ownership
of the SKB. These failure scenarios lead to a double-free and
segmentation fault.

Fix these scenarios by resolving the ownership issue. If the write to
IPC Router is successful, then IPC Router will keep the ownership of the
SKBs and free the packets. If the write fails, then the client will keep
the ownership of the SKBs and free the packets.

CRs-Fixed: 530180
Change-Id: Iaba47f5da377cdf0a6b16ae02d99eab91a9a6221
Signed-off-by: Zaheerulla Meer <zmeer@codeaurora.org>
This commit is contained in:
Zaheerulla Meer 2013-08-20 12:02:31 +05:30 committed by Stephen Boyd
parent f4899eaeb0
commit 2071905fcf
3 changed files with 15 additions and 8 deletions

View File

@ -458,7 +458,7 @@ static void *msm_ipc_router_skb_to_buf(struct sk_buff_head *skb_head,
return buf;
}
static void msm_ipc_router_free_skb(struct sk_buff_head *skb_head)
void msm_ipc_router_free_skb(struct sk_buff_head *skb_head)
{
struct sk_buff *temp_skb;
@ -2299,6 +2299,7 @@ static int loopback_data(struct msm_ipc_port *src,
if (!port_ptr) {
pr_err("%s: Local port %d not present\n", __func__, port_id);
up_read(&local_ports_lock_lha2);
pkt->pkt_fragment_q = NULL;
release_pkt(pkt);
return -ENODEV;
}
@ -2501,6 +2502,8 @@ int msm_ipc_router_send_to(struct msm_ipc_port *src,
ret = msm_ipc_router_write_pkt(src, rport_ptr, pkt);
up_read(&routing_table_lock_lha3);
if (ret < 0)
pkt->pkt_fragment_q = NULL;
release_pkt(pkt);
return ret;
@ -2520,11 +2523,10 @@ int msm_ipc_router_send_msg(struct msm_ipc_port *src,
}
ret = msm_ipc_router_send_to(src, out_skb_head, dest);
if (ret == -EAGAIN)
return ret;
if (ret < 0) {
pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
__func__, ret);
if (ret != -EAGAIN)
pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
__func__, ret);
msm_ipc_router_free_skb(out_skb_head);
return ret;
}

View File

@ -257,4 +257,5 @@ static inline void *msm_ipc_load_default_node(void)
static inline void msm_ipc_unload_default_node(void *pil) { }
#endif
void msm_ipc_router_free_skb(struct sk_buff_head *skb_head);
#endif

View File

@ -378,10 +378,14 @@ static int msm_ipc_router_sendmsg(struct kiocb *iocb, struct socket *sock,
msm_ipc_router_ipc_log(IPC_SEND, ipc_buf, port_ptr);
ret = msm_ipc_router_send_to(port_ptr, msg, &dest->address);
if (ret != total_len) {
if (ret < 0 && ret != -EAGAIN)
pr_err("%s: Send_to failure %d\n", __func__, ret);
else if (ret >= 0)
if (ret < 0) {
if (ret != -EAGAIN)
pr_err("%s: Send_to failure %d\n",
__func__, ret);
msm_ipc_router_free_skb(msg);
} else if (ret >= 0) {
ret = -EFAULT;
}
}
out_sendmsg: