libdwl: Add validate_strdata to limit Elf_Data d_size to valid strings.

Message ID 20250622122147.1569555-1-mark@klomp.org
State Committed
Headers
Series libdwl: Add validate_strdata to limit Elf_Data d_size to valid strings. |

Commit Message

Mark Wielaard June 22, 2025, 12:21 p.m. UTC
  dwfl_module_getsym returns the name of a symbol as found in the
corresponding (symbol) string section. Make sure all names are
correctly zero terminated by making sure the last valid index in a
section/segment Elf_Data contains a zero character.

	* libdwfl/dwfl_module_getdwarf.c (validate_strdata): New
	function taking Elf_Data and restricting d_size to last zero
	char.
	(translate_offs): Call validate_strdata.
	(find_symtab): Likewise for both symstrdata and aux_symstrdata.

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

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdwfl/dwfl_module_getdwarf.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
  

Comments

Aaron Merey June 23, 2025, 11:30 p.m. UTC | #1
Hi Mark,

On Sun, Jun 22, 2025 at 10:19 AM Mark Wielaard <mark@klomp.org> wrote:
>
> dwfl_module_getsym returns the name of a symbol as found in the
> corresponding (symbol) string section. Make sure all names are
> correctly zero terminated by making sure the last valid index in a
> section/segment Elf_Data contains a zero character.
>
>         * libdwfl/dwfl_module_getdwarf.c (validate_strdata): New
>         function taking Elf_Data and restricting d_size to last zero
>         char.
>         (translate_offs): Call validate_strdata.
>         (find_symtab): Likewise for both symstrdata and aux_symstrdata.
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=33099
>
> Signed-off-by: Mark Wielaard <mark@klomp.org>
> ---
>  libdwfl/dwfl_module_getdwarf.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
> index 7fd0d3aa3b17..135132d69178 100644
> --- a/libdwfl/dwfl_module_getdwarf.c
> +++ b/libdwfl/dwfl_module_getdwarf.c
> @@ -1,5 +1,6 @@
>  /* Find debugging and symbol information for a module in libdwfl.
>     Copyright (C) 2005-2012, 2014, 2015, 2025 Red Hat, Inc.
> +   Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org>
>     This file is part of elfutils.
>
>     This file is free software; you can redistribute it and/or modify
> @@ -692,6 +693,19 @@ find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
>      }
>  }
>
> +/* This is a string section/segment, so we want to make sure the last
> +   valid index contains a zero character to terminate a string.  */
> +static void
> +validate_strdata (Elf_Data *symstrdata)
> +{
> +  size_t size = symstrdata->d_size;
> +  const char *buf = symstrdata->d_buf;
> +  while (size > 0 && *(buf + size - 1) != '\0')
> +    --size;
> +  symstrdata->d_size = size;
> +}
> +
> +
>  /* Various addresses we might want to pull from the dynamic segment.  */
>  enum
>  {
> @@ -816,6 +830,8 @@ translate_offs (GElf_Addr adjust,
>                                                   ELF_T_BYTE);
>           if (mod->symstrdata == NULL)
>             mod->symdata = NULL;
> +         else
> +           validate_strdata (mod->symstrdata);
>         }
>        if (mod->symdata == NULL)
>         mod->symerr = DWFL_E (LIBELF, elf_errno ());
> @@ -1181,6 +1197,8 @@ find_symtab (Dwfl_Module *mod)
>    mod->symstrdata = elf_getdata (symstrscn, NULL);
>    if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
>      goto elferr;
> +  else
> +    validate_strdata (mod->symstrdata);
>
>    if (xndxscn == NULL)
>      mod->symxndxdata = NULL;
> @@ -1264,6 +1282,8 @@ find_symtab (Dwfl_Module *mod)
>        mod->aux_symstrdata = elf_getdata (aux_strscn, NULL);
>        if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
>         goto aux_cleanup;
> +      else
> +       validate_strdata (mod->aux_symstrdata);
>
>        if (aux_xndxscn == NULL)
>         mod->aux_symxndxdata = NULL;
> --
> 2.49.0
>

LGTM.

Aaron
  

Patch

diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 7fd0d3aa3b17..135132d69178 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1,5 +1,6 @@ 
 /* Find debugging and symbol information for a module in libdwfl.
    Copyright (C) 2005-2012, 2014, 2015, 2025 Red Hat, Inc.
+   Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org>
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -692,6 +693,19 @@  find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
     }
 }
 
+/* This is a string section/segment, so we want to make sure the last
+   valid index contains a zero character to terminate a string.  */
+static void
+validate_strdata (Elf_Data *symstrdata)
+{
+  size_t size = symstrdata->d_size;
+  const char *buf = symstrdata->d_buf;
+  while (size > 0 && *(buf + size - 1) != '\0')
+    --size;
+  symstrdata->d_size = size;
+}
+
+
 /* Various addresses we might want to pull from the dynamic segment.  */
 enum
 {
@@ -816,6 +830,8 @@  translate_offs (GElf_Addr adjust,
 						  ELF_T_BYTE);
 	  if (mod->symstrdata == NULL)
 	    mod->symdata = NULL;
+	  else
+	    validate_strdata (mod->symstrdata);
 	}
       if (mod->symdata == NULL)
 	mod->symerr = DWFL_E (LIBELF, elf_errno ());
@@ -1181,6 +1197,8 @@  find_symtab (Dwfl_Module *mod)
   mod->symstrdata = elf_getdata (symstrscn, NULL);
   if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
     goto elferr;
+  else
+    validate_strdata (mod->symstrdata);
 
   if (xndxscn == NULL)
     mod->symxndxdata = NULL;
@@ -1264,6 +1282,8 @@  find_symtab (Dwfl_Module *mod)
       mod->aux_symstrdata = elf_getdata (aux_strscn, NULL);
       if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
 	goto aux_cleanup;
+      else
+	validate_strdata (mod->aux_symstrdata);
 
       if (aux_xndxscn == NULL)
 	mod->aux_symxndxdata = NULL;