[report] staging: r8723au: rtw_report_sec_ie23a() is buggy

Dan Carpenter dan.carpenter at oracle.com
Thu Apr 10 14:20:30 UTC 2014


Hello Larry, Jes,

The rtw_report_sec_ie23a() is very buggy.

1) It uses GFP_KERNEL but the callers are holding a spinlock.

	rtw_select_and_join_from_scanned_queue23a() <- takes lock
	-> rtw_joinbss_cmd23a()
           -> rtw_restruct_sec_ie23a()
              -> rtw_report_sec_ie23a()

2) The sprintf() can overflow because we're putting over 512 characters
   into a IW_CUSTOM_MAX (256) character buffer.

3) It could actually be far worse than 512.  It could be a forever
   loop!  :P  The "i" variable is declared as u8 so it will always be
   less than IW_CUSTOM_MAX (256).

4) What is the point of this function?  It doesn't seem to store "buff"
   anywhere or do anything with "wrqu".

I have included my suggestion for how to start fixing the function but
it's not a complete solution because I don't know the answer to #4.

regards,
dan carpenter

diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
index b30d4d3..6927227 100644
--- a/drivers/staging/rtl8723au/os_dep/mlme_linux.c
+++ b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
@@ -102,42 +102,30 @@ void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter)
 
 void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie)
 {
-	uint	len;
-	u8	*buff, *p, i;
+	char buf[IW_CUSTOM_MAX];
+	int len;
+	int i;
+	int printed = 0;
 	union iwreq_data wrqu;
 
 	RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
 		 ("+rtw_report_sec_ie23a, authmode =%d\n", authmode));
 
-	buff = NULL;
-	if (authmode == _WPA_IE_ID_) {
-		RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
-			 ("rtw_report_sec_ie23a, authmode =%d\n", authmode));
-
-		buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
-		if (!buff)
-			return;
-		p = buff;
-
-		p += sprintf(p, "ASSOCINFO(ReqIEs =");
-
-		len = sec_ie[1]+2;
-		len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
-
-		for (i = 0; i < len; i++)
-			p += sprintf(p, "%02x", sec_ie[i]);
-
-		p += sprintf(p, ")");
-
-		memset(&wrqu, 0, sizeof(wrqu));
-
-		wrqu.data.length = p-buff;
-
-		wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
-				   wrqu.data.length : IW_CUSTOM_MAX;
+	if (authmode != _WPA_IE_ID_)
+		return;
 
-		kfree(buff);
+	printed += sprintf(p, "ASSOCINFO(ReqIEs =");
+	len = min(sec_ie[1] + 2, IW_CUSTOM_MAX);
+	for (i = 0; i < len; i++) {
+		printed += scnprintf(buf + printed, sizeof(buf) - printed,
+				     "%02x", sec_ie[i]);
 	}
+	printed += scnprintf(buf + printed, sizeof(buf) - printed, ")");
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	/* FIXME: store the buf somewhere */
+	wrqu.data.length = printed;
+	/* FIXME: do something with wrqu */
 }
 
 #ifdef CONFIG_8723AU_AP_MODE


More information about the devel mailing list