From patchwork Tue Jan 26 22:05:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 101076 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp2233764lbb; Tue, 26 Jan 2016 14:06:44 -0800 (PST) X-Received: by 10.66.90.166 with SMTP id bx6mr37831975pab.75.1453846004605; Tue, 26 Jan 2016 14:06:44 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y78si4463156pfa.174.2016.01.26.14.06.44; Tue, 26 Jan 2016 14:06:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752635AbcAZWGm (ORCPT + 30 others); Tue, 26 Jan 2016 17:06:42 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:53187 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750900AbcAZWGk (ORCPT ); Tue, 26 Jan 2016 17:06:40 -0500 Received: from wuerfel.lan. ([78.42.132.4]) by mrelayeu.kundenserver.de (mreue002) with ESMTPA (Nemesis) id 0Ldx0u-1ZlWUK46aC-00pthh; Tue, 26 Jan 2016 23:06:05 +0100 From: Arnd Bergmann To: Johannes Berg , "David S. Miller" Cc: linux-arm-kernel@lists.infradead.org, Arnd Bergmann , linux-wireless@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] mac80211: avoid excessive stack usage in sta_info Date: Tue, 26 Jan 2016 23:05:31 +0100 Message-Id: <1453845942-3402704-1-git-send-email-arnd@arndb.de> X-Mailer: git-send-email 2.7.0 X-Provags-ID: V03:K0:CcTM1slflFm/zWt5Gx6ljeVqykjllJ+t9rZxZbXamvdmgq/OCID zj/YzZtWCrCXS80S+fNRsl5l9Hm2bAH3MWP1kelDBr6oY5yKz42BE9Bb0q6Aih5fxHxaaqX S+t5ZN5c+4lm0vQE5z/rs5Jn4mGgW5tQ7PMSwknWYLebKiGVH8q7Sv8JtPB9HK9yxXhGilK hIvRXl6KXNDaPBe2WBqDQ== X-UI-Out-Filterresults: notjunk:1; V01:K0:z2kMax6Fth4=:GzHofPWV5OG6J1G7SAC2lN 0y1/8zqoAsVcKt8HYz6CocmMiUtoeuNfc6YGNQeY767l15mbUNxjYrDlubh0ROxWtI+MseizV DvoIMVsQIMO4SQpYLJbBJOmtgkBPUj04PfkGOCpHC3KstxmCLcAfObdDw5nD39I+Ogbr7P4Gs 7TG0CWA4K3/C0waa8FNk0Wa9+10QhuA2OZ2W4rxovzpGmz/t2pfTvbyIWZszq3z+MuAW8CoIA 8dj1ttNq0oAyY+geOTjTUdfdxv3yb80CB/6K6+i0CwYUfIQ51W6YVb1B9a8Vhw3MQoasCYhhE 45ztm/LdgjB9bVZPLWuThL7Nz8OGsi+cWiW790oxti65cwRX9YwXushRJVsfulRVzaAWiWJ42 W0u5x9IqpKoHbDhRvY3x9qK/XGGwfL0dxZ1Va6JgyJhlNg4GzBEZu4/3gS/16eMLNSAxeeK23 IpkBWV6NIWIF4XF4SzKI7UU6kE2/rtizNFVIbgtQpiCCDyMaq/GkW3fJxVtfdnnzn72B57dXu LleasGy3zL/MWBlggGfgn9yiCEjomdU3RsctBe/T+Q/Lel9HWIPxxryyUSrKpZYfd12neo65Y zqw9q7irlvWjWXPvloc8ohSmSUiGIl1uMczjbYaBq5ttOlgowsJ1glSAPbkPYbdi8y6UH8yTR 556fS8Reuy+HyGTaXB7xzy9xalgqyFNcJOBsAOIl76FMYh0fCdbM3Hs1U7i94wUrZCvI= Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When CONFIG_OPTIMIZE_INLINING is set, the sta_info_insert_finish function consumes more stack than normally, exceeding the 1024 byte limit on ARM: net/mac80211/sta_info.c: In function 'sta_info_insert_finish': net/mac80211/sta_info.c:561:1: error: the frame size of 1080 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] It turns out that there are two functions that put a 'struct station_info' on the stack: __sta_info_destroy_part2 and sta_info_insert_finish, and this structure alone requires up to 792 bytes. Hoping that both are called rarely enough, this replaces the on-stack structure with a dynamic allocation, which unfortunately requires some suboptimal error handling for out-of-memory. The __sta_info_destroy_part2 function is actually affected by the stack usage twice because it calls cfg80211_del_sta_sinfo(), which has another instance of struct station_info on its stack. Signed-off-by: Arnd Bergmann Fixes: 98b6218388e3 ("mac80211/cfg80211: add station events") Fixes: 6f7a8d26e266 ("mac80211: send statistics with delete station event") --- net/mac80211/sta_info.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) -- 2.7.0 diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4402ad5b27d1..a29199ec4c3c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -498,11 +498,17 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - struct station_info sinfo; + struct station_info *sinfo; int err = 0; lockdep_assert_held(&local->sta_mtx); + sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL); + if (!sinfo) { + err = -ENOMEM; + goto out_err; + } + /* check if STA exists already */ if (sta_info_get_bss(sdata, sta->sta.addr)) { err = -EEXIST; @@ -534,10 +540,9 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) ieee80211_sta_debugfs_add(sta); rate_control_add_sta_debugfs(sta); - memset(&sinfo, 0, sizeof(sinfo)); - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + sinfo->generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); + kfree(sinfo); sta_dbg(sdata, "Inserted STA %pM\n", sta->sta.addr); @@ -898,7 +903,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - struct station_info sinfo = {}; + struct station_info *sinfo; int ret; /* @@ -936,8 +941,11 @@ static void __sta_info_destroy_part2(struct sta_info *sta) sta_dbg(sdata, "Removed STA %pM\n", sta->sta.addr); - sta_set_sinfo(sta, &sinfo); - cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); + if (sinfo) + sta_set_sinfo(sta, sinfo); + cfg80211_del_sta_sinfo(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL); + kfree(sinfo); rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta);