[Crash-utility] [PATCH] Fix for an abort in vm_stat_init() without CONFIG_NUMA

Kazuhito Hagio k-hagio at ab.jp.nec.com
Wed Aug 22 15:12:33 UTC 2018


With recent kernels without CONFIG_NUMA (including Fedora 32-bit),
the vm_stat_init() function aborts when getting numa_stat_item
enum items, (probably) because it is not defined.

  crash> kmem -V
  double free or corruption (!prev)
  Aborted (core dumped) 

We can avoid the abort by checking whether the length of the
vm_numa_stat array is also not zero.

This patch tested OK with the following kernels:
  4.17.0-0.rc5.git3.1.fc29.i686
  4.18.0-0.rc5.git4.1.fc29.x86_64
  3.10.0-862.el7.x86_64

Signed-off-by: Kazuhito Hagio <k-hagio at ab.jp.nec.com>
---
 defs.h    |  1 +
 memory.c  | 10 ++++++----
 symbols.c |  4 ++++
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/defs.h b/defs.h
index f569a62..6fdb478 100644
--- a/defs.h
+++ b/defs.h
@@ -2220,6 +2220,7 @@ struct array_table {
 	int height_to_maxnodes;
 	int task_struct_rlim;
 	int signal_struct_rlim;
+	int vm_numa_stat;
 };
 
 /*
diff --git a/memory.c b/memory.c
index 7c0cb5f..e02ba68 100644
--- a/memory.c
+++ b/memory.c
@@ -17454,11 +17454,12 @@ vm_stat_init(void)
 		} else if (symbol_exists("vm_zone_stat") &&
 			get_symbol_type("vm_zone_stat",
 			NULL, NULL) == TYPE_CODE_ARRAY) {
-			if (symbol_exists("vm_numa_stat")) {
+			if (symbol_exists("vm_numa_stat") &&
+			    get_array_length("vm_numa_stat", NULL, 0)) {
 				vt->nr_vm_stat_items =
 					get_array_length("vm_zone_stat", NULL, 0)
 					+ get_array_length("vm_node_stat", NULL, 0) 
-					+ get_array_length("vm_numa_stat", NULL, 0);
+					+ ARRAY_LENGTH(vm_numa_stat);
 				split_vmstat = 2;
 				enumerator_value("NR_VM_ZONE_STAT_ITEMS", &zone_cnt);
 				enumerator_value("NR_VM_NODE_STAT_ITEMS", &node_cnt);
@@ -17599,7 +17600,7 @@ dump_vm_stat(char *item, long *retval, ulong zone)
 	buf = GETBUF(sizeof(ulong) * vt->nr_vm_stat_items);
 
 	if (symbol_exists("vm_node_stat") && symbol_exists("vm_zone_stat") &&
-	    symbol_exists("vm_numa_stat"))
+	    symbol_exists("vm_numa_stat") && ARRAY_LENGTH(vm_numa_stat))
 		split_vmstat = 2;
 	else if (symbol_exists("vm_node_stat") && symbol_exists("vm_zone_stat"))
 		split_vmstat = 1;
@@ -17666,7 +17667,8 @@ dump_vm_stat(char *item, long *retval, ulong zone)
 			if (!zone) {
 				if ((i == node_start) && symbol_exists("vm_node_stat")) 
 					fprintf(fp, "\n  VM_NODE_STAT:\n"); 
-				if ((i == numa_start) && symbol_exists("vm_numa_stat")) 
+				if ((i == numa_start) && symbol_exists("vm_numa_stat")
+				    && ARRAY_LENGTH(vm_numa_stat))
 					fprintf(fp, "\n  VM_NUMA_STAT:\n"); 
 			}
 			fprintf(fp, "%s%s: %ld\n",
diff --git a/symbols.c b/symbols.c
index df84ee2..bee60ba 100644
--- a/symbols.c
+++ b/symbols.c
@@ -8457,6 +8457,8 @@ builtin_array_length(char *s, int len, int *two_dim)
 		lenptr = &array_table.task_struct_rlim;
 	else if (STREQ(s, "signal_struct.rlim"))
 		lenptr = &array_table.signal_struct_rlim;
+	else if (STREQ(s, "vm_numa_stat"))
+		lenptr = &array_table.vm_numa_stat;
 
 	if (!lenptr)                /* not stored */
 		return(len);        
@@ -10594,6 +10596,8 @@ dump_offset_table(char *spec, ulong makestruct)
 		ARRAY_LENGTH(task_struct_rlim));
 	fprintf(fp, "            signal_struct_rlim: %d\n",
 		ARRAY_LENGTH(signal_struct_rlim));
+	fprintf(fp, "                  vm_numa_stat: %d\n",
+		ARRAY_LENGTH(vm_numa_stat));
 
 	if (spec) {
 		int in_size_table, in_array_table, arrays, offsets, sizes;
-- 
1.8.3.1




More information about the Crash-utility mailing list