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: Arun Prakash <app@codeaurora.org>
This commit is contained in:
committed by
Sivaji Boddupilli
parent
e13155f7ef
commit
b669e0ea2e
@@ -477,22 +477,20 @@ 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);
|
||||
|
||||
mutex_lock(&node->qrtr_tx_lock);
|
||||
flow = radix_tree_lookup(&node->qrtr_tx_flow, key);
|
||||
if (!flow) {
|
||||
flow = kzalloc(sizeof(*flow), GFP_KERNEL);
|
||||
if (!flow) {
|
||||
mutex_unlock(&node->qrtr_tx_lock);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
flow = radix_tree_lookup(&node->qrtr_tx_flow, key);
|
||||
if (!flow) {
|
||||
flow = kzalloc(sizeof(*flow), GFP_KERNEL);
|
||||
if (!flow) {
|
||||
mutex_unlock(&node->qrtr_tx_lock);
|
||||
return 1;
|
||||
}
|
||||
INIT_LIST_HEAD(&flow->waiters);
|
||||
radix_tree_insert(&node->qrtr_tx_flow, key, flow);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
kfree(flow);
|
||||
radix_tree_delete(&node->qrtr_tx_flow, key);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user