From patchwork Thu Jan 12 15:14:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 9513391 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B675D601E5 for ; Thu, 12 Jan 2017 15:14:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A8430286CD for ; Thu, 12 Jan 2017 15:14:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9C7EB286DD; Thu, 12 Jan 2017 15:14:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9531B286CD for ; Thu, 12 Jan 2017 15:14:05 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cRh4Y-0003PT-HL; Thu, 12 Jan 2017 15:13:50 +0000 Received: from mail-lf0-x231.google.com ([2a00:1450:4010:c07::231]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cRh4T-0003CI-KP for ath10k@lists.infradead.org; Thu, 12 Jan 2017 15:13:49 +0000 Received: by mail-lf0-x231.google.com with SMTP id k86so15046191lfi.0 for ; Thu, 12 Jan 2017 07:13:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id; bh=g3F379dQx+/coCmn3+VVTvfPYHgN3oi1nrNgefydpbk=; b=lBv5hR1vRrZc2HQdgBeC8Gk8YAc1tbn5qwaUEesjC6rScMp27Dl1pjpaU/VypagTDT BXMEXP/57+E/ojHdNJATwhVeAwcEbpo959VLACoyIonh/3Ecmi6UcIgjE5idKhcOpmes pIkyg75mTk41Y4SfRv5wJE8pijDS0jydzv034= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=g3F379dQx+/coCmn3+VVTvfPYHgN3oi1nrNgefydpbk=; b=YbvmVIKZHarBwKf1+DtGGh3lam7UssIV/HENkqIIF2fr8rz7LzHe8GhhvXXyY2OyoH IpnJPY/GBb+xB2iKL5Ds06t7Zh+Cd5C36V1QHaJB9bTirpwFRF4JygJNj/9Oqi9Rmv/s tUbmYRhOgXqS7Bvf6PQBfJMMCqBwTeWyJS0YGTpS4dJNJlYqxXroGAK7JwJnrG8YQ0UA BrNdwY3OmZQYVw4gJM17kL3sioixuZjCxxpJuo+O5Jittpo5xvTBv/g4E1e+YjwoEIn1 cTbVdgOHiQhywI2zzTuLcR8Rg5Aq7SqtbWNoYYyen4TkhX0i7ID/qhBDGuwb0y8RZUsz wLdg== X-Gm-Message-State: AIkVDXJ9MiW23HJh+rr97vPawZr80wmQ/yhWT8aLf30LFGCW73AkRY6fU7QIxlOp6qbRHHDq9CJhl4iblcftaYDGKSAErbkFdj8cK2mygsuv4JEjBziISvaBibLFgwGIPLAnpTrx X-Received: by 10.25.75.79 with SMTP id y76mr2330963lfa.143.1484233995964; Thu, 12 Jan 2017 07:13:15 -0800 (PST) Received: from localhost.localdomain ([91.198.246.8]) by smtp.gmail.com with ESMTPSA id s63sm805519lja.49.2017.01.12.07.13.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 12 Jan 2017 07:13:15 -0800 (PST) From: Michal Kazior To: kvalo@qca.qualcomm.com Subject: [PATCH] ath10k: prevent sta pointer rcu violation Date: Thu, 12 Jan 2017 16:14:30 +0100 Message-Id: <1484234070-7431-1-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 2.1.4 X-DomainID: tieto.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170112_071345_863392_82074706 X-CRM114-Status: GOOD ( 11.62 ) X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: greearb@candelatech.com, linux-wireless@vger.kernel.org, Michal Kazior , ath10k@lists.infradead.org, mohammed@qti.qualcomm.com MIME-Version: 1.0 Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Station pointers are RCU protected so driver must be extra careful if it tries to store them internally for later use outside of the RCU section it obtained it in. It was possible for station teardown to race with some htt events. The possible outcome could be a use-after-free and a crash. Only peer-flow-control capable firmware was affected (so hardware-wise qca99x0 and qca4019). This could be done in sta_state() itself via explicit synchronize_net() call but there's already a convenient sta_pre_rcu_remove() op that can be hooked up to avoid extra rcu stall. The peer->sta pointer itself can't be set to NULL/ERR_PTR because it is later used in sta_state() for extra sanity checks. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c7664d6569fa..1ab589296dff 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -314,6 +314,7 @@ struct ath10k_peer { struct ieee80211_vif *vif; struct ieee80211_sta *sta; + bool removed; int vdev_id; u8 addr[ETH_ALEN]; DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d1b7edba5e49..aa91f55b35a4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3774,6 +3774,9 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, if (!peer) return NULL; + if (peer->removed) + return NULL; + if (peer->sta) return peer->sta->txq[tid]; else if (peer->vif) @@ -7476,6 +7479,20 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, return 0; } +static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath10k *ar; + struct ath10k_peer *peer; + + ar = hw->priv; + + list_for_each_entry(peer, &ar->peers, list) + if (peer->sta == sta) + peer->removed = true; +} + static const struct ieee80211_ops ath10k_ops = { .tx = ath10k_mac_op_tx, .wake_tx_queue = ath10k_mac_op_wake_tx_queue, @@ -7516,6 +7533,7 @@ static const struct ieee80211_ops ath10k_ops = { .assign_vif_chanctx = ath10k_mac_op_assign_vif_chanctx, .unassign_vif_chanctx = ath10k_mac_op_unassign_vif_chanctx, .switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx, + .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove, CFG80211_TESTMODE_CMD(ath10k_tm_cmd)