From 94869df3285bb142d6cb220df16176ba816693f7 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 1 May 2018 13:31:38 -0700 Subject: [PATCH] net: qrtr: Do not send packets before hello negotiation There is a race where broadcast packets can be sent to a node that has not sent the hello message to the remote processor. This breaks the protocol expectation. Add a status variable to track when the hello packet has been sent. An alternative solution attempted was to remove the nodes from the broadcast list until the hello packet is sent. This is not a valid solution because hello messages are broadcasted if the ns is restarted or started late. There needs to be a status variable separate from the broadcast list. This change squashes the following commits from msm-4.14: commit abd3961d05be ("qrtr: Only broadcast to initialized nodes") commit 90cb0e473226 ("net: qrtr: Do not send packets before Hello negotiation") commit 07abd1abe803 ("net: qrtr: Fix hello packet drop memory leak") In addition, fix minor format issues. Change-Id: I2a55e587f324e64e2bde4ea634de66008f190de1 Signed-off-by: Chris Lew --- net/qrtr/qrtr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index f132d5c39e93..8e6a392ea34c 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -116,6 +116,7 @@ static DEFINE_MUTEX(qrtr_port_lock); * @ep: endpoint * @ref: reference count for node * @nid: node id + * @hello_sent: hello packet sent to endpoint * @qrtr_tx_flow: tree with tx counts per flow * @resume_tx: waiters for a resume tx from the remote * @qrtr_tx_lock: lock for qrtr_tx_flow @@ -128,6 +129,7 @@ struct qrtr_node { struct qrtr_endpoint *ep; struct kref ref; unsigned int nid; + atomic_t hello_sent; struct radix_tree_root qrtr_tx_flow; struct wait_queue_head resume_tx; @@ -336,6 +338,11 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, int rc = -ENODEV; int confirm_rx; + if (!atomic_read(&node->hello_sent) && type != QRTR_TYPE_HELLO) { + kfree_skb(skb); + return rc; + } + confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type); if (confirm_rx < 0) { kfree_skb(skb); @@ -371,6 +378,8 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb, * confirm_rx flag if we dropped this one */ if (rc && confirm_rx) qrtr_tx_flow_failed(node, to->sq_node, to->sq_port); + if (!rc && type == QRTR_TYPE_HELLO) + atomic_inc(&node->hello_sent); return rc; } @@ -560,6 +569,7 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) skb_queue_head_init(&node->rx_queue); node->nid = QRTR_EP_NID_AUTO; node->ep = ep; + atomic_set(&node->hello_sent, 0); mutex_init(&node->qrtr_tx_lock); INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); @@ -842,6 +852,8 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, mutex_lock(&qrtr_node_lock); list_for_each_entry(node, &qrtr_all_nodes, item) { + if (node->nid == QRTR_EP_NID_AUTO) + continue; skbn = skb_clone(skb, GFP_KERNEL); if (!skbn) break;