From 2c147eaf06d244f43c580e8e30ce4ea4e9a9d50b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 7 May 2021 17:42:52 +0100 Subject: [PATCH] Stop stack exhaustion when demangling corrupt rust names. Resolves: #1956424 --- binutils-CVE-2021-3530.patch | 69 ++++++++++++++++++++++++++++++++++++ binutils.spec | 9 ++++- 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 binutils-CVE-2021-3530.patch diff --git a/binutils-CVE-2021-3530.patch b/binutils-CVE-2021-3530.patch new file mode 100644 index 0000000..1afe989 --- /dev/null +++ b/binutils-CVE-2021-3530.patch @@ -0,0 +1,69 @@ +--- binutils.orig/libiberty/rust-demangle.c 2021-05-07 17:13:43.762229783 +0100 ++++ binutils-2.36.1/libiberty/rust-demangle.c 2021-05-07 17:14:39.805820593 +0100 +@@ -74,6 +74,12 @@ struct rust_demangler + /* Rust mangling version, with legacy mangling being -1. */ + int version; + ++ /* Recursion depth. */ ++ uint recursion; ++ /* Maximum number of times demangle_path may be called recursively. */ ++#define RUST_MAX_RECURSION_COUNT 1024 ++#define RUST_NO_RECURSION_LIMIT ((uint) -1) ++ + uint64_t bound_lifetime_depth; + }; + +@@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rd + if (rdm->errored) + return; + ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ { ++ ++ rdm->recursion; ++ if (rdm->recursion > RUST_MAX_RECURSION_COUNT) ++ /* FIXME: There ought to be a way to report ++ that the recursion limit has been reached. */ ++ goto fail_return; ++ } ++ + switch (tag = next (rdm)) + { + case 'C': +@@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rd + case 'N': + ns = next (rdm); + if (!ISLOWER (ns) && !ISUPPER (ns)) +- { +- rdm->errored = 1; +- return; +- } ++ goto fail_return; + + demangle_path (rdm, in_value); + +@@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rd + } + break; + default: +- rdm->errored = 1; +- return; ++ goto fail_return; + } ++ goto pass_return; ++ ++ fail_return: ++ rdm->errored = 1; ++ pass_return: ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ -- rdm->recursion; + } + + static void +@@ -1317,6 +1335,7 @@ rust_demangle_callback (const char *mang + rdm.skipping_printing = 0; + rdm.verbose = (options & DMGL_VERBOSE) != 0; + rdm.version = 0; ++ rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0; + rdm.bound_lifetime_depth = 0; + + /* Rust symbols always start with _R (v0) or _ZN (legacy). */ diff --git a/binutils.spec b/binutils.spec index 04bafa1..b19d4ba 100644 --- a/binutils.spec +++ b/binutils.spec @@ -39,7 +39,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?name_cross}%{?_with_debug:-debug} Version: 2.36.1 -Release: 8%{?dist} +Release: 9%{?dist} License: GPLv3+ URL: https://sourceware.org/binutils @@ -273,6 +273,10 @@ Patch19: binutils-s390-arch14-insns.patch # Lifetime: Fixed in 2.37 Patch20: binutils-CVE-2021-20197.patch +# Purpose: Avoid stack exhaustion whilst demangling rust names +# Lifetime: Fixed in 2.37 +Patch21: binutils-CVE-2021-3530.patch + #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -858,6 +862,9 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Fri May 07 2021 Nick Clifton - 2.36.1-9 +- Fix stack exhaustion in the rust demangler. (#1956424) + * Thu Mar 25 2021 Nick Clifton - 2.36.1-8 - Add an explicit dependency upon autoconf 2.69. (#1942991)