From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id LOiWEhnnl2qvhh4AWB0awg (envelope-from ) for ; Wed, 02 Sep 2026 05:06:33 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=duPXKlqZ; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=+uSrEI+P; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=PHy2ugjQ; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=0GCJBx2X; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 296D21E166; Wed, 02 Sep 2026 05:06:33 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-5.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id AC2281E09B for ; Wed, 02 Sep 2026 05:06:30 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 33B674BA2E36 for ; Wed, 2 Sep 2026 09:06:29 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 33B674BA2E36 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=duPXKlqZ; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=+uSrEI+P; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=PHy2ugjQ; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=0GCJBx2X Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) by sourceware.org (Postfix) with ESMTPS id 771254BA2E0C for ; Wed, 2 Sep 2026 09:05:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 771254BA2E0C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 771254BA2E0C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788339954; cv=none; b=hVYMGA1G0xCJVmW1g3nCU2pOitDWIhmeCXbCadVo8wGVSQgsWmLiOe4B3d/DQ4G8UGOe3pBYtmj7HKNmyH/5t9TAqLkpwn8/u4Ipqg6mS1r9+m+dY7j2kBWyuQ+SgxffaRcw7zSk4jgzgWp4cBg8/7QKBRMrvRtzrEmLIJY+/YE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788339954; c=relaxed/simple; bh=U4otQlbg3MGQApT7KrRibEgQGYMqi9hQpe6c3w311Tk=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature:From: To:Subject:Date:Message-ID:MIME-Version; b=g38bKUrcPeR0Vp/ZokSgcJFmQBDIjmh51inTHu7xvKCdN5NgMW4PX1tSWKSAXQT1TUP6Tz0DBDWrxQzZJg0vjLxdzIq3bDXo6hbThgrPX/olLo+fVitkMgSPHoTFegHjRxZuA1Be3GmIpC8rdMElKg+F21hZIBcz5UWnNOoc6uA= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=duPXKlqZ; dkim=pass header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=+uSrEI+P; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.a=rsa-sha256 header.s=susede2_rsa header.b=PHy2ugjQ; dkim=neutral header.d=suse.de header.i=@suse.de header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=0GCJBx2X DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 771254BA2E0C Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 1E69521F8E for ; Wed, 2 Sep 2026 09:05:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788339949; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=S+AL0Y38HLFFVLkreDqE56qM585lQJ69v/e0Ewxedgo=; b=duPXKlqZvkKGmX1b4NcISv/HVeUQWR97GXKQf3AJ6G+Rw5chp8BNRtFFGcQTNGpoDm7W8I E0vDvkBwsXQ8NAxn3+V6mLD2fUnDTpziDN40Pt8vFLJrMLsXnm3cYZAUB2jVUA3yaQ+vtw mVltpD95ILtdE9TL9bwF7P1uO3rkPlo= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788339949; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=S+AL0Y38HLFFVLkreDqE56qM585lQJ69v/e0Ewxedgo=; b=+uSrEI+PYf8lSidLZ6c53Mty4XopxLEClogz1NOlEspo1phDp8zZeJ+1vkqM7wkp1YH5u+ 45Wykp9wUprGReCQ== Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=PHy2ugjQ; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=0GCJBx2X DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788339945; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=S+AL0Y38HLFFVLkreDqE56qM585lQJ69v/e0Ewxedgo=; b=PHy2ugjQZbk4F2j0TLiFoBGuneS/ZYzF4e51iHwEh/iSLyGBZ8DW9Jiyk/e2msTGh8lVuf b/eSbzS4+SMM1Jp/mqqcLExXMTf0ux+l9uJcZM2/ek9/29XtgLdDagk34EiBJDCGaEIoAj yCzn8H8mHIPA0dP1UTW43l5NZCWMHTU= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788339945; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=S+AL0Y38HLFFVLkreDqE56qM585lQJ69v/e0Ewxedgo=; b=0GCJBx2XJ7YzHFUN5Spz6Ctsu5msNxn5BH5zizsf20ztCKPfCA5PTxQQ0GyREDmyi51ORw RmG0h4yO2TNjqwDw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id E66FE13515 for ; Wed, 2 Sep 2026 09:05:44 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 5IPNNujml2owSwAAD6G6ig (envelope-from ) for ; Wed, 02 Sep 2026 09:05:44 +0000 From: Tom de Vries To: gdb-patches@sourceware.org Subject: [PATCH] [gdb-17-branch, gdb/stabs] Fix out-of-bounds write in read_member_functions Date: Wed, 2 Sep 2026 11:05:44 +0200 Message-ID: <20260902090544.2061258-1-tdevries@suse.de> X-Mailer: git-send-email 2.51.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Action: no action X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Rspamd-Queue-Id: 1E69521F8E X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; RCPT_COUNT_ONE(0.00)[1]; MIME_TRACE(0.00)[0:+]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; FROM_HAS_DN(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[nist.gov:url,cve.org:url,suse.de:dkim,suse.de:mid,s3.next:url,imap1.dmz-prg2.suse.org:rdns,imap1.dmz-prg2.suse.org:helo]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_NONE(0.00)[]; RCVD_TLS_ALL(0.00)[]; PREVIOUSLY_DELIVERED(0.00)[gdb-patches@sourceware.org]; DNSWL_BLOCKED(0.00)[2a07:de40:b281:104:10:150:64:97:from,2a07:de40:b281:106:10:150:64:167:received]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; DKIM_TRACE(0.00)[suse.de:+] X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org [ This is related to the STABS reader, which has been removed in gdb 18, so the fix is on top of gdb-17-branch. ] CVE-2026-13732 reports: ... gdb: out-of-bounds write in stabs parser read_member_functions() via crafted elf A flaw was found in GDB's STABS debug format parser. The read_member_functions() function in gdb/stabsread.c contains a linked list removal bug in the code that separates destructor and non-destructor member functions of C++ classes. The bug causes the destructor entries to remain in the main function list while the list length counter is decremented, resulting in an out-of-bounds write when the function list is copied to its final allocated array. An attacker can craft an ELF binary with malicious .stab and .stabstr sections that triggers this out-of-bounds write when a user opens the file in GDB and performs any symbol-inspection operation such as setting a breakpoint. The inferior process does not need to be executed. Under controlled conditions, this was demonstrated to achieve execution of arbitrary commands within the GDB process. ... AFAIU from gdb/SECURITY.txt: ... There are known bugs in GDB related to loading malformed executables and parsing the debug information, a consequence of these bugs is that a malicious program could trigger undefined behavior in GDB, which could be used to trigger arbitrary code execution. Given these risks, the advice of the GDB project is that, when using GDB with an untrusted binary, always do so in a secure, sandboxed environment. As there are already known bugs in GDB relating to undefined behavior triggered from malformed programs, further bugs in this area should still be reported, but are unlikely to be given high priority. Bugs in GDB that are triggered by well-formed programs should also be reported, and are likely to be treated as higher priority as these are more likely to impact normal use of GDB. ... this is not a high priority. Still, it's worthwhile fixing this. The problem is single-linked list update logic in this loop: ... tmp_sublist = sublist; last_sublist = NULL; i = 0; while (tmp_sublist != NULL) { if (!is_destructor_name (tmp_sublist->fn_field.physname)) { tmp_sublist = tmp_sublist->next; continue; } destr_fnlist->fn_fieldlist.fn_fields[i++] = tmp_sublist->fn_field; if (last_sublist) last_sublist->next = tmp_sublist->next; else sublist = tmp_sublist->next; last_sublist = tmp_sublist; tmp_sublist = tmp_sublist->next; } ... I wrote a stand alone reproducer containing fix and unit test: ... #include #include #ifndef FIX #define FIX 0 #endif #ifndef VERBOSE #define VERBOSE 0 #endif struct s { int i; struct s *next; }; static int test_mode = 0; static int max_test_mode = 11; static int test (int i) { switch (test_mode) { case 0: return 0; case 1: return 1; case 2: return i % 2 == 0; case 3: return i % 2 == 1; case 4: return i == 1; case 5: return i != 1; case 6: return i == 6; case 7: return i != 6; case 8: return i >= 5; case 9: return !(i >= 5); case 10: return (i == 3 || i == 4); case 11: return !(i == 3 || i == 4); default: assert (0); } } static struct s * filter (struct s *sublist) { struct s *tmp_sublist; struct s *last_sublist; /* Current element = start of list. Previous element = before start of list == NULL. Legend: l: last_sublist (Previous element) t: tmp_sublist (Current element) s: sublist (Head of list) x: NULL After: l s/t x 1 -> 2 -> 3 */ tmp_sublist = sublist; last_sublist = NULL; while (tmp_sublist != NULL) { if (test (tmp_sublist->i)) { /* Keep element. Required: Update both pointers to their next element. Bug: last_sublist is not updated. Before: l s/t x 1 -> 2 -> 3 After (without fix): l s t x 1 -> 2 -> 3 After (with fix): s/l t 1 -> 2 -> 3 */ if (FIX) last_sublist = tmp_sublist; tmp_sublist = tmp_sublist->next; continue; } if (last_sublist) /* Remove element other than first. Before: s/l t 1 -> 2 -> 3 After: s/l t 1 -> 3 2 */ last_sublist->next = tmp_sublist->next; else /* Remove first element. Before: l s/t x 1 -> 2 -> 3 After: l s t x 2 -> 3 1 */ sublist = tmp_sublist->next; /* Update current element. Required: Because we just removed the current element, we're not updating the previous element. Bug: last_sublist is updated. Before: s/l t 1 -> 3 2 After (without fix): s t l 1 -> 3 2 After (with fix): s/l t 1 -> 3 */ if (!FIX) last_sublist = tmp_sublist; tmp_sublist = tmp_sublist->next; } return sublist; } struct s s1, s2, s3, s4, s5, s6; static int init (int i) { s1.i = 1; s2.i = 2; s3.i = 3; s4.i = 4; s5.i = 5; s6.i = 6; s1.next = NULL; s2.next = &s1; s3.next = &s2; s4.next = &s3; s5.next = &s4; s6.next = &s5; switch (i) { case 0: return 6; case 1: s5.next = NULL; return 2; case 2: s6.next = NULL; return 1; default: assert (false); } } int main () { assert (filter (NULL) == NULL); for (int i = 0; i < 3; ++i) for (test_mode = 0; test_mode <= max_test_mode; ++test_mode) { int len = init (i); struct s *res = filter (&s6); if (VERBOSE) { printf ("EXPECTED: "); for (int i = 6; i > 6 - len; --i) if (test (i)) printf (" %d", i); printf ("\n"); printf ("ACTUAL : "); for (struct s *elem = res; elem != NULL; elem = elem->next) printf (" %d", elem->i); printf ("\n"); } for (struct s *elem = res; elem != NULL; elem = elem->next) assert (test (elem->i)); struct s *elem = res; for (int i = 6; i > 6 - len; --i) if (test (i)) { assert (i == elem->i); elem = elem->next; } assert (elem == NULL); } return 0; } ... This patch applies the same fix in read_member_functions. Relevant links: - http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2026-13732 - https://www.cve.org/CVERecord?id=CVE-2026-13732 - https://access.redhat.com/security/cve/CVE-2026-13732 - https://bugzilla.redhat.com/show_bug.cgi?id=2494416 --- gdb/stabsread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdb/stabsread.c b/gdb/stabsread.c index 2d1411e9146..6cc3c5c7e02 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -5112,6 +5112,7 @@ read_member_functions (struct stab_field_info *fip, const char **pp, { if (!is_destructor_name (tmp_sublist->fn_field.physname)) { + last_sublist = tmp_sublist; tmp_sublist = tmp_sublist->next; continue; } @@ -5122,7 +5123,6 @@ read_member_functions (struct stab_field_info *fip, const char **pp, last_sublist->next = tmp_sublist->next; else sublist = tmp_sublist->next; - last_sublist = tmp_sublist; tmp_sublist = tmp_sublist->next; } base-commit: 2636da31af44fab38c22cee0fe771761173ea64b -- 2.51.0