irqbalance/irqbalance-prevent-NULL-pointer-dereference-in-do_on.patch

155 lines
4.2 KiB
Diff
Raw Normal View History

2020-07-03 17:09:39 +08:00
From c2d1429ba289e9cea76dd08e24e2d40af3ab0435 Mon Sep 17 00:00:00 2001
From: Yunfeng Ye <yeyunfeng@huawei.com>
Date: Thu, 31 Oct 2019 00:39:11 +0800
Subject: [PATCH 36/53] irqbalance: prevent NULL pointer dereference in
do_one_cpu()
add_cpu_to_cache_domain() will return NULL if memory allocation failure,
so check the return value before invoking add_cache_domain_to_package(),
and add a global variable need_rebuild to check this situation, if
need_rebuild is set, then invoke free_object_tree() and try again a few
times, if it still fail, then return scan().
In addition, also set need_rebuild where calloc fails throughout the
build_object_tree process.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
cputree.c | 16 +++++++++++-----
irqbalance.c | 19 ++++++++++++++++---
irqbalance.h | 1 +
numa.c | 4 +++-
4 files changed, 31 insertions(+), 9 deletions(-)
diff --git a/cputree.c b/cputree.c
index c1b4950..6bbc2cb 100644
--- a/cputree.c
+++ b/cputree.c
@@ -176,8 +176,10 @@ static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache,
if (!entry) {
package = calloc(1, sizeof(struct topo_obj));
- if (!package)
+ if (!package) {
+ need_rebuild = 1;
return NULL;
+ }
package->mask = package_mask;
package->obj_type = OBJ_TYPE_PACKAGE;
package->obj_type_list = &packages;
@@ -214,8 +216,10 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu,
if (!entry) {
cache = calloc(1, sizeof(struct topo_obj));
- if (!cache)
+ if (!cache) {
+ need_rebuild = 1;
return NULL;
+ }
cache->obj_type = OBJ_TYPE_CACHE;
cache->mask = cache_mask;
cache->number = cache_domain_count;
@@ -271,8 +275,10 @@ static void do_one_cpu(char *path)
return;
cpu = calloc(1, sizeof(struct topo_obj));
- if (!cpu)
+ if (!cpu) {
+ need_rebuild = 1;
return;
+ }
cpu->obj_type = OBJ_TYPE_CPU;
@@ -372,8 +378,8 @@ static void do_one_cpu(char *path)
cpus_and(package_mask, package_mask, unbanned_cpus);
cache = add_cpu_to_cache_domain(cpu, cache_mask, nodeid);
- add_cache_domain_to_package(cache, packageid, package_mask,
- nodeid);
+ if (cache)
+ add_cache_domain_to_package(cache, packageid, package_mask, nodeid);
cpu->obj_type_list = &cpus;
cpus = g_list_append(cpus, cpu);
diff --git a/irqbalance.c b/irqbalance.c
index 3ff5f13..619f51f 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -52,6 +52,7 @@ int foreground_mode;
int numa_avail;
int journal_logging = 0;
int need_rescan;
+int need_rebuild;
unsigned int log_mask = TO_ALL;
const char *log_indent;
unsigned long power_thresh = ULONG_MAX;
@@ -260,14 +261,25 @@ gboolean scan(gpointer data __attribute__((unused)))
/* cope with cpu hotplug -- detected during /proc/interrupts parsing */
- if (need_rescan) {
+ if (need_rescan || need_rebuild) {
+ int try_times = 0;
+
need_rescan = 0;
cycle_count = 0;
log(TO_CONSOLE, LOG_INFO, "Rescanning cpu topology \n");
clear_work_stats();
- free_object_tree();
- build_object_tree();
+ do {
+ free_object_tree();
+ if (++try_times > 3) {
+ log(TO_CONSOLE, LOG_WARNING, "Rescanning cpu topology: fail\n");
+ goto out;
+ }
+
+ need_rebuild = 0;
+ build_object_tree();
+ } while (need_rebuild);
+
for_each_irq(NULL, force_rebalance_irq, NULL);
parse_proc_interrupts();
parse_proc_stat();
@@ -284,6 +296,7 @@ gboolean scan(gpointer data __attribute__((unused)))
calculate_placement();
activate_mappings();
+out:
if (debug_mode)
dump_tree();
if (one_shot_mode)
diff --git a/irqbalance.h b/irqbalance.h
index 62c7151..79f5450 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -67,6 +67,7 @@ extern int debug_mode;
extern int journal_logging;
extern int one_shot_mode;
extern int need_rescan;
+extern int need_rebuild;
extern unsigned long long cycle_count;
extern unsigned long power_thresh;
extern unsigned long deepest_cache;
diff --git a/numa.c b/numa.c
index e76b6e0..9d55784 100644
--- a/numa.c
+++ b/numa.c
@@ -58,8 +58,10 @@ static void add_one_node(const char *nodename)
struct topo_obj *new;
new = calloc(1, sizeof(struct topo_obj));
- if (!new)
+ if (!new) {
+ need_rebuild = 1;
return;
+ }
cpus_clear(new->mask);
sprintf(path, "%s/%s/cpumap", SYSFS_NODE_PATH, nodename);
--
2.23.0