From patchwork Tue Feb 14 20:00:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: lilydjwg--- via Elfutils-devel X-Patchwork-Id: 65013 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4B1C73858C1F for ; Tue, 14 Feb 2023 20:01:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4B1C73858C1F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1676404916; bh=MMGcutmG+5lK9VKGjCTBOuAUodBCP7jX+j9LDE+pPyo=; h=Date:Subject:To:Cc:List-Id:List-Unsubscribe:List-Archive: List-Help:List-Subscribe:From:Reply-To:From; b=dEWFOFjd9nv73k1czFzqPjWxOJirXoa1zNgb0IhoY2u99WCd1K/SxTtC0C8qS4sRc 80rt0lrKUdqcTXfGSSXdWMrEtvuqIqNRSK0InNp8HjJ4B8mqf6zxZcjCwuHEnEEbpO 9bwCNZdEDj008ARHEod5GtwGZQcn09IBvMyXh0cM= X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from mail-wm1-x34a.google.com (mail-wm1-x34a.google.com [IPv6:2a00:1450:4864:20::34a]) by sourceware.org (Postfix) with ESMTPS id F3A323858D1E for ; Tue, 14 Feb 2023 20:01:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F3A323858D1E Received: by mail-wm1-x34a.google.com with SMTP id j20-20020a05600c1c1400b003dc5dd44c0cso8264212wms.8 for ; Tue, 14 Feb 2023 12:01:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=MMGcutmG+5lK9VKGjCTBOuAUodBCP7jX+j9LDE+pPyo=; b=mRYMkpSungcIgK5tsOLwyhhijmO00WdKshVOPgpbduJ2ArhLfxXzHX9JRFAzm3bGmE ZXAmKll4JZg6Crb1CV2BmJd86VGFeVYD5u5xCLzPM25flvJQeDcSYUK2ZnIaBL+MWu90 yEusIZltld2P5F0DDMYW4GBi8n7tpxNZSJUGY/vhfSkK6Nw5HxKo3jSX8wcSgJvJ1EOw iWt70lnbfc/FtVUk8xJcHNL4BLhCcND8qkG4C6BU9HDVmLKFimtW4DpJTSx4kaWVpmp7 ku9NZO61TFf+YizSA3I1X/sLIe6v3DcV6ex3+Xo3PbjoeFAS1d9wGyfO6FCaHOCW3C1r 2Nnw== X-Gm-Message-State: AO0yUKX5hYEtl9/3dSlkO/0AvymE0g2w+C6vnrSh1Y6wHkEcP+dhwVJb l/acewEC5eObaXdaKOX8mXcCKKIHDPSJMKYKMHLjpOBNtqVyuvcPGRfEWsxxLIgpOFThL1MYq// xCc35jHTlnkJ4HGtSVI+4+4XqH/QDmmujAhjqFSHQ5ekpYvi2TRw2cUgsjyxmNSaK1VpysXc= X-Google-Smtp-Source: AK7set8b7O/QZvDAHS0B3rq+eP2snMM9FTYMiBe+S4yHHbq3g9dqXrp8eAyPgneUhkG34VvCdaROQrTV+Y8= X-Received: from vvvvvv-dev.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:472]) (user=vvvvvv job=sendgmr) by 2002:a05:600c:2f10:b0:3db:2e60:7449 with SMTP id r16-20020a05600c2f1000b003db2e607449mr15207wmn.2.1676404903670; Tue, 14 Feb 2023 12:01:43 -0800 (PST) Date: Tue, 14 Feb 2023 20:00:42 +0000 Mime-Version: 1.0 X-Mailer: git-send-email 2.39.1.581.gbfd45094c4-goog Message-ID: <20230214200042.3675502-1-vvvvvv@google.com> Subject: [PATCH] libdw: check that DWARF strings are null-terminated To: elfutils-devel@sourceware.org Cc: kernel-team@android.com, maennich@google.com, vvvvvv@google.com X-Spam-Status: No, score=-20.3 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HK_RANDOM_FROM, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Elfutils-devel mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Aleksei Vetrov via Elfutils-devel From: lilydjwg--- via Elfutils-devel Reply-To: vvvvvv@google.com Errors-To: elfutils-devel-bounces+patchwork=sourceware.org@sourceware.org Sender: "Elfutils-devel" From: Aleksei Vetrov 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 --- 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;