From fd7df9d3eddf7e0ba5b4a11aacacc45bcefafd65 Mon Sep 17 00:00:00 2001 From: Kyle Zeng Date: Wed, 20 Jan 2021 06:58:50 -0700 Subject: [PATCH] fix wrong prpsinfo in 32bit coredump (#347) * fix wrong prpsinfo in 32bit coredump * add a sample coredump * finish the testcase for 32bit core dump --- elftools/elf/structs.py | 8 +- test/test_core_notes32.py | 174 ++++++++++++++++++ ...est_core_notes.py => test_core_notes64.py} | 0 test/testfiles_for_unittests/core_linux32.elf | Bin 0 -> 221184 bytes 4 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 test/test_core_notes32.py rename test/{test_core_notes.py => test_core_notes64.py} (100%) create mode 100644 test/testfiles_for_unittests/core_linux32.elf diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py index b9203c6..0c6a809 100644 --- a/elftools/elf/structs.py +++ b/elftools/elf/structs.py @@ -389,10 +389,10 @@ class ELFStructs(object): self.Elf_xword('pr_flag'), self.Elf_half('pr_uid'), self.Elf_half('pr_gid'), - self.Elf_half('pr_pid'), - self.Elf_half('pr_ppid'), - self.Elf_half('pr_pgrp'), - self.Elf_half('pr_sid'), + self.Elf_word('pr_pid'), + self.Elf_word('pr_ppid'), + self.Elf_word('pr_pgrp'), + self.Elf_word('pr_sid'), String('pr_fname', 16), String('pr_psargs', 80), ) diff --git a/test/test_core_notes32.py b/test/test_core_notes32.py new file mode 100644 index 0000000..d0726e9 --- /dev/null +++ b/test/test_core_notes32.py @@ -0,0 +1,174 @@ +#------------------------------------------------------------------------------ +# elftools tests +# +# Kyle Zeng (zengyhkyle@asu.edu) +# This code is in the public domain +#------------------------------------------------------------------------------ +import unittest +import os + +from elftools.elf.elffile import ELFFile +from elftools.elf.segments import NoteSegment + + +class TestCoreNotes(unittest.TestCase): + """ This test makes sure than core dump specific + sections are properly analyzed. + """ + @classmethod + def setUpClass(cls): + cls._core_file = open(os.path.join('test', + 'testfiles_for_unittests', 'core_linux32.elf'), + 'rb') + + def test_core_prpsinfo(self): + elf = ELFFile(self._core_file) + for segment in elf.iter_segments(): + if not isinstance(segment, NoteSegment): + continue + notes = list(segment.iter_notes()) + for note in segment.iter_notes(): + if note['n_type'] != 'NT_PRPSINFO': + continue + desc = note['n_desc'] + self.assertEqual(desc['pr_state'], 0) + self.assertEqual(desc['pr_sname'], b'R') + self.assertEqual(desc['pr_zomb'], 0) + self.assertEqual(desc['pr_nice'], 0) + self.assertEqual(desc['pr_flag'], 0x400600) + self.assertEqual(desc['pr_uid'], 1000) + self.assertEqual(desc['pr_gid'], 1000) + self.assertEqual(desc['pr_pid'], 11038) + self.assertEqual(desc['pr_ppid'], 10442) + self.assertEqual(desc['pr_pgrp'], 11038) + self.assertEqual(desc['pr_sid'], 10442) + self.assertEqual( + desc['pr_fname'], + b'coredump\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual( + desc['pr_psargs'], + b'./coredump foo bar 42 '.ljust(80, b'\x00')) + + def test_core_nt_file(self): + """ + Test that the parsing of the NT_FILE note within a core file is + correct. + The assertions are made against the output of eu-readelf. + + eu-readelf -n core_linux64.elf + ... + CORE 0x0000018b NT_FILE (mapped files) + Page size: 4096 + Start End Page Offset + 0x56624000 0x56625000 0x00000000 + /tmp/coredump + 0x56625000 0x56626000 0x00000000 + /tmp/coredump + 0x56626000 0x56627000 0x00000001 + /tmp/coredump + 0xf7d13000 0xf7ee8000 0x00000000 + /lib/i386-linux-gnu/libc-2.27.so + 0xf7ee8000 0xf7ee9000 0x000001d5 + /lib/i386-linux-gnu/libc-2.27.so + 0xf7ee9000 0xf7eeb000 0x000001d5 + /lib/i386-linux-gnu/libc-2.27.so + 0xf7eeb000 0xf7eec000 0x000001d7 + /lib/i386-linux-gnu/libc-2.27.so + 0xf7f39000 0xf7f5f000 0x00000000 + /lib/i386-linux-gnu/ld-2.27.so + 0xf7f5f000 0xf7f60000 0x00000025 + /lib/i386-linux-gnu/ld-2.27.so + 0xf7f60000 0xf7f61000 0x00000026 + /lib/i386-linux-gnu/ld-2.27.so + ... + """ + elf = ELFFile(self._core_file) + nt_file_found = False + for segment in elf.iter_segments(): + if not isinstance(segment, NoteSegment): + continue + for note in segment.iter_notes(): + if note['n_type'] != 'NT_FILE': + continue + nt_file_found = True + desc = note['n_desc'] + self.assertEqual(desc['num_map_entries'], 10) + self.assertEqual(desc['page_size'], 4096) + self.assertEqual(len(desc['Elf_Nt_File_Entry']), 10) + self.assertEqual(len(desc['filename']), 10) + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][0], + desc['page_size'], + 0x56624000, 0x56625000, 0x00000000) + self.assertEqual(desc['filename'][0], + b"/tmp/coredump") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][1], + desc['page_size'], + 0x56625000, 0x56626000, 0x00000000) + self.assertEqual(desc['filename'][1], + b"/tmp/coredump") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][2], + desc['page_size'], + 0x56626000, 0x56627000, 0x00000001) + self.assertEqual(desc['filename'][2], + b"/tmp/coredump") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][3], + desc['page_size'], + 0xf7d13000, 0xf7ee8000, 0x00000000) + self.assertEqual(desc['filename'][3], + b"/lib/i386-linux-gnu/libc-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][4], + desc['page_size'], + 0xf7ee8000, 0xf7ee9000, 0x000001d5) + self.assertEqual(desc['filename'][4], + b"/lib/i386-linux-gnu/libc-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][5], + desc['page_size'], + 0xf7ee9000, 0xf7eeb000, 0x000001d5) + self.assertEqual(desc['filename'][5], + b"/lib/i386-linux-gnu/libc-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][6], + desc['page_size'], + 0xf7eeb000, 0xf7eec000, 0x000001d7) + self.assertEqual(desc['filename'][6], + b"/lib/i386-linux-gnu/libc-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][7], + desc['page_size'], + 0xf7f39000, 0xf7f5f000, 0x00000000) + self.assertEqual(desc['filename'][7], + b"/lib/i386-linux-gnu/ld-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][8], + desc['page_size'], + 0xf7f5f000, 0xf7f60000, 0x00000025) + self.assertEqual(desc['filename'][8], + b"/lib/i386-linux-gnu/ld-2.27.so") + + self.validate_nt_file_entry(desc['Elf_Nt_File_Entry'][9], + desc['page_size'], + 0xf7f60000, 0xf7f61000, 0x00000026) + self.assertEqual(desc['filename'][9], + b"/lib/i386-linux-gnu/ld-2.27.so") + + self.assertTrue(nt_file_found) + + def validate_nt_file_entry(self, + entry, + page_size, + expected_vm_start, + expected_vm_end, + expected_page_offset): + self.assertEqual(entry.vm_start, expected_vm_start) + self.assertEqual(entry.vm_end, expected_vm_end) + self.assertEqual(entry.page_offset, expected_page_offset) + + @classmethod + def tearDownClass(cls): + cls._core_file.close() diff --git a/test/test_core_notes.py b/test/test_core_notes64.py similarity index 100% rename from test/test_core_notes.py rename to test/test_core_notes64.py diff --git a/test/testfiles_for_unittests/core_linux32.elf b/test/testfiles_for_unittests/core_linux32.elf new file mode 100644 index 0000000000000000000000000000000000000000..bbc5a0450b010e5b399484f141c1b58e73726d2a GIT binary patch literal 221184 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 literal 0 HcmV?d00001 -- 2.30.2