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

Commit b669e0ea authored by Arun Prakash's avatar Arun Prakash Committed by Sivaji Boddupilli
Browse files

net: qrtr: Use radix_tree_iter_delete to delete tx flow



Below two issues are handled in this change.

1.Use radix_tree_iter_delete instead of radix_tree_delete to properly
remove slots in a radix tree without any dangling references.

2.Flow entry can be deleted when sending process waiting on the queue
if remote socket closes.Which leads to accessing non-valid flow entry.
To resolve this lookup for the tx flow entry each time before reading
flow count or inserting caller process to waiting list to check the
validity of flow entry in the radix tree.

Change-Id: I42b85b53cfcf5cd4256fbd6cb445d0098078a6f0
Signed-off-by: default avatarArun Prakash <app@codeaurora.org>
parent e13155f7
Loading
Loading
Loading
Loading
+23 −16
Original line number Diff line number Diff line
@@ -477,6 +477,8 @@ static int qrtr_tx_wait(struct qrtr_node *node, struct sockaddr_qrtr *to,
	/* Assume sk is set correctly for all data type packets */
	timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);

	ret = timeo;
	for (;;) {
		mutex_lock(&node->qrtr_tx_lock);
		flow = radix_tree_lookup(&node->qrtr_tx_flow, key);
		if (!flow) {
@@ -488,11 +490,7 @@ static int qrtr_tx_wait(struct qrtr_node *node, struct sockaddr_qrtr *to,
			INIT_LIST_HEAD(&flow->waiters);
			radix_tree_insert(&node->qrtr_tx_flow, key, flow);
		}
	mutex_unlock(&node->qrtr_tx_lock);

	ret = timeo;
	for (;;) {
		mutex_lock(&node->qrtr_tx_lock);
		if (atomic_read(&flow->pending) < QRTR_TX_FLOW_HIGH) {
			atomic_inc(&flow->pending);
			confirm_rx = atomic_read(&flow->pending) ==
@@ -1069,8 +1067,10 @@ static void qrtr_cleanup_flow_control(struct qrtr_node *node,
{
	struct qrtr_ctrl_pkt *pkt;
	unsigned long key;
	void __rcu **slot;
	struct sockaddr_qrtr src;
	struct qrtr_tx_flow *flow;
	struct radix_tree_iter iter;
	struct qrtr_tx_flow_waiter *waiter;
	struct qrtr_tx_flow_waiter *temp;
	u32 cmd;
@@ -1100,8 +1100,15 @@ static void qrtr_cleanup_flow_control(struct qrtr_node *node,
		sock_put(waiter->sk);
		kfree(waiter);
	}

	radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) {
		if (flow == (struct qrtr_tx_flow *)rcu_dereference(*slot)) {
			radix_tree_iter_delete(&node->qrtr_tx_flow,
					       &iter, slot);
			kfree(flow);
	radix_tree_delete(&node->qrtr_tx_flow, key);
			break;
		}
	}
	mutex_unlock(&node->qrtr_tx_lock);
}

@@ -1132,8 +1139,8 @@ static void qrtr_handle_del_proc(struct qrtr_node *node, struct sk_buff *skb)
			sock_put(waiter->sk);
			kfree(waiter);
		}
		radix_tree_iter_delete(&node->qrtr_tx_flow, &iter, slot);
		kfree(flow);
		radix_tree_delete(&node->qrtr_tx_flow, iter.index);
	}
	mutex_unlock(&node->qrtr_tx_lock);