mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
cpufreq: stats: Fix buffer overflow detection in trans_stats()
Commit3c0897c180
("cpufreq: Use scnprintf() for avoiding potential buffer overflow") switched from snprintf to the more secure scnprintf but never updated the exit condition for PAGE_SIZE. As the commit say and as scnprintf document, what scnprintf returns what is actually written not counting the '\0' end char. This results in the case of len exceeding the size, len set to PAGE_SIZE - 1, as it can be written at max PAGE_SIZE - 1 (as '\0' is not counted) Because of len is never set to PAGE_SIZE, the function never break early, never prints the warning and never return -EFBIG. Fix this by changing the condition to PAGE_SIZE - 1 to correctly trigger the error. Cc: 5.10+ <stable@vger.kernel.org> # 5.10+ Fixes:3c0897c180
("cpufreq: Use scnprintf() for avoiding potential buffer overflow") Signed-off-by: Christian Marangi <ansuelsmth@gmail.com> [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
e7a1b32e43
commit
ea167a7fc2
@ -131,23 +131,23 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
|||||||
len += sysfs_emit_at(buf, len, " From : To\n");
|
len += sysfs_emit_at(buf, len, " From : To\n");
|
||||||
len += sysfs_emit_at(buf, len, " : ");
|
len += sysfs_emit_at(buf, len, " : ");
|
||||||
for (i = 0; i < stats->state_num; i++) {
|
for (i = 0; i < stats->state_num; i++) {
|
||||||
if (len >= PAGE_SIZE)
|
if (len >= PAGE_SIZE - 1)
|
||||||
break;
|
break;
|
||||||
len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]);
|
len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]);
|
||||||
}
|
}
|
||||||
if (len >= PAGE_SIZE)
|
if (len >= PAGE_SIZE - 1)
|
||||||
return PAGE_SIZE;
|
return PAGE_SIZE - 1;
|
||||||
|
|
||||||
len += sysfs_emit_at(buf, len, "\n");
|
len += sysfs_emit_at(buf, len, "\n");
|
||||||
|
|
||||||
for (i = 0; i < stats->state_num; i++) {
|
for (i = 0; i < stats->state_num; i++) {
|
||||||
if (len >= PAGE_SIZE)
|
if (len >= PAGE_SIZE - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]);
|
len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]);
|
||||||
|
|
||||||
for (j = 0; j < stats->state_num; j++) {
|
for (j = 0; j < stats->state_num; j++) {
|
||||||
if (len >= PAGE_SIZE)
|
if (len >= PAGE_SIZE - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pending)
|
if (pending)
|
||||||
@ -157,12 +157,12 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
|
|||||||
|
|
||||||
len += sysfs_emit_at(buf, len, "%9u ", count);
|
len += sysfs_emit_at(buf, len, "%9u ", count);
|
||||||
}
|
}
|
||||||
if (len >= PAGE_SIZE)
|
if (len >= PAGE_SIZE - 1)
|
||||||
break;
|
break;
|
||||||
len += sysfs_emit_at(buf, len, "\n");
|
len += sysfs_emit_at(buf, len, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= PAGE_SIZE) {
|
if (len >= PAGE_SIZE - 1) {
|
||||||
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
|
pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n");
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user