From owner-svn-src-head@freebsd.org Sun Jan 24 23:35:21 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 59BB372CF; Sun, 24 Jan 2016 23:35:21 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2D6F5A3A; Sun, 24 Jan 2016 23:35:21 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u0ONZKZS053627; Sun, 24 Jan 2016 23:35:20 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u0ONZKwW053626; Sun, 24 Jan 2016 23:35:20 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201601242335.u0ONZKwW053626@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Sun, 24 Jan 2016 23:35:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r294697 - head/sys/net80211 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 24 Jan 2016 23:35:21 -0000 Author: avos Date: Sun Jan 24 23:35:20 2016 New Revision: 294697 URL: https://svnweb.freebsd.org/changeset/base/294697 Log: net80211: reduce stack usage for ieee80211_ioctl*() methods. Use malloc(9) for - struct ieee80211req_wpaie2 (518 bytes, used in ieee80211_ioctl_getwpaie()) - struct ieee80211_scan_req (128 bytes, used in setmlme_assoc_adhoc() and ieee80211_ioctl_scanreq()) Also, drop __noinline workarounds; stack overflow is not reproducible with recent compilers. Tested with Clang 3.7.1, GCC 4.2.1 (from 9.3-RELEASE) and 4.9.4 (with -fstack-usage flag) Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D5041 Modified: head/sys/net80211/ieee80211_ioctl.c Modified: head/sys/net80211/ieee80211_ioctl.c ============================================================================== --- head/sys/net80211/ieee80211_ioctl.c Sun Jan 24 23:28:14 2016 (r294696) +++ head/sys/net80211/ieee80211_ioctl.c Sun Jan 24 23:35:20 2016 (r294697) @@ -68,7 +68,7 @@ static struct ieee80211_channel *findcha static int ieee80211_scanreq(struct ieee80211vap *, struct ieee80211_scan_req *); -static __noinline int +static int ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -124,7 +124,7 @@ ieee80211_ioctl_getkey(struct ieee80211v return copyout(&ik, ireq->i_data, sizeof(ik)); } -static __noinline int +static int ieee80211_ioctl_getchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -134,7 +134,7 @@ ieee80211_ioctl_getchanlist(struct ieee8 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); } -static __noinline int +static int ieee80211_ioctl_getchaninfo(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -148,36 +148,40 @@ ieee80211_ioctl_getchaninfo(struct ieee8 return copyout(&ic->ic_nchans, ireq->i_data, space); } -static __noinline int +static int ieee80211_ioctl_getwpaie(struct ieee80211vap *vap, struct ieee80211req *ireq, int req) { struct ieee80211_node *ni; - struct ieee80211req_wpaie2 wpaie; + struct ieee80211req_wpaie2 *wpaie; int error; if (ireq->i_len < IEEE80211_ADDR_LEN) return EINVAL; - error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); + wpaie = IEEE80211_MALLOC(sizeof(*wpaie), M_TEMP, + IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); + if (wpaie == NULL) + return ENOMEM; + error = copyin(ireq->i_data, wpaie->wpa_macaddr, IEEE80211_ADDR_LEN); if (error != 0) - return error; - ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie.wpa_macaddr); - if (ni == NULL) - return ENOENT; - memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); + goto bad; + ni = ieee80211_find_vap_node(&vap->iv_ic->ic_sta, vap, wpaie->wpa_macaddr); + if (ni == NULL) { + error = ENOENT; + goto bad; + } if (ni->ni_ies.wpa_ie != NULL) { int ielen = ni->ni_ies.wpa_ie[1] + 2; - if (ielen > sizeof(wpaie.wpa_ie)) - ielen = sizeof(wpaie.wpa_ie); - memcpy(wpaie.wpa_ie, ni->ni_ies.wpa_ie, ielen); + if (ielen > sizeof(wpaie->wpa_ie)) + ielen = sizeof(wpaie->wpa_ie); + memcpy(wpaie->wpa_ie, ni->ni_ies.wpa_ie, ielen); } if (req == IEEE80211_IOC_WPAIE2) { - memset(wpaie.rsn_ie, 0, sizeof(wpaie.rsn_ie)); if (ni->ni_ies.rsn_ie != NULL) { int ielen = ni->ni_ies.rsn_ie[1] + 2; - if (ielen > sizeof(wpaie.rsn_ie)) - ielen = sizeof(wpaie.rsn_ie); - memcpy(wpaie.rsn_ie, ni->ni_ies.rsn_ie, ielen); + if (ielen > sizeof(wpaie->rsn_ie)) + ielen = sizeof(wpaie->rsn_ie); + memcpy(wpaie->rsn_ie, ni->ni_ies.rsn_ie, ielen); } if (ireq->i_len > sizeof(struct ieee80211req_wpaie2)) ireq->i_len = sizeof(struct ieee80211req_wpaie2); @@ -186,18 +190,21 @@ ieee80211_ioctl_getwpaie(struct ieee8021 /* XXX check ic_flags? */ if (ni->ni_ies.rsn_ie != NULL) { int ielen = ni->ni_ies.rsn_ie[1] + 2; - if (ielen > sizeof(wpaie.wpa_ie)) - ielen = sizeof(wpaie.wpa_ie); - memcpy(wpaie.wpa_ie, ni->ni_ies.rsn_ie, ielen); + if (ielen > sizeof(wpaie->wpa_ie)) + ielen = sizeof(wpaie->wpa_ie); + memcpy(wpaie->wpa_ie, ni->ni_ies.rsn_ie, ielen); } if (ireq->i_len > sizeof(struct ieee80211req_wpaie)) ireq->i_len = sizeof(struct ieee80211req_wpaie); } ieee80211_free_node(ni); - return copyout(&wpaie, ireq->i_data, ireq->i_len); + error = copyout(wpaie, ireq->i_data, ireq->i_len); +bad: + IEEE80211_FREE(wpaie, M_TEMP); + return error; } -static __noinline int +static int ieee80211_ioctl_getstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -252,7 +259,7 @@ get_scan_space(void *arg, const struct i req->space += scan_space(se, &ielen); } -static __noinline void +static void get_scan_result(void *arg, const struct ieee80211_scan_entry *se) { struct scanreq *req = arg; @@ -302,7 +309,7 @@ get_scan_result(void *arg, const struct req->sr = (struct ieee80211req_scan_result *)(((uint8_t *)sr) + len); } -static __noinline int +static int ieee80211_ioctl_getscanresults(struct ieee80211vap *vap, struct ieee80211req *ireq) { @@ -366,7 +373,7 @@ get_sta_space(void *arg, struct ieee8021 req->space += sta_space(ni, &ielen); } -static __noinline void +static void get_sta_info(void *arg, struct ieee80211_node *ni) { struct stainforeq *req = arg; @@ -452,7 +459,7 @@ get_sta_info(void *arg, struct ieee80211 req->space -= len; } -static __noinline int +static int getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq, struct ieee80211_node *ni, size_t off) { @@ -496,7 +503,7 @@ bad: return error; } -static __noinline int +static int ieee80211_ioctl_getstainfo(struct ieee80211vap *vap, struct ieee80211req *ireq) { uint8_t macaddr[IEEE80211_ADDR_LEN]; @@ -519,7 +526,7 @@ ieee80211_ioctl_getstainfo(struct ieee80 return getstainfo_common(vap, ireq, ni, off); } -static __noinline int +static int ieee80211_ioctl_getstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -540,7 +547,7 @@ ieee80211_ioctl_getstatxpow(struct ieee8 return error; } -static __noinline int +static int ieee80211_ioctl_getwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -583,7 +590,7 @@ ieee80211_ioctl_getwmeparam(struct ieee8 return 0; } -static __noinline int +static int ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) { const struct ieee80211_aclator *acl = vap->iv_acl; @@ -591,7 +598,7 @@ ieee80211_ioctl_getmaccmd(struct ieee802 return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq)); } -static __noinline int +static int ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -648,7 +655,7 @@ ieee80211_ioctl_getappie(struct ieee8021 return EINVAL; } -static __noinline int +static int ieee80211_ioctl_getregdomain(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -660,7 +667,7 @@ ieee80211_ioctl_getregdomain(struct ieee sizeof(ic->ic_regdomain)); } -static __noinline int +static int ieee80211_ioctl_getroam(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -671,7 +678,7 @@ ieee80211_ioctl_getroam(struct ieee80211 return copyout(vap->iv_roamparms, ireq->i_data, len); } -static __noinline int +static int ieee80211_ioctl_gettxparams(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -682,7 +689,7 @@ ieee80211_ioctl_gettxparams(struct ieee8 return copyout(vap->iv_txparms, ireq->i_data, len); } -static __noinline int +static int ieee80211_ioctl_getdevcaps(struct ieee80211com *ic, const struct ieee80211req *ireq) { @@ -716,7 +723,7 @@ ieee80211_ioctl_getdevcaps(struct ieee80 return error; } -static __noinline int +static int ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -765,23 +772,7 @@ ieee80211_ioctl_getdefault(struct ieee80 return EINVAL; } -/* - * When building the kernel with -O2 on the i386 architecture, gcc - * seems to want to inline this function into ieee80211_ioctl() - * (which is the only routine that calls it). When this happens, - * ieee80211_ioctl() ends up consuming an additional 2K of stack - * space. (Exactly why it needs so much is unclear.) The problem - * is that it's possible for ieee80211_ioctl() to invoke other - * routines (including driver init functions) which could then find - * themselves perilously close to exhausting the stack. - * - * To avoid this, we deliberately prevent gcc from inlining this - * routine. Another way to avoid this is to use less agressive - * optimization when compiling this file (i.e. -O instead of -O2) - * but special-casing the compilation of this one module in the - * build system would be awkward. - */ -static __noinline int +static int ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq) { @@ -1136,7 +1127,7 @@ ieee80211_ioctl_get80211(struct ieee8021 #undef MS } -static __noinline int +static int ieee80211_ioctl_setkey(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211req_key ik; @@ -1210,7 +1201,7 @@ ieee80211_ioctl_setkey(struct ieee80211v return error; } -static __noinline int +static int ieee80211_ioctl_delkey(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211req_del_key dk; @@ -1352,7 +1343,7 @@ setmlme_dropsta(struct ieee80211vap *vap return error; } -static __noinline int +static int setmlme_common(struct ieee80211vap *vap, int op, const uint8_t mac[IEEE80211_ADDR_LEN], int reason) { @@ -1513,7 +1504,7 @@ mlmelookup(void *arg, const struct ieee8 look->se = se; } -static __noinline int +static int setmlme_assoc_sta(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN]) @@ -1538,12 +1529,13 @@ setmlme_assoc_sta(struct ieee80211vap *v return 0; } -static __noinline int +static int setmlme_assoc_adhoc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], int ssid_len, const uint8_t ssid[IEEE80211_NWID_LEN]) { - struct ieee80211_scan_req sr; + struct ieee80211_scan_req *sr; + int error; KASSERT(vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_AHDEMO, @@ -1553,23 +1545,30 @@ setmlme_assoc_adhoc(struct ieee80211vap if (ssid_len == 0) return EINVAL; + sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP, + IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); + if (sr == NULL) + return ENOMEM; + /* NB: IEEE80211_IOC_SSID call missing for ap_scan=2. */ memset(vap->iv_des_ssid[0].ssid, 0, IEEE80211_NWID_LEN); vap->iv_des_ssid[0].len = ssid_len; memcpy(vap->iv_des_ssid[0].ssid, ssid, ssid_len); vap->iv_des_nssid = 1; - memset(&sr, 0, sizeof(sr)); - sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE; - sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; - memcpy(sr.sr_ssid[0].ssid, ssid, ssid_len); - sr.sr_ssid[0].len = ssid_len; - sr.sr_nssid = 1; + sr->sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE; + sr->sr_duration = IEEE80211_IOC_SCAN_FOREVER; + memcpy(sr->sr_ssid[0].ssid, ssid, ssid_len); + sr->sr_ssid[0].len = ssid_len; + sr->sr_nssid = 1; + + error = ieee80211_scanreq(vap, sr); - return ieee80211_scanreq(vap, &sr); + IEEE80211_FREE(sr, M_TEMP); + return error; } -static __noinline int +static int ieee80211_ioctl_setmlme(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211req_mlme mlme; @@ -1594,7 +1593,7 @@ ieee80211_ioctl_setmlme(struct ieee80211 mlme.im_macaddr, mlme.im_reason); } -static __noinline int +static int ieee80211_ioctl_macmac(struct ieee80211vap *vap, struct ieee80211req *ireq) { uint8_t mac[IEEE80211_ADDR_LEN]; @@ -1619,7 +1618,7 @@ ieee80211_ioctl_macmac(struct ieee80211v return 0; } -static __noinline int +static int ieee80211_ioctl_setmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq) { const struct ieee80211_aclator *acl = vap->iv_acl; @@ -1657,7 +1656,7 @@ ieee80211_ioctl_setmaccmd(struct ieee802 return 0; } -static __noinline int +static int ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -1703,7 +1702,7 @@ ieee80211_ioctl_setchanlist(struct ieee8 return ENETRESET; } -static __noinline int +static int ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -1729,7 +1728,7 @@ ieee80211_ioctl_setstastats(struct ieee8 return 0; } -static __noinline int +static int ieee80211_ioctl_setstatxpow(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -1749,7 +1748,7 @@ ieee80211_ioctl_setstatxpow(struct ieee8 return error; } -static __noinline int +static int ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -1975,7 +1974,7 @@ setcurchan(struct ieee80211vap *vap, str * Old api for setting the current channel; this is * deprecated because channel numbers are ambiguous. */ -static __noinline int +static int ieee80211_ioctl_setchannel(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -2054,7 +2053,7 @@ ieee80211_ioctl_setchannel(struct ieee80 * channel description is provide so there is no ambiguity in * identifying the channel. */ -static __noinline int +static int ieee80211_ioctl_setcurchan(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -2078,7 +2077,7 @@ ieee80211_ioctl_setcurchan(struct ieee80 return setcurchan(vap, c); } -static __noinline int +static int ieee80211_ioctl_setregdomain(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -2152,7 +2151,7 @@ checkmcs(int mcs) return (mcs & 0x7f) <= 15; /* XXX could search ht rate set */ } -static __noinline int +static int ieee80211_ioctl_settxparams(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -2273,7 +2272,7 @@ setwparsnie(struct ieee80211vap *vap, ui vap->iv_rsn_ie = ie; } -static __noinline int +static int ieee80211_ioctl_setappie_locked(struct ieee80211vap *vap, const struct ieee80211req *ireq, int fc0) { @@ -2351,7 +2350,7 @@ ieee80211_ioctl_setappie_locked(struct i return error; } -static __noinline int +static int ieee80211_ioctl_setappie(struct ieee80211vap *vap, const struct ieee80211req *ireq) { @@ -2369,7 +2368,7 @@ ieee80211_ioctl_setappie(struct ieee8021 return error; } -static __noinline int +static int ieee80211_ioctl_chanswitch(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; @@ -2505,21 +2504,28 @@ ieee80211_scanreq(struct ieee80211vap *v #undef IEEE80211_IOC_SCAN_FLAGS } -static __noinline int +static int ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq) { - struct ieee80211_scan_req sr; /* XXX off stack? */ + struct ieee80211_scan_req *sr; int error; - if (ireq->i_len != sizeof(sr)) + if (ireq->i_len != sizeof(*sr)) return EINVAL; - error = copyin(ireq->i_data, &sr, sizeof(sr)); + sr = IEEE80211_MALLOC(sizeof(*sr), M_TEMP, + IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); + if (sr == NULL) + return ENOMEM; + error = copyin(ireq->i_data, sr, sizeof(*sr)); if (error != 0) - return error; - return ieee80211_scanreq(vap, &sr); + goto bad; + error = ieee80211_scanreq(vap, sr); +bad: + IEEE80211_FREE(sr, M_TEMP); + return error; } -static __noinline int +static int ieee80211_ioctl_setstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -2583,7 +2589,7 @@ ieee80211_ioctl_setdefault(struct ieee80 return EINVAL; } -static __noinline int +static int ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic;