Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70bae382 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Greg Kroah-Hartman
Browse files

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: 8c5af16f ("staging: rtl8712: reduce stack usage")
Fixes: 81a56f6dcd20 ("gcc-plugins: structleak: Generalize to all variable types")
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b46475ec
Loading
Loading
Loading
Loading
+88 −69
Original line number Diff line number Diff line
@@ -141,7 +141,88 @@ static inline void handle_group_key(struct ieee_param *param,
	}
}

static noinline_for_stack char *translate_scan(struct _adapter *padapter,
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)
@@ -257,73 +338,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);
		}
	}
	start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);

	{ /* parsing WPS IE */
		u8 wps_ie[512];
		uint wps_ielen;
	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);