fixed parsing for structures containing uids or gids in core dumps for most architect...
authorLukas Dresel <Lukas-Dresel@users.noreply.github.com>
Mon, 2 Aug 2021 15:30:19 +0000 (11:30 -0400)
committerGitHub <noreply@github.com>
Mon, 2 Aug 2021 15:30:19 +0000 (08:30 -0700)
* fixed parsing for structures containing uids or gids in core dumps for most architectures

* added testcase for mips corefile uid/gid parsing

* better description

* better email

elftools/elf/structs.py
test/test_core_notes32_mips.py [new file with mode: 0644]
test/testfiles_for_unittests/core_linux32_qemu_mips.elf [new file with mode: 0644]

index ee4beac88d8de0a306f0df6abf2f7d724016519c..5be009b5ec3047a8604308ad847b843e7978ea9e 100644 (file)
@@ -373,6 +373,20 @@ class ELFStructs(object):
 
     def _create_note(self, e_type=None):
         # Structure of "PT_NOTE" section
+
+        self.Elf_ugid = self.Elf_half if self.elfclass == 32 and self.e_machine in {
+            'EM_MN10300',
+            'EM_ARM',
+            'EM_CRIS',
+            'EM_CYGNUS_FRV',
+            'EM_386',
+            'EM_M32R',
+            'EM_68K',
+            'EM_S390',
+            'EM_SH',
+            'EM_SPARC',
+        } else self.Elf_word
+
         self.Elf_Nhdr = Struct('Elf_Nhdr',
             self.Elf_word('n_namesz'),
             self.Elf_word('n_descsz'),
@@ -390,8 +404,8 @@ class ELFStructs(object):
                 self.Elf_byte('pr_zomb'),
                 self.Elf_byte('pr_nice'),
                 self.Elf_xword('pr_flag'),
-                self.Elf_half('pr_uid'),
-                self.Elf_half('pr_gid'),
+                self.Elf_ugid('pr_uid'),
+                self.Elf_ugid('pr_gid'),
                 self.Elf_word('pr_pid'),
                 self.Elf_word('pr_ppid'),
                 self.Elf_word('pr_pgrp'),
@@ -407,8 +421,8 @@ class ELFStructs(object):
                 self.Elf_byte('pr_nice'),
                 Padding(4),
                 self.Elf_xword('pr_flag'),
-                self.Elf_word('pr_uid'),
-                self.Elf_word('pr_gid'),
+                self.Elf_ugid('pr_uid'),
+                self.Elf_ugid('pr_gid'),
                 self.Elf_word('pr_pid'),
                 self.Elf_word('pr_ppid'),
                 self.Elf_word('pr_pgrp'),
diff --git a/test/test_core_notes32_mips.py b/test/test_core_notes32_mips.py
new file mode 100644 (file)
index 0000000..8c910b1
--- /dev/null
@@ -0,0 +1,60 @@
+#------------------------------------------------------------------------------
+# elftools tests
+#
+# Lukas Dresel (lukas.dresel@cs.ucsb.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 ensures that core dump specific notes
+        are properly analyzed. Specifically, tests for a
+        regression where MIPS PRPSINFO structures would be
+        parsed incorrectly due to being treated as 16-bit
+        fields instead of 32-bit fields.
+    """
+    @classmethod
+    def setUpClass(cls):
+       cls._core_file = open(os.path.join('test',
+                             'testfiles_for_unittests', 'core_linux32_qemu_mips.elf'),
+                             'rb')
+
+    def test_core_prpsinfo(self):
+        elf = ELFFile(self._core_file)
+        for segment in elf.iter_segments():
+            if not isinstance(segment, NoteSegment):
+                continue
+            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'\0')
+                self.assertEqual(desc['pr_zomb'], 0)
+                self.assertEqual(desc['pr_nice'], 0)
+                self.assertEqual(desc['pr_flag'], 0x0)
+                self.assertEqual(desc['pr_uid'], 1000)
+                self.assertEqual(desc['pr_gid'], 1000)
+                self.assertEqual(desc['pr_pid'], 449015)
+                self.assertEqual(desc['pr_ppid'], 4238)
+                self.assertEqual(desc['pr_pgrp'], 449015)
+                self.assertEqual(desc['pr_sid'], 4238)
+                self.assertEqual(
+                    desc['pr_fname'],
+                    b'crash'.ljust(16, b'\0'))
+                self.assertEqual(
+                    desc['pr_psargs'],
+                    b'./crash '.ljust(80, b'\x00'))
+
+    @classmethod
+    def tearDownClass(cls):
+        cls._core_file.close()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/test/testfiles_for_unittests/core_linux32_qemu_mips.elf b/test/testfiles_for_unittests/core_linux32_qemu_mips.elf
new file mode 100644 (file)
index 0000000..6dad0fc
Binary files /dev/null and b/test/testfiles_for_unittests/core_linux32_qemu_mips.elf differ