summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Asseg <frank.asseg@objecthunter.net>2018-03-12 14:57:06 -0400
committerJiri Kosina <jkosina@suse.cz>2018-03-27 03:51:23 -0400
commit6c59f64b7ecf2bccbe73931d7d573d66ed13b537 (patch)
tree3e0be7a9e2ccb0a8372ab0c3d9c7a1faf882d9a4
parentb903036aad6c46f0c94b3a58c86f7467776a5dcf (diff)
tools/thermal: tmon: fix for segfault
Fixes a segfault occurring when e.g. <TAB> is pressed multiple times in the ncurses tmon application. The segfault is caused by incrementing cur_thermal_record in the main function without checking if it's value reached NR_THERMAL_RECORD immediately. Since the boundary check only occurred in update_thermal_data a race condition existed, which lead to an attempted read beyond the last element of the trec array. The fix was implemented by moving the cur_thermal_record incrementation to the update_thermal_data function using a temporary variable on which the boundary condition is checked before updating cur_thread_record, so that the variable is never incremented beyond the trec array's boundary. It seems the segfault does not occur on every machine: On a HP EliteBook G4 the segfault happens, while it does not happen on a Thinkpad T540p. Signed-off-by: Frank Asseg <frank.asseg@objecthunter.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--tools/thermal/tmon/sysfs.c12
-rw-r--r--tools/thermal/tmon/tmon.c1
2 files changed, 7 insertions, 6 deletions
diff --git a/tools/thermal/tmon/sysfs.c b/tools/thermal/tmon/sysfs.c
index 1c12536f2081..18f523557983 100644
--- a/tools/thermal/tmon/sysfs.c
+++ b/tools/thermal/tmon/sysfs.c
@@ -486,6 +486,7 @@ int zone_instance_to_index(int zone_inst)
486int update_thermal_data() 486int update_thermal_data()
487{ 487{
488 int i; 488 int i;
489 int next_thermal_record = cur_thermal_record + 1;
489 char tz_name[256]; 490 char tz_name[256];
490 static unsigned long samples; 491 static unsigned long samples;
491 492
@@ -495,9 +496,9 @@ int update_thermal_data()
495 } 496 }
496 497
497 /* circular buffer for keeping historic data */ 498 /* circular buffer for keeping historic data */
498 if (cur_thermal_record >= NR_THERMAL_RECORDS) 499 if (next_thermal_record >= NR_THERMAL_RECORDS)
499 cur_thermal_record = 0; 500 next_thermal_record = 0;
500 gettimeofday(&trec[cur_thermal_record].tv, NULL); 501 gettimeofday(&trec[next_thermal_record].tv, NULL);
501 if (tmon_log) { 502 if (tmon_log) {
502 fprintf(tmon_log, "%lu ", ++samples); 503 fprintf(tmon_log, "%lu ", ++samples);
503 fprintf(tmon_log, "%3.1f ", p_param.t_target); 504 fprintf(tmon_log, "%3.1f ", p_param.t_target);
@@ -507,11 +508,12 @@ int update_thermal_data()
507 snprintf(tz_name, 256, "%s/%s%d", THERMAL_SYSFS, TZONE, 508 snprintf(tz_name, 256, "%s/%s%d", THERMAL_SYSFS, TZONE,
508 ptdata.tzi[i].instance); 509 ptdata.tzi[i].instance);
509 sysfs_get_ulong(tz_name, "temp", 510 sysfs_get_ulong(tz_name, "temp",
510 &trec[cur_thermal_record].temp[i]); 511 &trec[next_thermal_record].temp[i]);
511 if (tmon_log) 512 if (tmon_log)
512 fprintf(tmon_log, "%lu ", 513 fprintf(tmon_log, "%lu ",
513 trec[cur_thermal_record].temp[i]/1000); 514 trec[next_thermal_record].temp[i] / 1000);
514 } 515 }
516 cur_thermal_record = next_thermal_record;
515 for (i = 0; i < ptdata.nr_cooling_dev; i++) { 517 for (i = 0; i < ptdata.nr_cooling_dev; i++) {
516 char cdev_name[256]; 518 char cdev_name[256];
517 unsigned long val; 519 unsigned long val;
diff --git a/tools/thermal/tmon/tmon.c b/tools/thermal/tmon/tmon.c
index 9aa19652e8e8..b43138f8b862 100644
--- a/tools/thermal/tmon/tmon.c
+++ b/tools/thermal/tmon/tmon.c
@@ -336,7 +336,6 @@ int main(int argc, char **argv)
336 show_data_w(); 336 show_data_w();
337 show_cooling_device(); 337 show_cooling_device();
338 } 338 }
339 cur_thermal_record++;
340 time_elapsed += ticktime; 339 time_elapsed += ticktime;
341 controller_handler(trec[0].temp[target_tz_index] / 1000, 340 controller_handler(trec[0].temp[target_tz_index] / 1000,
342 &yk); 341 &yk);