Commit 11b2357d authored by Karl Beldan's avatar Karl Beldan Committed by Johannes Berg

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: default avatarKarl Beldan <karl.beldan@rivierawaves.com>
Acked-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c7abf25a
...@@ -62,14 +62,14 @@ minstrel_stats_open(struct inode *inode, struct file *file) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment