Subject: [PATCH 18/18] sadump: check if given cpu is online in per-cpu related helper functions This is a backport of http://lists.infradead.org/pipermail/kexec/2012-February/006072.html Per-cpu helper functions sanity check given cpu ids if they are not-minus and less than the maximal but it should have checked if they are online. By this mistake, one cannot see generated vmcore correctly if sadump collects vmcore when some cpus are offline e.g. using cpu hotplug or panic and so all the cpus except for a unique CPU halting. Signed-off-by: HATAYAMA Daisuke --- diff -Nrup kexec-tools-2.0.0.old/makedumpfile-1.3.5/sadump_info.c kexec-tools-2.0.0/makedumpfile-1.3.5/sadump_info.c --- kexec-tools-2.0.0.old/makedumpfile-1.3.5/sadump_info.c 2012-04-18 04:08:29.003041051 -0400 +++ kexec-tools-2.0.0/makedumpfile-1.3.5/sadump_info.c 2012-04-18 04:12:27.016191380 -0400 @@ -44,7 +44,7 @@ KEXEC_CORE_NOTE_DESC_BYTES ) #define for_each_online_cpu(cpu) \ - for (cpu = 0; cpu < BITPERBYTE * si->cpumask_size; ++cpu) \ + for (cpu = 0; cpu < max_mask_cpu(); ++cpu) \ if (is_online_cpu(cpu)) enum { @@ -93,6 +93,7 @@ static int read_sadump_header_diskset(in static unsigned long long pfn_to_block(unsigned long long pfn); static int lookup_diskset(unsigned long long whole_offset, int *diskid, unsigned long long *disk_offset); +static int max_mask_cpu(void); static int cpu_online_mask_init(void); static int per_cpu_init(void); static int get_data_from_elf_note_desc(const char *note_buf, uint32_t n_descsz, @@ -799,6 +800,12 @@ sadump_initialize_bitmap_memory(void) } static int +max_mask_cpu(void) +{ + return BITPERBYTE * si->cpumask_size; +} + +static int cpu_online_mask_init(void) { ulong cpu_online_mask_addr; @@ -1289,6 +1296,9 @@ is_online_cpu(int cpu) { unsigned long mask; + if (cpu < 0 || cpu >= max_mask_cpu()) + return FALSE; + mask = ULONG(si->cpu_online_mask_buf + (cpu / BITPERWORD) * sizeof(unsigned long)); @@ -1300,7 +1310,7 @@ legacy_per_cpu_ptr(unsigned long ptr, in { unsigned long addr; - if (cpu < 0 || cpu >= info->nr_cpus) + if (!is_online_cpu(cpu)) return 0UL; if (!readmem(VADDR, ~ptr + cpu*sizeof(unsigned long), &addr, @@ -1313,7 +1323,7 @@ legacy_per_cpu_ptr(unsigned long ptr, in static unsigned long per_cpu_ptr(unsigned long ptr, int cpu) { - if (cpu < 0 || cpu >= info->nr_cpus) + if (!is_online_cpu(cpu)) return 0UL; if (si->__per_cpu_offset[cpu] == si->__per_cpu_load) @@ -1329,7 +1339,7 @@ get_prstatus_from_crash_notes(int cpu, c char note_buf[KEXEC_NOTE_BYTES], zero_buf[KEXEC_NOTE_BYTES]; char *prstatus_ptr; - if (cpu < 0 || info->nr_cpus <= cpu) + if (!is_online_cpu(cpu)) return FALSE; if (SYMBOL(crash_notes) == NOT_FOUND_SYMBOL)