Parcourir la source

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
Bojun Pan il y a 4 ans
Parent
commit
03f3d1ac41
1 fichiers modifiés avec 6 ajouts et 4 suppressions
  1. 6 4
      drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c

+ 6 - 4
drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c

@@ -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;