[PATCH] iwinfo: add guard for scan buffer overflow

Wojciech Jowsa wojciech.jowsa at gmail.com
Mon May 17 01:05:18 PDT 2021


It might happen that driver returns a huge scan results e.g.
when there are many access points available in the area where
scanning is performed. Currently, all scan results are copied
to the buffer, no matter the buffer size.
This adds a guard to prevent buffer overflow i.e. scan buffer can
be filled only to its maximum length. Buffer length can be passed
trough the len argument of the scanlist method.

Signed-off-by: Wojciech Jowsa <wojciech.jowsa at gmail.com>
---
 iwinfo_nl80211.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/iwinfo_nl80211.c b/iwinfo_nl80211.c
index eea521e..b7cf677 100644
--- a/iwinfo_nl80211.c
+++ b/iwinfo_nl80211.c
@@ -2357,6 +2357,7 @@ static void nl80211_get_scancrypto(char *spec, struct iwinfo_crypto_entry *c)
 struct nl80211_scanlist {
 	struct iwinfo_scanlist_entry *e;
 	int len;
+	int maxlen;
 };
 
 
@@ -2435,6 +2436,10 @@ static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
 		[NL80211_BSS_BEACON_IES]           = { 0 },
 	};
 
+	if(sl->maxlen && (sl->len + 1) > sl->maxlen) {
+		return NL_STOP;
+	}
+
 	if (!tb[NL80211_ATTR_BSS] ||
 		nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
 		                 bss_policy) ||
@@ -2496,9 +2501,9 @@ static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg)
 	return NL_SKIP;
 }
 
-static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len)
+static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len, int maxlen)
 {
-	struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf };
+	struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf, .maxlen = maxlen };
 
 	if (nl80211_request(ifname, NL80211_CMD_TRIGGER_SCAN, 0, NULL, NULL))
 		goto out;
@@ -2732,9 +2737,7 @@ static int nl80211_get_scanlist_wpactl(const char *ifname, char *buf, int *len)
 static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 {
 	char *res;
-	int rv, mode;
-
-	*len = 0;
+	int rv, mode, maxlen = *len / sizeof(struct iwinfo_scanlist_entry);
 
 	/* Got a radioX pseudo interface, find some interface on it or create one */
 	if (!strncmp(ifname, "radio", 5))
@@ -2754,6 +2757,8 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 		}
 	}
 
+	*len = 0;
+
 	/* WPA supplicant */
 	if (!nl80211_get_scanlist_wpactl(ifname, buf, len))
 	{
@@ -2768,7 +2773,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 	          mode == IWINFO_OPMODE_MONITOR) &&
 	         iwinfo_ifup(ifname))
 	{
-		return nl80211_get_scanlist_nl(ifname, buf, len);
+		return nl80211_get_scanlist_nl(ifname, buf, len, maxlen);
 	}
 
 	/* AP scan */
@@ -2780,7 +2785,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			if (!iwinfo_ifup(ifname))
 				return -1;
 
-			rv = nl80211_get_scanlist_nl(ifname, buf, len);
+			rv = nl80211_get_scanlist_nl(ifname, buf, len, maxlen);
 			iwinfo_ifdown(ifname);
 			return rv;
 		}
@@ -2797,7 +2802,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			 * additional interface and there's no need to tear down the ap */
 			if (iwinfo_ifup(res))
 			{
-				rv = nl80211_get_scanlist_nl(res, buf, len);
+				rv = nl80211_get_scanlist_nl(res, buf, len, maxlen);
 				iwinfo_ifdown(res);
 			}
 
@@ -2805,7 +2810,7 @@ static int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 			 * during scan */
 			else if (iwinfo_ifdown(ifname) && iwinfo_ifup(res))
 			{
-				rv = nl80211_get_scanlist_nl(res, buf, len);
+				rv = nl80211_get_scanlist_nl(res, buf, len, maxlen);
 				iwinfo_ifdown(res);
 				iwinfo_ifup(ifname);
 				nl80211_hostapd_hup(ifname);
-- 
2.25.1




More information about the openwrt-devel mailing list