From 5f15256acab27859ececcfda1b882e8c49597697 Mon Sep 17 00:00:00 2001 From: HATAYAMA Daisuke Date: Tue, 20 Oct 2015 16:08:01 +0900 Subject: [PATCH 1/2] [PATCH 1/2] sadump: Change bit order. sadump formats associate each bit in a bitmap with a physical page in reverse order with the kdump-compressed format. We had not detected this bug for considerably long term because bitmaps in sadump formats consist mostly of 0x00 and 0xff excluding a very limited amount of memory space for firmware. Signed-off-by: Takao Indoh Signed-off-by: HATAYAMA Daisuke --- makedumpfile-1.5.7/sadump_info.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/makedumpfile-1.5.7/sadump_info.c b/makedumpfile-1.5.7/sadump_info.c index 23275e2..4740683 100644 --- a/makedumpfile-1.5.7/sadump_info.c +++ b/makedumpfile-1.5.7/sadump_info.c @@ -85,6 +85,7 @@ struct sadump_info { unsigned long long backup_offset; int kdump_backed_up; mdf_pfn_t max_mapnr; + struct dump_bitmap *ram_bitmap; }; static char *guid_to_str(efi_guid_t *guid, char *buf, size_t buflen); @@ -127,6 +128,35 @@ static int get_registers(int cpu, struct elf_prstatus *prstatus); static struct sadump_info sadump_info = {}; static struct sadump_info *si = &sadump_info; +static inline int +sadump_is_on(char *bitmap, mdf_pfn_t i) +{ + return bitmap[i >> 3] & (1 << (7 - (i & 7))); +} + +static inline int +sadump_is_dumpable(struct dump_bitmap *bitmap, mdf_pfn_t pfn) +{ + off_t offset; + + if (pfn == 0 || bitmap->no_block != pfn/PFN_BUFBITMAP) { + offset = bitmap->offset + BUFSIZE_BITMAP*(pfn/PFN_BUFBITMAP); + lseek(bitmap->fd, offset, SEEK_SET); + read(bitmap->fd, bitmap->buf, BUFSIZE_BITMAP); + if (pfn == 0) + bitmap->no_block = 0; + else + bitmap->no_block = pfn / PFN_BUFBITMAP; + } + return sadump_is_on(bitmap->buf, pfn % PFN_BUFBITMAP); +} + +static inline int +sadump_is_ram(mdf_pfn_t pfn) +{ + return sadump_is_dumpable(si->ram_bitmap, pfn); +} + int check_and_get_sadump_header_info(char *filename) { @@ -161,6 +191,21 @@ check_and_get_sadump_header_info(char *filename) return TRUE; } +static void +reverse_bit(char *buf, int len) +{ + int i; + unsigned char c; + + for (i = 0; i < len; i++) { + c = buf[i]; + c = ((c & 0x55) << 1) | ((c & 0xaa) >> 1); /* Swap 1bit */ + c = ((c & 0x33) << 2) | ((c & 0xcc) >> 2); /* Swap 2bit */ + c = (c << 4) | (c >> 4); /* Swap 4bit */ + buf[i] = c; + } +} + int sadump_copy_1st_bitmap_from_memory(void) { @@ -189,6 +234,14 @@ sadump_copy_1st_bitmap_from_memory(void) info->name_memory, strerror(errno)); return FALSE; } + /* + * sadump formats associate each bit in a bitmap with + * a physical page in reverse order with the + * kdump-compressed format. We need to change bit + * order to reuse bitmaps in sadump formats in the + * kdump-compressed format. + */ + reverse_bit(buf, sizeof(buf)); if (write(info->bitmap1->fd, buf, sizeof(buf)) != sizeof(buf)) { ERRMSG("Can't write the bitmap(%s). %s\n", info->bitmap1->file_name, strerror(errno)); @@ -808,6 +861,19 @@ sadump_initialize_bitmap_memory(void) info->bitmap_memory = bmp; si->block_table = block_table; + bmp = malloc(sizeof(struct dump_bitmap)); + if (bmp == NULL) { + ERRMSG("Can't allocate memory for the memory-bitmap. %s\n", + strerror(errno)); + return FALSE; + } + bmp->fd = info->fd_memory; + bmp->file_name = info->name_memory; + bmp->no_block = -1; + memset(bmp->buf, 0, BUFSIZE_BITMAP); + bmp->offset = si->sub_hdr_offset + sh->block_size * sh->sub_hdr_size; + si->ram_bitmap = bmp; + return TRUE; } @@ -977,7 +1043,12 @@ readpage_sadump(unsigned long long paddr, void *bufptr) if (pfn >= si->max_mapnr) return FALSE; - if (!is_dumpable(info->bitmap_memory, pfn)) { + if (!sadump_is_ram(pfn)) { + ERRMSG("pfn(%llx) is not ram.\n", pfn); + return FALSE; + } + + if (!sadump_is_dumpable(info->bitmap_memory, pfn)) { ERRMSG("pfn(%llx) is excluded from %s.\n", pfn, info->name_memory); return FALSE; @@ -1142,7 +1213,7 @@ pfn_to_block(mdf_pfn_t pfn) block = 0; for (p = section * SADUMP_PF_SECTION_NUM; p < pfn; ++p) - if (is_dumpable(info->bitmap_memory, p)) + if (sadump_is_dumpable(info->bitmap_memory, p)) block++; return block; -- 2.1.0