svn commit: r343035 - stable/11/sys/net80211

Andriy Voskoboinyk avos at FreeBSD.org
Tue Jan 15 02:16:24 UTC 2019


Author: avos
Date: Tue Jan 15 02:16:23 2019
New Revision: 343035
URL: https://svnweb.freebsd.org/changeset/base/343035

Log:
  MFC r342966:
  net80211: fix possible panic for some drivers after r342464
  
  Check if rate control structures were allocated before trying to
  access them in various places; this was possible before on
  allocation failure (unlikely), but was revealed after r342211
  where allocation was deferred.
  
  In case if driver uses wlan_amrr(4) and it is loaded it
  is possible to reproduce the panic via
  
  sysctl net.wlan.<number>.rate_stats
  
  (for wlan0 the number will be 0).
  
  The patch was adjusted a bit since file contents are different enough
  since r306591.

Modified:
  stable/11/sys/net80211/ieee80211_amrr.c
  stable/11/sys/net80211/ieee80211_rssadapt.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/net80211/ieee80211_amrr.c
==============================================================================
--- stable/11/sys/net80211/ieee80211_amrr.c	Tue Jan 15 02:09:32 2019	(r343034)
+++ stable/11/sys/net80211/ieee80211_amrr.c	Tue Jan 15 02:16:23 2019	(r343035)
@@ -104,6 +104,9 @@ amrr_setinterval(const struct ieee80211vap *vap, int m
 	struct ieee80211_amrr *amrr = vap->iv_rs;
 	int t;
 
+	if (!amrr)
+		return;
+
 	if (msecs < 100)
 		msecs = 100;
 	t = msecs_to_ticks(msecs);
@@ -166,6 +169,12 @@ amrr_node_init(struct ieee80211_node *ni)
 	struct ieee80211_amrr_node *amn;
 	uint8_t rate;
 
+	if (!amrr) {
+		if_printf(vap->iv_ifp, "ratectl structure was not allocated, "
+		    "per-node structure allocation skipped\n");
+		return;
+	}
+
 	if (ni->ni_rctls == NULL) {
 		ni->ni_rctls = amn = IEEE80211_MALLOC(sizeof(struct ieee80211_amrr_node),
 		    M_80211_RATECTL, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
@@ -327,10 +336,19 @@ static int
 amrr_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
 {
 	struct ieee80211_amrr_node *amn = ni->ni_rctls;
-	struct ieee80211_amrr *amrr = amn->amn_amrr;
+	struct ieee80211_amrr *amrr;
 	const struct ieee80211_rateset *rs = NULL;
 	int rix;
 
+	/* XXX should return -1 here, but drivers may not expect this... */
+	if (!amn)
+	{
+		ni->ni_txrate = ni->ni_rates.rs_rates[0];
+		return 0;
+	}
+
+	amrr = amn->amn_amrr;
+
 	/* 11n or not? Pick the right rateset */
 	if (amrr_node_is_11n(ni)) {
 		/* XXX ew */
@@ -370,6 +388,9 @@ amrr_tx_complete(const struct ieee80211vap *vap,
 	struct ieee80211_amrr_node *amn = ni->ni_rctls;
 	int retries = *(int *)arg1;
 
+	if (!amn)
+		return;
+
 	amn->amn_txcnt++;
 	if (ok)
 		amn->amn_success++;
@@ -398,9 +419,12 @@ amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
 {
 	struct ieee80211vap *vap = arg1;
 	struct ieee80211_amrr *amrr = vap->iv_rs;
-	int msecs = ticks_to_msecs(amrr->amrr_interval);
-	int error;
+	int msecs, error;
 
+	if (!amrr)
+		return ENOMEM;
+
+	msecs = ticks_to_msecs(amrr->amrr_interval);
 	error = sysctl_handle_int(oidp, &msecs, 0, req);
 	if (error || !req->newptr)
 		return error;
@@ -414,6 +438,9 @@ amrr_sysctlattach(struct ieee80211vap *vap,
 {
 	struct ieee80211_amrr *amrr = vap->iv_rs;
 
+	if (!amrr)
+		return;
+
 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 	    "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap,
 	    0, amrr_sysctl_interval, "I", "amrr operation interval (ms)");
@@ -434,6 +461,9 @@ amrr_node_stats(struct ieee80211_node *ni, struct sbuf
 	struct ieee80211_rateset *rs;
 
 	/* XXX TODO: check locking? */
+
+	if (!amn)
+		return;
 
 	/* XXX TODO: this should be a method */
 	if (amrr_node_is_11n(ni)) {

Modified: stable/11/sys/net80211/ieee80211_rssadapt.c
==============================================================================
--- stable/11/sys/net80211/ieee80211_rssadapt.c	Tue Jan 15 02:09:32 2019	(r343034)
+++ stable/11/sys/net80211/ieee80211_rssadapt.c	Tue Jan 15 02:16:23 2019	(r343035)
@@ -118,6 +118,9 @@ rssadapt_setinterval(const struct ieee80211vap *vap, i
 	struct ieee80211_rssadapt *rs = vap->iv_rs;
 	int t;
 
+	if (!rs)
+		return;
+
 	if (msecs < 100)
 		msecs = 100;
 	t = msecs_to_ticks(msecs);
@@ -176,6 +179,12 @@ rssadapt_node_init(struct ieee80211_node *ni)
 	struct ieee80211_rssadapt *rsa = vap->iv_rs;
 	const struct ieee80211_rateset *rs = &ni->ni_rates;
 
+	if (!rsa) {
+		if_printf(vap->iv_ifp, "ratectl structure was not allocated, "
+		    "per-node structure allocation skipped\n");
+		return;
+	}
+
 	if (ni->ni_rctls == NULL) {
 		ni->ni_rctls = ra = 
 		    IEEE80211_MALLOC(sizeof(struct ieee80211_rssadapt_node),
@@ -230,10 +239,18 @@ rssadapt_rate(struct ieee80211_node *ni, void *arg __u
 {
 	struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
 	u_int pktlen = iarg;
-	const struct ieee80211_rateset *rs = &ra->ra_rates;
+	const struct ieee80211_rateset *rs;
 	uint16_t (*thrs)[IEEE80211_RATE_SIZE];
 	int rix, rssi;
 
+	/* XXX should return -1 here, but drivers may not expect this... */
+	if (!ra)
+	{
+		ni->ni_txrate = ni->ni_rates.rs_rates[0];
+		return 0;
+	}
+
+	rs = &ra->ra_rates;
 	if ((ticks - ra->ra_ticks) > ra->ra_rs->interval) {
 		rssadapt_updatestats(ra);
 		ra->ra_ticks = ticks;
@@ -319,6 +336,9 @@ rssadapt_tx_complete(const struct ieee80211vap *vap,
 	struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
 	int pktlen = *(int *)arg1, rssi = *(int *)arg2;
 
+	if (!ra)
+		return;
+
 	if (success) {
 		ra->ra_nok++;
 		if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates &&
@@ -335,9 +355,12 @@ rssadapt_sysctl_interval(SYSCTL_HANDLER_ARGS)
 {
 	struct ieee80211vap *vap = arg1;
 	struct ieee80211_rssadapt *rs = vap->iv_rs;
-	int msecs = ticks_to_msecs(rs->interval);
-	int error;
+	int msecs, error;
 
+	if (!rs)
+		return ENOMEM;
+
+	msecs = ticks_to_msecs(rs->interval);
 	error = sysctl_handle_int(oidp, &msecs, 0, req);
 	if (error || !req->newptr)
 		return error;


More information about the svn-src-all mailing list