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

Commit 03f3d1ac authored by Bojun Pan's avatar Bojun Pan
Browse files

msm: ipa: fix the use after free in rmnet_ipa_ctl xmit

skb->len is still used to update the tx stats, after the skb
could be freed in tx completion context.

Change-Id: I2c490dfdbc9401613816058c1c8207ea6b6f3450
parent ec17a7f3
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -383,6 +383,7 @@ void ipa3_rmnet_ctl_ready_notifier(void)
int ipa3_rmnet_ctl_xmit(struct sk_buff *skb)
{
	int ret;
	int len;
	unsigned long flags;

	if (!ipa3_ctx->rmnet_ctl_enable) {
@@ -451,6 +452,7 @@ int ipa3_rmnet_ctl_xmit(struct sk_buff *skb)
	}
	spin_unlock_irqrestore(&rmnet_ctl_ipa3_ctx->tx_lock, flags);

	len = skb->len;
	/*
	 * both data packets and command will be routed to
	 * IPA_CLIENT_Q6_WAN_CONS based on DMA settings
@@ -478,8 +480,7 @@ int ipa3_rmnet_ctl_xmit(struct sk_buff *skb)
	spin_lock_irqsave(&rmnet_ctl_ipa3_ctx->tx_lock, flags);
	atomic_inc(&rmnet_ctl_ipa3_ctx->stats.outstanding_pkts);
	rmnet_ctl_ipa3_ctx->stats.tx_pkt_sent++;
	rmnet_ctl_ipa3_ctx->stats.tx_byte_sent +=
		skb->len;
	rmnet_ctl_ipa3_ctx->stats.tx_byte_sent += len;
	ret = 0;

out:
@@ -496,6 +497,7 @@ static void rmnet_ctl_wakeup_ipa(struct work_struct *work)
	int ret;
	unsigned long flags;
	struct sk_buff *skb;
	int len;

	/* calling from WQ */
	ret = ipa_pm_activate_sync(rmnet_ctl_ipa3_ctx->rmnet_ctl_pm_hdl);
@@ -512,6 +514,7 @@ static void rmnet_ctl_wakeup_ipa(struct work_struct *work)
	/* dequeue the skb */
	while (skb_queue_len(&rmnet_ctl_ipa3_ctx->tx_queue) > 0) {
		skb = skb_dequeue(&rmnet_ctl_ipa3_ctx->tx_queue);
		len = skb->len;
		spin_unlock_irqrestore(&rmnet_ctl_ipa3_ctx->tx_lock, flags);
		/*
		 * both data packets and command will be routed to
@@ -539,8 +542,7 @@ static void rmnet_ctl_wakeup_ipa(struct work_struct *work)
		atomic_inc(&rmnet_ctl_ipa3_ctx->stats.outstanding_pkts);
		spin_lock_irqsave(&rmnet_ctl_ipa3_ctx->tx_lock, flags);
		rmnet_ctl_ipa3_ctx->stats.tx_pkt_sent++;
		rmnet_ctl_ipa3_ctx->stats.tx_byte_sent +=
			skb->len;
		rmnet_ctl_ipa3_ctx->stats.tx_byte_sent += len;
	}
	spin_unlock_irqrestore(&rmnet_ctl_ipa3_ctx->tx_lock, flags);
	goto out;