staging: rtl8712: reduce stack usage, again [Linux 5.2.1]

staging: rtl8712: reduce stack usage, again [Linux 5.2.1]

This Linux kernel change "staging: rtl8712: reduce stack usage, again" is included in the Linux 5.2.1 release. This change is authored by Arnd Bergmann <arnd [at] arndb.de> on Fri Jun 28 14:37:48 2019 +0200. The commit for this change in Linux stable tree is 090ce9c (patch) which is from upstream commit fbd6b25. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream fbd6b25.

staging: rtl8712: reduce stack usage, again

commit fbd6b25009ac76b2034168cd21d5e01f8c2d83d1 upstream.

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>

There are 157 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 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 a7230c0..8f5a8ac 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);

Leave a Reply

Your email address will not be published. Required fields are marked *