mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
mac80211: minstrels: fix buffer overflow in HT debugfs rc_stats
ATM an HT rc_stats line is 106 chars. Times 8(MCS_GROUP_RATES)*3(SS)*2(GI)*2(BW) + CCK(4), i.e. x100, this is well above the current 8192 - sizeof(*ms) currently allocated. Fix this by squeezing the output as follows (not that we're short on memory but this also improves readability and range, the new format adds one more digit to *ok/*cum and ok/cum): - Before (HT) (106 ch): type rate throughput ewma prob this prob retry this succ/attempt success attempts CCK/LP 5.5M 0.0 0.0 0.0 0 0( 0) 0 0 HT20/LGI ABCDP MCS0 0.0 0.0 0.0 1 0( 0) 0 0 - After (75 ch): type rate tpt eprob *prob ret *ok(*cum) ok( cum) CCK/LP 5.5M 0.0 0.0 0.0 0 0( 0) 0( 0) HT20/LGI ABCDP MCS0 0.0 0.0 0.0 1 0( 0) 0( 0) - Align non-HT format Before (non-HT) (83 ch): rate throughput ewma prob this prob this succ/attempt success attempts ABCDP 6 0.0 0.0 0.0 0( 0) 0 0 54 0.0 0.0 0.0 0( 0) 0 0 - After (61 ch): rate tpt eprob *prob *ok(*cum) ok( cum) ABCDP 1 0.0 0.0 0.0 0( 0) 0( 0) 54 0.0 0.0 0.0 0( 0) 0( 0) *This also adds dynamic checks for overflow, lowers the size of the non-HT request (allowing > 30 entries) and replaces the buddy-rounded allocations (s/sizeof(*ms) + 8192/8192). Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com> Acked-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c7abf25af0
commit
11b2357d5d
@ -62,14 +62,14 @@ minstrel_stats_open(struct inode *inode, struct file *file)
|
|||||||
unsigned int i, tp, prob, eprob;
|
unsigned int i, tp, prob, eprob;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL);
|
ms = kmalloc(2048, GFP_KERNEL);
|
||||||
if (!ms)
|
if (!ms)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
file->private_data = ms;
|
file->private_data = ms;
|
||||||
p = ms->buf;
|
p = ms->buf;
|
||||||
p += sprintf(p, "rate throughput ewma prob this prob "
|
p += sprintf(p, "rate tpt eprob *prob"
|
||||||
"this succ/attempt success attempts\n");
|
" *ok(*cum) ok( cum)\n");
|
||||||
for (i = 0; i < mi->n_rates; i++) {
|
for (i = 0; i < mi->n_rates; i++) {
|
||||||
struct minstrel_rate *mr = &mi->r[i];
|
struct minstrel_rate *mr = &mi->r[i];
|
||||||
struct minstrel_rate_stats *mrs = &mi->r[i].stats;
|
struct minstrel_rate_stats *mrs = &mi->r[i].stats;
|
||||||
@ -86,8 +86,8 @@ minstrel_stats_open(struct inode *inode, struct file *file)
|
|||||||
prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
|
||||||
eprob = MINSTREL_TRUNC(mrs->probability * 1000);
|
eprob = MINSTREL_TRUNC(mrs->probability * 1000);
|
||||||
|
|
||||||
p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
|
p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u"
|
||||||
" %3u(%3u) %8llu %8llu\n",
|
" %4u(%4u) %9llu(%9llu)\n",
|
||||||
tp / 10, tp % 10,
|
tp / 10, tp % 10,
|
||||||
eprob / 10, eprob % 10,
|
eprob / 10, eprob % 10,
|
||||||
prob / 10, prob % 10,
|
prob / 10, prob % 10,
|
||||||
@ -102,6 +102,8 @@ minstrel_stats_open(struct inode *inode, struct file *file)
|
|||||||
mi->sample_packets);
|
mi->sample_packets);
|
||||||
ms->len = p - ms->buf;
|
ms->len = p - ms->buf;
|
||||||
|
|
||||||
|
WARN_ON(ms->len + sizeof(*ms) > 2048);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
|
|||||||
prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
|
prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
|
||||||
eprob = MINSTREL_TRUNC(mr->probability * 1000);
|
eprob = MINSTREL_TRUNC(mr->probability * 1000);
|
||||||
|
|
||||||
p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
|
p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u "
|
||||||
"%3u %3u(%3u) %8llu %8llu\n",
|
"%3u %4u(%4u) %9llu(%9llu)\n",
|
||||||
tp / 10, tp % 10,
|
tp / 10, tp % 10,
|
||||||
eprob / 10, eprob % 10,
|
eprob / 10, eprob % 10,
|
||||||
prob / 10, prob % 10,
|
prob / 10, prob % 10,
|
||||||
@ -96,14 +96,15 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL);
|
ms = kmalloc(8192, GFP_KERNEL);
|
||||||
if (!ms)
|
if (!ms)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
file->private_data = ms;
|
file->private_data = ms;
|
||||||
p = ms->buf;
|
p = ms->buf;
|
||||||
p += sprintf(p, "type rate throughput ewma prob "
|
p += sprintf(p, "type rate tpt eprob *prob "
|
||||||
"this prob retry this succ/attempt success attempts\n");
|
"ret *ok(*cum) ok( cum)\n");
|
||||||
|
|
||||||
|
|
||||||
p = minstrel_ht_stats_dump(mi, max_mcs, p);
|
p = minstrel_ht_stats_dump(mi, max_mcs, p);
|
||||||
for (i = 0; i < max_mcs; i++)
|
for (i = 0; i < max_mcs; i++)
|
||||||
@ -118,6 +119,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
|
|||||||
MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
|
MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
|
||||||
ms->len = p - ms->buf;
|
ms->len = p - ms->buf;
|
||||||
|
|
||||||
|
WARN_ON(ms->len + sizeof(*ms) > 8192);
|
||||||
|
|
||||||
return nonseekable_open(inode, file);
|
return nonseekable_open(inode, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user