From patchwork Mon Feb 13 20:10:05 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: 64930 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 B65283858025 for ; Mon, 13 Feb 2023 20:11:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B65283858025 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1676319086; bh=stDA6Xm8JmnlbJAw/mM+9OS4ZMsSZooOtoZTZrxfVWw=; h=Date:In-Reply-To:References:Subject:To:Cc:List-Id: List-Unsubscribe:List-Archive:List-Help:List-Subscribe:From: Reply-To:From; b=JyAgmaLeqhpvyrOnmjs1/p7GIYEOULhnClGJY+u94ki6338yd6X1CByuIpTS9H5np bYUer7N6a/O42V38Xb1BHKVAXOYA/GHMGoo7d8+twIsafkcZcrwl2jHciKDK1/eUP8 NAW1iHj9gPPAi5R214AeOx1C1dij+g1vU7YXhfXA= X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by sourceware.org (Postfix) with ESMTPS id 38C213858C27 for ; Mon, 13 Feb 2023 20:11:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 38C213858C27 Received: by mail-yb1-xb49.google.com with SMTP id y125-20020a25c883000000b0086349255277so13478184ybf.8 for ; Mon, 13 Feb 2023 12:11:16 -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:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=stDA6Xm8JmnlbJAw/mM+9OS4ZMsSZooOtoZTZrxfVWw=; b=vBfbIr5rHNHWujYDiVrGQ130s2RNzhQJyOHAEHjVVgQaT8qJeEwstKbKOOjhZxDzap sm0NN9jvqDuOLBQEGdtB5K2FUVJ2S3auXenoqu3cqKpswrnxLQ4MeS44sbMP1iIJGXCN 2lZS9jMxmiKQC1qOp+29W7cbwSL1VWVGtfsR9nYGH0Big1iaYCTbe5S5Uh2Jw4zJaf9Z c3xcKZrocMthbJ/Pg7othEHVsFBk5+XX6FnaTIYUYjEx69eCAOBOM+HSrEoslg7u7I92 Eb9MJF/AP9BOO/2et8grIRZVc90EssWCkTl9nTFbWU2M7/cr1/UEFiBnUXypEWYDI0lB 4geg== X-Gm-Message-State: AO0yUKV5lK1BYz0sFobIWsxwtpaPxTPeW2y2X2S+cNH8V0VwK3Oz4D7V lV6Wkgr22lKRsl0n4S4771UgkKpL3Gk= X-Google-Smtp-Source: AK7set/rDuxrZU0L9IpE6qSyITIxFLTfGpZZ+gVCbXBIs+RbM5aHu0YDaJ3YdVNLYCEwkHv/kWbtrw80kzc= X-Received: from vvvvvv-dev.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:472]) (user=vvvvvv job=sendgmr) by 2002:a5b:24c:0:b0:870:7a04:3264 with SMTP id g12-20020a5b024c000000b008707a043264mr28272ybp.38.1676319075516; Mon, 13 Feb 2023 12:11:15 -0800 (PST) Date: Mon, 13 Feb 2023 20:10:05 +0000 In-Reply-To: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.39.1.581.gbfd45094c4-goog Message-ID: <20230213201005.2498216-1-vvvvvv@google.com> Subject: [PATCH v2] libdw: check memory access in get_(u|s)leb128 To: vvvvvv@google.com Cc: elfutils-devel@sourceware.org, kernel-team@android.com, maennich@google.com, mark@klomp.org X-Spam-Status: No, score=-19.7 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, KAM_NUMSUBJECT, 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 __libdw_get_uleb128 and __libdw_get_sleb128 should check if addrp has already reached the end before unrolling the first step. It is done by moving __libdw_max_len to the beginning of the function, which can notice, that addrp is beyond the end. Then we just check the result of this function. Signed-off-by: Aleksei Vetrov --- libdw/memory-access.h | 10 ++++++++-- tests/leb128.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/libdw/memory-access.h b/libdw/memory-access.h index fca4129a..6d79343c 100644 --- a/libdw/memory-access.h +++ b/libdw/memory-access.h @@ -72,13 +72,16 @@ __libdw_max_len_sleb128 (const unsigned char *addr, const unsigned char *end) static inline uint64_t __libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end) { + const size_t max = __libdw_max_len_uleb128 (*addrp, end); + if (unlikely (max == 0)) + return UINT64_MAX; + uint64_t acc = 0; /* Unroll the first step to help the compiler optimize for the common single-byte case. */ get_uleb128_step (acc, *addrp, 0); - const size_t max = __libdw_max_len_uleb128 (*addrp - 1, end); for (size_t i = 1; i < max; ++i) get_uleb128_step (acc, *addrp, i); /* Other implementations set VALUE to UINT_MAX in this @@ -124,6 +127,10 @@ __libdw_get_uleb128_unchecked (const unsigned char **addrp) static inline int64_t __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end) { + const size_t max = __libdw_max_len_sleb128 (*addrp, end); + if (unlikely (max == 0)) + return INT64_MAX; + /* Do the work in an unsigned type, but use implementation-defined behavior to cast to signed on return. This avoids some undefined behavior when shifting. */ @@ -133,7 +140,6 @@ __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end) for the common single-byte case. */ get_sleb128_step (acc, *addrp, 0); - const size_t max = __libdw_max_len_sleb128 (*addrp - 1, end); for (size_t i = 1; i < max; ++i) get_sleb128_step (acc, *addrp, i); if (*addrp == end) diff --git a/tests/leb128.c b/tests/leb128.c index 47b57c0d..03090d80 100644 --- a/tests/leb128.c +++ b/tests/leb128.c @@ -117,6 +117,19 @@ test_sleb (void) return OK; } +static int +test_sleb_safety (void) +{ + const int64_t expected_error = INT64_MAX; + int64_t value; + const unsigned char *test = NULL; + get_sleb128 (value, test, test); + if (value != expected_error) + return FAIL; + + return OK; +} + static int test_one_uleb (const unsigned char *data, size_t len, uint64_t expect) { @@ -166,8 +179,22 @@ test_uleb (void) return OK; } +static int +test_uleb_safety (void) +{ + const uint64_t expected_error = UINT64_MAX; + uint64_t value; + const unsigned char *test = NULL; + get_uleb128 (value, test, test); + if (value != expected_error) + return FAIL; + + return OK; +} + int main (void) { - return test_sleb () || test_uleb (); + return test_sleb () || test_sleb_safety () || test_uleb () + || test_uleb_safety (); }