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

Commit 63354797 authored by Reshetova, Elena's avatar Reshetova, Elena Committed by David S. Miller
Browse files

net: convert sk_buff.users from atomic_t to refcount_t



refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.

Signed-off-by: default avatarElena Reshetova <elena.reshetova@intel.com>
Signed-off-by: default avatarHans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarDavid Windsor <dwindsor@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 53869ceb
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -742,7 +742,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,

	if (type == NES_TIMER_TYPE_SEND) {
		new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
		atomic_inc(&new_send->skb->users);
		refcount_inc(&new_send->skb->users);
		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
		cm_node->send_entry = new_send;
		add_ref_cm_node(cm_node);
@@ -924,7 +924,7 @@ static void nes_cm_timer_tick(unsigned long pass)
						  flags);
				break;
			}
			atomic_inc(&send_entry->skb->users);
			refcount_inc(&send_entry->skb->users);
			cm_packets_retrans++;
			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
				  "for node %p, jiffies = %lu, time to send = "
+1 −1
Original line number Diff line number Diff line
@@ -155,7 +155,7 @@ mISDN_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
	copied = skb->len + MISDN_HEADER_LEN;
	if (len < copied) {
		if (flags & MSG_PEEK)
			atomic_dec(&skb->users);
			refcount_dec(&skb->users);
		else
			skb_queue_head(&sk->sk_receive_queue, skb);
		return -ENOSPC;
+1 −1
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
				rionet_queue_tx_msg(skb, ndev,
					nets[rnet->mport->id].active[i]);
				if (count)
					atomic_inc(&skb->users);
					refcount_inc(&skb->users);
				count++;
			}
	} else if (RIONET_MAC_MATCH(eth->h_dest)) {
+13 −13
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
			return -EBUSY;
		} else {
			atomic_inc(&skb->users);
			refcount_inc(&skb->users);
			header.length = l;
			header.type = be16_to_cpu(skb->protocol);
			header.unused = 0;
@@ -500,7 +500,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
	 * Protect skb against beeing free'd by upper
	 * layers.
	 */
	atomic_inc(&skb->users);
	refcount_inc(&skb->users);
	ch->prof.txlen += skb->len;
	header.length = skb->len + LL_HEADER_LENGTH;
	header.type = be16_to_cpu(skb->protocol);
@@ -517,14 +517,14 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
	if (hi) {
		nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
		if (!nskb) {
			atomic_dec(&skb->users);
			refcount_dec(&skb->users);
			skb_pull(skb, LL_HEADER_LENGTH + 2);
			ctcm_clear_busy(ch->netdev);
			return -ENOMEM;
		} else {
			skb_put_data(nskb, skb->data, skb->len);
			atomic_inc(&nskb->users);
			atomic_dec(&skb->users);
			refcount_inc(&nskb->users);
			refcount_dec(&skb->users);
			dev_kfree_skb_irq(skb);
			skb = nskb;
		}
@@ -542,7 +542,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
			 * Remove our header. It gets added
			 * again on retransmit.
			 */
			atomic_dec(&skb->users);
			refcount_dec(&skb->users);
			skb_pull(skb, LL_HEADER_LENGTH + 2);
			ctcm_clear_busy(ch->netdev);
			return -ENOMEM;
@@ -553,7 +553,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
		ch->ccw[1].count = skb->len;
		skb_copy_from_linear_data(skb,
				skb_put(ch->trans_skb, skb->len), skb->len);
		atomic_dec(&skb->users);
		refcount_dec(&skb->users);
		dev_kfree_skb_irq(skb);
		ccw_idx = 0;
	} else {
@@ -679,7 +679,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)

	if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
		spin_lock_irqsave(&ch->collect_lock, saveflags);
		atomic_inc(&skb->users);
		refcount_inc(&skb->users);
		p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());

		if (!p_header) {
@@ -716,7 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
	 * Protect skb against beeing free'd by upper
	 * layers.
	 */
	atomic_inc(&skb->users);
	refcount_inc(&skb->users);

	/*
	 * IDAL support in CTCM is broken, so we have to
@@ -729,8 +729,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
			goto nomem_exit;
		} else {
			skb_put_data(nskb, skb->data, skb->len);
			atomic_inc(&nskb->users);
			atomic_dec(&skb->users);
			refcount_inc(&nskb->users);
			refcount_dec(&skb->users);
			dev_kfree_skb_irq(skb);
			skb = nskb;
		}
@@ -810,7 +810,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
		ch->trans_skb->len = 0;
		ch->ccw[1].count = skb->len;
		skb_put_data(ch->trans_skb, skb->data, skb->len);
		atomic_dec(&skb->users);
		refcount_dec(&skb->users);
		dev_kfree_skb_irq(skb);
		ccw_idx = 0;
		CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
@@ -855,7 +855,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
			"%s(%s): MEMORY allocation ERROR\n",
			CTCM_FUNTAIL, ch->id);
	rc = -ENOMEM;
	atomic_dec(&skb->users);
	refcount_dec(&skb->users);
	dev_kfree_skb_any(skb);
	fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
done:
+5 −5
Original line number Diff line number Diff line
@@ -743,7 +743,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
	conn->prof.tx_pending--;
	if (single_flag) {
		if ((skb = skb_dequeue(&conn->commit_queue))) {
			atomic_dec(&skb->users);
			refcount_dec(&skb->users);
			if (privptr) {
				privptr->stats.tx_packets++;
				privptr->stats.tx_bytes +=
@@ -766,7 +766,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
		txbytes += skb->len;
		txpackets++;
		stat_maxcq++;
		atomic_dec(&skb->users);
		refcount_dec(&skb->users);
		dev_kfree_skb_any(skb);
	}
	if (conn->collect_len > conn->prof.maxmulti)
@@ -958,7 +958,7 @@ static void netiucv_purge_skb_queue(struct sk_buff_head *q)
	struct sk_buff *skb;

	while ((skb = skb_dequeue(q))) {
		atomic_dec(&skb->users);
		refcount_dec(&skb->users);
		dev_kfree_skb_any(skb);
	}
}
@@ -1176,7 +1176,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
			IUCV_DBF_TEXT(data, 2,
				      "EBUSY from netiucv_transmit_skb\n");
		} else {
			atomic_inc(&skb->users);
			refcount_inc(&skb->users);
			skb_queue_tail(&conn->collect_queue, skb);
			conn->collect_len += l;
			rc = 0;
@@ -1245,7 +1245,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
		} else {
			if (copied)
				dev_kfree_skb(skb);
			atomic_inc(&nskb->users);
			refcount_inc(&nskb->users);
			skb_queue_tail(&conn->commit_queue, nskb);
		}
	}
Loading