[PATCH] libebl: Check NT_PLATFORM core notes contain a zero terminated string.
From: Mark Wielaard <mark at klomp dot org>
To: elfutils-devel at sourceware dot org
Cc: Mark Wielaard <mark at klomp dot org>
Date: Wed, 16 Jan 2019 15:44:08 +0100
Subject: [PATCH] libebl: Check NT_PLATFORM core notes contain a zero terminated
string.
Reference: bnc#1125007

Most strings in core notes are fixed size. But NT_PLATFORM contains just
a variable length string. Check that it is actually zero terminated
before passing to readelf to print.

https://sourceware.org/bugzilla/show_bug.cgi?id=24089

elfutils packaging edits:
 - changelog hunk removed from original patch to avoid conflict
 - backported from upstream patch to 0.158

Signed-off-by: Mark Wielaard <mark@klomp.org>
Signed-off-by: Joao Moreira <jmoreira@suse.de>

--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -136,7 +136,7 @@
       const Ebl_Register_Location *reglocs;
       size_t nitems;
       const Ebl_Core_Item *items;
-      if (! ebl_core_note (core_arg->ebl, &nhdr, name,
+      if (! ebl_core_note (core_arg->ebl, &nhdr, name, desc,
 			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
 	{
 	  /* This note may be just not recognized, skip it.  */
@@ -189,8 +189,9 @@
   const Ebl_Register_Location *reglocs;
   size_t nitems;
   const Ebl_Core_Item *items;
-  int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, &regs_offset,
-				     &nregloc, &reglocs, &nitems, &items);
+  int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, desc,
+				     &regs_offset, &nregloc, &reglocs,
+				     &nitems, &items);
   /* __libdwfl_attach_state_for_core already verified the note is there.  */
   assert (core_note_err != 0);
   assert (nhdr.n_type == NT_PRSTATUS);
@@ -370,7 +371,7 @@
       const Ebl_Register_Location *reglocs;
       size_t nitems;
       const Ebl_Core_Item *items;
-      if (! ebl_core_note (ebl, &nhdr, name,
+      if (! ebl_core_note (ebl, &nhdr, name, desc,
 			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
 	{
 	  /* This note may be just not recognized, skip it.  */
--- a/libebl/eblcorenote.c
+++ b/libebl/eblcorenote.c
@@ -35,21 +35,16 @@
 #include <endian.h>
 #include <inttypes.h>
 #include <stdio.h>
+#include <string.h>
 #include <stddef.h>
 #include <libeblP.h>
 
-
 int
-ebl_core_note (ebl, nhdr, name,
-	       regs_offset, nregloc, reglocs, nitems, items)
-     Ebl *ebl;
-     const GElf_Nhdr *nhdr;
-     const char *name;
-     GElf_Word *regs_offset;
-     size_t *nregloc;
-     const Ebl_Register_Location **reglocs;
-     size_t *nitems;
-     const Ebl_Core_Item **items;
+ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const char *name,
+	       const char *desc,
+	       GElf_Word *regs_offset, size_t *nregloc,
+	       const Ebl_Register_Location **reglocs, size_t *nitems,
+	       const Ebl_Core_Item **items)
 {
   int result = ebl->core_note (nhdr, name,
 			       regs_offset, nregloc, reglocs, nitems, items);
@@ -57,28 +52,25 @@
     {
       /* The machine specific function did not know this type.  */
 
-      *regs_offset = 0;
-      *nregloc = 0;
-      *reglocs = NULL;
-      switch (nhdr->n_type)
+      /* NT_PLATFORM is kind of special since it needs a zero terminated
+         string (other notes often have a fixed size string).  */
+      static const Ebl_Core_Item platform[] =
 	{
-#define ITEMS(type, table)				\
-	  case type:					\
-	    *items = table;				\
-	    *nitems = sizeof table / sizeof table[0];	\
-	    result = 1;					\
-	    break
-
-	  static const Ebl_Core_Item platform[] =
-	    {
-	      {
-		.name = "Platform",
-		.type = ELF_T_BYTE, .count = 0, .format = 's'
-	      }
-	    };
-	  ITEMS (NT_PLATFORM, platform);
-
-#undef	ITEMS
+	  {
+	    .name = "Platform",
+	    .type = ELF_T_BYTE, .count = 0, .format = 's'
+	  }
+	};
+
+      if (nhdr->n_type == NT_PLATFORM
+	  && memchr (desc, '\0', nhdr->n_descsz) != NULL)
+        {
+	  *regs_offset = 0;
+	  *nregloc = 0;
+	  *reglocs = NULL;
+	  *items = platform;
+	  *nitems = 1;
+	  result = 1;
 	}
     }
 
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -374,7 +374,8 @@
 
 /* Describe the format of a core file note with the given header and NAME.
    NAME is not guaranteed terminated, it's NHDR->n_namesz raw bytes.  */
-extern int ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const char *name,
+extern int ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
+			  const char *name, const char *desc,
 			  GElf_Word *regs_offset, size_t *nregloc,
 			  const Ebl_Register_Location **reglocs,
 			  size_t *nitems, const Ebl_Core_Item **items)
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8775,7 +8775,7 @@
   size_t nitems;
   const Ebl_Core_Item *items;
 
-  if (! ebl_core_note (ebl, nhdr, name,
+  if (! ebl_core_note (ebl, nhdr, name, desc,
 		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
     return;
 
