From patchwork Fri Aug 9 15:03:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1970985 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=C+fmm1UW; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WgRyR0x1dz1yYl for ; Sat, 10 Aug 2024 01:04:15 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5647E385C6C6 for ; Fri, 9 Aug 2024 15:04:13 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 458333858CD9 for ; Fri, 9 Aug 2024 15:03:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 458333858CD9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 458333858CD9 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723215838; cv=none; b=JvhfSogGuLOqcaflaqvm1Rb39G/06d4dwXo5cfGHwAU5UpfKKqXwdKnoxVM+6DLWQ+GVfJ2O0DDfEfz+BQZs9rtYhwnqCTaAl/E2xUzoIv1bl+7VkhehRgys4X2H0t2fgt63FCa0h9FKLTx0A1NcMrnXl1aFkdSaU9saGrfmZ98= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723215838; c=relaxed/simple; bh=4X5wrhsCorAnCMuV2xGTNcfV68NeVzRNmKtUB+GntdM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=aDX7XJFUDXfyU+S6x9mOOKY2/NblveqI9lgIS7t+JvPmvUYTvD/3FdmfZO8wIUGEsXfkZHRU5lZcChLzh4QSRZy1HfSy6J4/ALvd3aPpiscBUwUTEDuDJDZCKVg39+7xJ6zAul/N8scleU44WoIZq0pVido80KJ4xBqwPQH7Y1M= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1723215837; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=232DIqMiBn3UhwuPCJIAqbLtGfwPDc2SBPjF76eNNQI=; b=C+fmm1UWFNsOM8INKlMsWcC3xbkxKFT2erqFK2h2q5PGrFinL9Aky2zf1F+7ER1B4HOIzV h/ttJwyLZt4QKLb6PXeJWrPamg65KT/+xD6wM5TVtsyokuX5SZTR24PahMz9conqYgClKe ql330YJZXOWvYq9Ma1EoCMteLmtoruc= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-393-GhgVBaD9NhuMFzuV0fzvkQ-1; Fri, 09 Aug 2024 11:03:55 -0400 X-MC-Unique: GhgVBaD9NhuMFzuV0fzvkQ-1 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 33A8F1955F0D for ; Fri, 9 Aug 2024 15:03:52 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.2.16.5]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 456DF19560A3 for ; Fri, 9 Aug 2024 15:03:50 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH v2] string: strerror, strsignal cannot use buffer after dlmopen (bug 32026) Date: Fri, 09 Aug 2024 17:03:48 +0200 Message-ID: <87jzgpg2ln.fsf@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP 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: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org Secondary namespaces have a different malloc. Allocating the buffer in one namespace and freeing it another results in heap corruption. Fix this by using a static string (potentially translated) in secondary namespaces. It would also be possible to use the malloc from the initial namespace to manage the buffer, but these functions would still not be safe to use in auditors etc. because a call to strerror could still free a buffer while it is used by the application. Another approach could use proper initial-exec TLS, duplicated in secondary namespaces, but that would need a callback interface for freeing libc resources in namespaces on thread exit, which does not exist today. Reviewed-by: Adhemerval Zanella --- v2: Fix double-free bug in strsignal (after asprintf failure). string/strerror_l.c | 35 ++++++++++++++++++++++++----------- string/strsignal.c | 34 +++++++++++++++++++++------------- 2 files changed, 45 insertions(+), 24 deletions(-) base-commit: eb0e50e9a1cf80a2ba6f33f990a08ef37a3267fb diff --git a/string/strerror_l.c b/string/strerror_l.c index 15cce261e6..70456e5bb4 100644 --- a/string/strerror_l.c +++ b/string/strerror_l.c @@ -20,7 +20,7 @@ #include #include #include - +#include static const char * translate (const char *str, locale_t loc) @@ -31,6 +31,12 @@ translate (const char *str, locale_t loc) return res; } +static char * +unknown_error (locale_t loc) +{ + return (char *) translate ("Unknown error", loc); +} + /* Return a string describing the errno code in ERRNUM. */ char * @@ -40,18 +46,25 @@ __strerror_l (int errnum, locale_t loc) char *err = (char *) __get_errlist (errnum); if (__glibc_unlikely (err == NULL)) { - struct tls_internal_t *tls_internal = __glibc_tls_internal (); - free (tls_internal->strerror_l_buf); - if (__asprintf (&tls_internal->strerror_l_buf, "%s%d", - translate ("Unknown error ", loc), errnum) > 0) - err = tls_internal->strerror_l_buf; - else + if (__libc_initial) { - /* The memory was freed above. */ - tls_internal->strerror_l_buf = NULL; - /* Provide a fallback translation. */ - err = (char *) translate ("Unknown error", loc); + struct tls_internal_t *tls_internal = __glibc_tls_internal (); + free (tls_internal->strerror_l_buf); + if (__asprintf (&tls_internal->strerror_l_buf, "%s%d", + translate ("Unknown error ", loc), errnum) > 0) + err = tls_internal->strerror_l_buf; + else + { + /* The memory was freed above. */ + tls_internal->strerror_l_buf = NULL; + /* Provide a fallback translation. */ + err = unknown_error (loc); + } } + else + /* Secondary namespaces use a different malloc, so cannot + participate in the buffer management. */ + err = unknown_error (loc); } else err = (char *) translate (err, loc); diff --git a/string/strsignal.c b/string/strsignal.c index 3114601564..d9b0365468 100644 --- a/string/strsignal.c +++ b/string/strsignal.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Return a string describing the meaning of the signal number SIGNUM. */ char * @@ -30,21 +31,28 @@ strsignal (int signum) if (desc != NULL) return _(desc); - struct tls_internal_t *tls_internal = __glibc_tls_internal (); - free (tls_internal->strsignal_buf); + if (__libc_initial) + { + struct tls_internal_t *tls_internal = __glibc_tls_internal (); + free (tls_internal->strsignal_buf); - int r; + int r; #ifdef SIGRTMIN - if (signum >= SIGRTMIN && signum <= SIGRTMAX) - r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"), - signum - SIGRTMIN); - else + if (signum >= SIGRTMIN && signum <= SIGRTMAX) + r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"), + signum - SIGRTMIN); + else #endif - r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"), - signum); + r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"), + signum); - if (r == -1) - tls_internal->strsignal_buf = NULL; - - return tls_internal->strsignal_buf; + if (r >= 0) + return tls_internal->strsignal_buf; + else + tls_internal->strsignal_buf = NULL; + } + /* Fall through on asprintf error, and for !__libc_initial: + secondary namespaces use a different malloc and cannot + participate in the buffer management. */ + return _("Unknown signal"); }