[PATCH 3/4] staging: rtl8712: reduce stack usage, again

From: Arnd Bergmann
Date: Fri Jun 28 2019 - 08:40:39 EST


An earlier patch I sent reduced the stack usage enough to get
below the warning limit, and I could show this was safe, but with
GCC_PLUGIN_STRUCTLEAK_BYREF_ALL, it gets worse again because large stack
variables in the same function no longer overlap:

drivers/staging/rtl8712/rtl871x_ioctl_linux.c: In function 'translate_scan.isra.2':
drivers/staging/rtl8712/rtl871x_ioctl_linux.c:322:1: error: the frame size of 1200 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]

Split out the largest two blocks in the affected function into two
separate functions and mark those noinline_for_stack.

Fixes: 8c5af16f7953 ("staging: rtl8712: reduce stack usage")
Fixes: 81a56f6dcd20 ("gcc-plugins: structleak: Generalize to all variable types")
Signed-off-by: Arnd Bergmann <arnd@xxxxxxxx>
---
drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 157 ++++++++++--------
1 file changed, 88 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index a224797cd993..fdc1df99d852 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -124,10 +124,91 @@ static inline void handle_group_key(struct ieee_param *param,
}
}

-static noinline_for_stack char *translate_scan(struct _adapter *padapter,
- struct iw_request_info *info,
- struct wlan_network *pnetwork,
- char *start, char *stop)
+static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
+ struct wlan_network *pnetwork,
+ struct iw_event *iwe,
+ char *start, char *stop)
+{
+ /* parsing WPA/WPA2 IE */
+ u8 buf[MAX_WPA_IE_LEN];
+ u8 wpa_ie[255], rsn_ie[255];
+ u16 wpa_len = 0, rsn_len = 0;
+ int n, i;
+
+ r8712_get_sec_ie(pnetwork->network.IEs,
+ pnetwork->network.IELength, rsn_ie, &rsn_len,
+ wpa_ie, &wpa_len);
+ if (wpa_len > 0) {
+ memset(buf, 0, MAX_WPA_IE_LEN);
+ n = sprintf(buf, "wpa_ie=");
+ for (i = 0; i < wpa_len; i++) {
+ n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+ "%02x", wpa_ie[i]);
+ if (n >= MAX_WPA_IE_LEN)
+ break;
+ }
+ memset(iwe, 0, sizeof(*iwe));
+ iwe->cmd = IWEVCUSTOM;
+ iwe->u.data.length = (u16)strlen(buf);
+ start = iwe_stream_add_point(info, start, stop,
+ iwe, buf);
+ memset(iwe, 0, sizeof(*iwe));
+ iwe->cmd = IWEVGENIE;
+ iwe->u.data.length = (u16)wpa_len;
+ start = iwe_stream_add_point(info, start, stop,
+ iwe, wpa_ie);
+ }
+ if (rsn_len > 0) {
+ memset(buf, 0, MAX_WPA_IE_LEN);
+ n = sprintf(buf, "rsn_ie=");
+ for (i = 0; i < rsn_len; i++) {
+ n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
+ "%02x", rsn_ie[i]);
+ if (n >= MAX_WPA_IE_LEN)
+ break;
+ }
+ memset(iwe, 0, sizeof(*iwe));
+ iwe->cmd = IWEVCUSTOM;
+ iwe->u.data.length = strlen(buf);
+ start = iwe_stream_add_point(info, start, stop,
+ iwe, buf);
+ memset(iwe, 0, sizeof(*iwe));
+ iwe->cmd = IWEVGENIE;
+ iwe->u.data.length = rsn_len;
+ start = iwe_stream_add_point(info, start, stop, iwe,
+ rsn_ie);
+ }
+
+ return start;
+}
+
+static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info,
+ struct wlan_network *pnetwork,
+ struct iw_event *iwe,
+ char *start, char *stop)
+{
+ /* parsing WPS IE */
+ u8 wps_ie[512];
+ uint wps_ielen;
+
+ if (r8712_get_wps_ie(pnetwork->network.IEs,
+ pnetwork->network.IELength,
+ wps_ie, &wps_ielen)) {
+ if (wps_ielen > 2) {
+ iwe->cmd = IWEVGENIE;
+ iwe->u.data.length = (u16)wps_ielen;
+ start = iwe_stream_add_point(info, start, stop,
+ iwe, wps_ie);
+ }
+ }
+
+ return start;
+}
+
+static char *translate_scan(struct _adapter *padapter,
+ struct iw_request_info *info,
+ struct wlan_network *pnetwork,
+ char *start, char *stop)
{
struct iw_event iwe;
struct ieee80211_ht_cap *pht_capie;
@@ -240,73 +321,11 @@ static noinline_for_stack char *translate_scan(struct _adapter *padapter,
/* Check if we added any event */
if ((current_val - start) > iwe_stream_lcp_len(info))
start = current_val;
- /* parsing WPA/WPA2 IE */
- {
- u8 buf[MAX_WPA_IE_LEN];
- u8 wpa_ie[255], rsn_ie[255];
- u16 wpa_len = 0, rsn_len = 0;
- int n;
-
- r8712_get_sec_ie(pnetwork->network.IEs,
- pnetwork->network.IELength, rsn_ie, &rsn_len,
- wpa_ie, &wpa_len);
- if (wpa_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "wpa_ie=");
- for (i = 0; i < wpa_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", wpa_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
- break;
- }
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = (u16)strlen(buf);
- start = iwe_stream_add_point(info, start, stop,
- &iwe, buf);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wpa_len;
- start = iwe_stream_add_point(info, start, stop,
- &iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "rsn_ie=");
- for (i = 0; i < rsn_len; i++) {
- n += snprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", rsn_ie[i]);
- if (n >= MAX_WPA_IE_LEN)
- break;
- }
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVCUSTOM;
- iwe.u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop,
- &iwe, buf);
- memset(&iwe, 0, sizeof(iwe));
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, &iwe,
- rsn_ie);
- }
- }

- { /* parsing WPS IE */
- u8 wps_ie[512];
- uint wps_ielen;
+ start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);
+
+ start = translate_scan_wps(info, pnetwork, &iwe, start, stop);

- if (r8712_get_wps_ie(pnetwork->network.IEs,
- pnetwork->network.IELength,
- wps_ie, &wps_ielen)) {
- if (wps_ielen > 2) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop,
- &iwe, wps_ie);
- }
- }
- }
/* Add quality statistics */
iwe.cmd = IWEVQUAL;
rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
--
2.20.0