mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-02 12:20:51 +00:00
net80211: fix possible panic for some drivers after r342211
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). Tested with: RTL8188EE, AP mode + RTL8188CUS, STA mode. MFC after: 3 days
This commit is contained in:
parent
31afdd6f10
commit
4367c2d177
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342966
@ -104,6 +104,9 @@ amrr_setinterval(const struct ieee80211vap *vap, int msecs)
|
||||
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 */
|
||||
@ -369,6 +387,9 @@ amrr_tx_complete(const struct ieee80211_node *ni,
|
||||
struct ieee80211_amrr_node *amn = ni->ni_rctls;
|
||||
int retries;
|
||||
|
||||
if (!amn)
|
||||
return;
|
||||
|
||||
retries = 0;
|
||||
if (status->flags & IEEE80211_RATECTL_STATUS_LONG_RETRY)
|
||||
retries = status->long_retries;
|
||||
@ -386,6 +407,9 @@ amrr_tx_update_cb(void *arg, struct ieee80211_node *ni)
|
||||
struct ieee80211_amrr_node *amn = ni->ni_rctls;
|
||||
int txcnt, success, retrycnt;
|
||||
|
||||
if (!amn)
|
||||
return;
|
||||
|
||||
txcnt = stats->nframes;
|
||||
success = stats->nsuccess;
|
||||
retrycnt = 0;
|
||||
@ -420,9 +444,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;
|
||||
@ -436,6 +463,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)");
|
||||
@ -457,6 +487,9 @@ amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
|
||||
|
||||
/* XXX TODO: check locking? */
|
||||
|
||||
if (!amn)
|
||||
return;
|
||||
|
||||
/* XXX TODO: this should be a method */
|
||||
if (amrr_node_is_11n(ni)) {
|
||||
rs = (struct ieee80211_rateset *) &ni->ni_htrates;
|
||||
|
@ -119,6 +119,9 @@ rssadapt_setinterval(const struct ieee80211vap *vap, int msecs)
|
||||
struct ieee80211_rssadapt *rs = vap->iv_rs;
|
||||
int t;
|
||||
|
||||
if (!rs)
|
||||
return;
|
||||
|
||||
if (msecs < 100)
|
||||
msecs = 100;
|
||||
t = msecs_to_ticks(msecs);
|
||||
@ -177,6 +180,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),
|
||||
@ -231,10 +240,18 @@ rssadapt_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg)
|
||||
{
|
||||
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;
|
||||
@ -320,6 +337,9 @@ rssadapt_tx_complete(const struct ieee80211_node *ni,
|
||||
struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
|
||||
int pktlen, rssi;
|
||||
|
||||
if (!ra)
|
||||
return;
|
||||
|
||||
if ((status->flags &
|
||||
(IEEE80211_RATECTL_STATUS_PKTLEN|IEEE80211_RATECTL_STATUS_RSSI)) !=
|
||||
(IEEE80211_RATECTL_STATUS_PKTLEN|IEEE80211_RATECTL_STATUS_RSSI))
|
||||
@ -344,9 +364,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;
|
||||
|
Loading…
Reference in New Issue
Block a user