From: vvvvvv@google.com
To: elfutils-devel@sourceware.org
Cc: kernel-team@android.com, maennich@google.com, vvvvvv@google.com
Subject: [PATCH] libdw: check that DWARF strings are null-terminated
Date: Tue, 14 Feb 2023 20:00:42 +0000 [thread overview]
Message-ID: <20230214200042.3675502-1-vvvvvv@google.com> (raw)
From: Aleksei Vetrov <vvvvvv@google.com>
It is expected from libdw to return strings that are null-terminated to
avoid overflowing ELF data.
* Add calculation of a safe prefix inside string sections, where any
string will be null-terminated.
* Check if offset overflows the safe prefix in dwarf_formstring.
Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
---
libdw/dwarf_begin_elf.c | 37 +++++++++++++++++++++++++++++++++++++
libdw/dwarf_formstring.c | 5 ++++-
libdw/libdwP.h | 11 +++++++++++
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 8fcef335..76b30a3c 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -70,6 +70,30 @@ static const char dwarf_scnnames[IDX_last][19] =
};
#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
+/* Map from section index to string secton index.
+ Non-string sections should have STR_SCN_IDX_last. */
+static const enum string_secton_index scn_to_string_secton_idx[IDX_last] =
+{
+ [IDX_debug_info] = STR_SCN_IDX_last,
+ [IDX_debug_types] = STR_SCN_IDX_last,
+ [IDX_debug_abbrev] = STR_SCN_IDX_last,
+ [IDX_debug_addr] = STR_SCN_IDX_last,
+ [IDX_debug_aranges] = STR_SCN_IDX_last,
+ [IDX_debug_line] = STR_SCN_IDX_last,
+ [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str,
+ [IDX_debug_frame] = STR_SCN_IDX_last,
+ [IDX_debug_loc] = STR_SCN_IDX_last,
+ [IDX_debug_loclists] = STR_SCN_IDX_last,
+ [IDX_debug_pubnames] = STR_SCN_IDX_last,
+ [IDX_debug_str] = STR_SCN_IDX_debug_str,
+ [IDX_debug_str_offsets] = STR_SCN_IDX_last,
+ [IDX_debug_macinfo] = STR_SCN_IDX_last,
+ [IDX_debug_macro] = STR_SCN_IDX_last,
+ [IDX_debug_ranges] = STR_SCN_IDX_last,
+ [IDX_debug_rnglists] = STR_SCN_IDX_last,
+ [IDX_gnu_debugaltlink] = STR_SCN_IDX_last
+};
+
static enum dwarf_type
scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
{
@@ -230,6 +254,19 @@ check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
/* We can now read the section data into results. */
result->sectiondata[cnt] = data;
+ /* If the section contains string data, we want to know a size of a prefix
+ where any string will be null-terminated. */
+ enum string_secton_index string_secton_idx = scn_to_string_secton_idx[cnt];
+ if (string_secton_idx < STR_SCN_IDX_last)
+ {
+ size_t size = data->d_size;
+ /* Reduce the size by the number of non-zero bytes at the end of the
+ section. */
+ while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
+ --size;
+ result->string_secton_size[string_secton_idx] = size;
+ }
+
return result;
}
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c
index c3e892a8..a6f511f8 100644
--- a/libdw/dwarf_formstring.c
+++ b/libdw/dwarf_formstring.c
@@ -61,6 +61,9 @@ dwarf_formstring (Dwarf_Attribute *attrp)
Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
? dbg_ret->sectiondata[IDX_debug_line_str]
: dbg_ret->sectiondata[IDX_debug_str]);
+ size_t data_size = ((attrp->form == DW_FORM_line_strp)
+ ? dbg_ret->string_secton_size[STR_SCN_IDX_debug_line_str]
+ : dbg_ret->string_secton_size[STR_SCN_IDX_debug_str]);
if (data == NULL)
{
__libdw_seterrno ((attrp->form == DW_FORM_line_strp)
@@ -171,7 +174,7 @@ dwarf_formstring (Dwarf_Attribute *attrp)
else
off = read_8ubyte_unaligned (dbg, datap);
- if (off > dbg->sectiondata[IDX_debug_str]->d_size)
+ if (off >= data_size)
goto invalid_offset;
}
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 961fa4e7..55eb45ed 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -86,6 +86,13 @@ enum
IDX_last
};
+/* Valid indices for the string section's information. */
+enum string_secton_index
+ {
+ STR_SCN_IDX_debug_line_str,
+ STR_SCN_IDX_debug_str,
+ STR_SCN_IDX_last
+ };
/* Error values. */
enum
@@ -169,6 +176,10 @@ struct Dwarf
/* The section data. */
Elf_Data *sectiondata[IDX_last];
+ /* Size of a prefix of string sections, where any string will be
+ null-terminated. */
+ size_t string_secton_size[STR_SCN_IDX_last];
+
/* True if the file has a byte order different from the host. */
bool other_byte_order;
--
2.39.1.581.gbfd45094c4-goog
next reply other threads:[~2023-02-14 20:01 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-14 20:00 vvvvvv [this message]
2023-02-14 20:30 ` [PATCH v2 0/1] " Aleksei Vetrov
2023-02-14 20:30 ` [PATCH v2 1/1] " Aleksei Vetrov
2023-02-16 23:45 ` Mark Wielaard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230214200042.3675502-1-vvvvvv@google.com \
--to=vvvvvv@google.com \
--cc=elfutils-devel@sourceware.org \
--cc=kernel-team@android.com \
--cc=maennich@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).