staging: rtl8712: reduce stack usage, again
authorArnd Bergmann <arnd@arndb.de>
Fri, 28 Jun 2019 12:37:48 +0000 (14:37 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Jun 2019 12:54:45 +0000 (14:54 +0200)
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@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rtl8712/rtl871x_ioctl_linux.c

index a224797..fdc1df9 100644 (file)
@@ -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);