Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2071905f authored by Zaheerulla Meer's avatar Zaheerulla Meer Committed by Stephen Boyd
Browse files

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: default avatarZaheerulla Meer <zmeer@codeaurora.org>
parent f4899eae
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -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,9 +2523,8 @@ 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) {
		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);
+1 −0
Original line number Diff line number Diff line
@@ -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
+7 −3
Original line number Diff line number Diff line
@@ -378,11 +378,15 @@ 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:
	release_sock(sk);