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: 9513389 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 D8C62601E5 for ; Thu, 12 Jan 2017 15:13:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CB2D4286D3 for ; Thu, 12 Jan 2017 15:13:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BF76C286DE; Thu, 12 Jan 2017 15:13:20 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F7A6286D3 for ; Thu, 12 Jan 2017 15:13:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750773AbdALPNS (ORCPT ); Thu, 12 Jan 2017 10:13:18 -0500 Received: from mail-lf0-f44.google.com ([209.85.215.44]:35689 "EHLO mail-lf0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750720AbdALPNR (ORCPT ); Thu, 12 Jan 2017 10:13:17 -0500 Received: by mail-lf0-f44.google.com with SMTP id m78so14976721lfg.2 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=GfGnAnhf50bkVnJ8w1kJhQ6dsBdB0n7l5q9IuKQ7m2KoWPm2LOnNQ8SrmDo5upTI5g NM0XJ0CXzYCWJ62F+vpDjnkjR5twH9ihT8KVbReoF4v9aPDMtKzJcKxr1kApGYcvLi0v a+vBHihopDTYEgEXJIppchwgdWaPlJ4EGQpyKpWkEghwY2DCg/KDp0EbkJCgHRZR5LP1 REEPHNUMWlPfWXSrKQEga93VSUBp+5KV+ePoRDUZxXh3MICOClK+krl0BKmidy1obDyc MfAdIocaa7nuPq5J7MI1WxPUaRy5gM7px6iS4D3U4Fy1gaaSzfsse+6BEu5pXKshRB98 VFpQ== X-Gm-Message-State: AIkVDXIJAGXwYePMJ+FJBZGhI9JphUC8TYScD1jtTGsDJBxAudQ9tFICBNiQHoQvFV2VPvmgyS9XMq4Leze9hcVlnOqEyECh0bSMKoZPX+KL77rPIOGGvvkUVa1nEAE7vLxUoeL3Ia+bQQ== 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 Cc: linux-wireless@vger.kernel.org, ath10k@lists.infradead.org, greearb@candelatech.com, mohammed@qti.qualcomm.com, Michal Kazior 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 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.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)