From unknown Tue Aug 19 18:07:57 2025 X-Loop: help-debbugs@gnu.org Subject: bug#62729: [PATCH] Fix dangling pointers in `environ' Resent-From: Olivier Dion Original-Sender: "Debbugs-submit" Resent-CC: bug-guile@gnu.org Resent-Date: Sat, 08 Apr 2023 20:49:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 62729 X-GNU-PR-Package: guile X-GNU-PR-Keywords: patch To: 62729@debbugs.gnu.org Cc: Olivier Dion X-Debbugs-Original-To: bug-guile@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.168098690616868 (code B ref -1); Sat, 08 Apr 2023 20:49:02 +0000 Received: (at submit) by debbugs.gnu.org; 8 Apr 2023 20:48:26 +0000 Received: from localhost ([127.0.0.1]:59706 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1plFU1-0004Ny-Be for submit@debbugs.gnu.org; Sat, 08 Apr 2023 16:48:25 -0400 Received: from lists.gnu.org ([209.51.188.17]:58906) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1plFTy-0004Nc-Dy for submit@debbugs.gnu.org; Sat, 08 Apr 2023 16:48:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plFTx-0007fW-BL for bug-guile@gnu.org; Sat, 08 Apr 2023 16:48:21 -0400 Received: from smtp.polymtl.ca ([132.207.4.11]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plFTu-000528-SL for bug-guile@gnu.org; Sat, 08 Apr 2023 16:48:20 -0400 Received: from laura.hitronhub.home (modemcable094.169-200-24.mc.videotron.ca [24.200.169.94]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 338Km2lk007168 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 8 Apr 2023 16:48:10 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 338Km2lk007168 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=default; t=1680986891; bh=B8nLyrfW99d6XL/3kTuK8p53nbp8VZrNm7bYIyb3gcw=; h=From:To:Cc:Subject:Date:From; b=O8zoNnl7zwvoZBoXmmsd19xaon9dyHVVzdrd8eqCq6KQa7x7R6ngZFlIoon7ofZn4 SUB3vUmmVZVMmHdR6aqKt9jmYnL093CnyoysQszLr664pLQrxMd1EL78p3+ejy7Cc2 J3zZJlWLJfE1Z/G0JbEmaRwf6OjOYf/hK+SfL6JA= From: Olivier Dion Date: Sat, 8 Apr 2023 16:48:01 -0400 Message-Id: <20230408204801.10408-1-olivier.dion@polymtl.ca> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Poly-FromMTA: (modemcable094.169-200-24.mc.videotron.ca [24.200.169.94]) at Sat, 8 Apr 2023 20:48:02 +0000 Received-SPF: pass client-ip=132.207.4.11; envelope-from=olivier.dion@polymtl.ca; helo=smtp.polymtl.ca X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) From: Olivier Dion When calling `environ', Guile set the global variable `environ' to a list allocated with the GC. Strings in it are also allocated with the GC. However, if an user call the Scheme setenv() procedure, the resulting call to putenv() in libc might reallocate `environ' to a new pointer while copying sub-pointers owned by Guile in it. This results in the GC marking these strings for reclamation when they are actually still present in `environ'. Thus, the values in the environment are now undefined. To fix this, Guile should only manipulate the `environ' using the standard libc functions. This ensures that concurrent modification of it is safe in multi-threaded program. Therefore, the procedure `environ' now call the libc clearenv() procedure to purge the environment. Then, the desired values are put in `environ' using scm_putenv(). At the end, no GC allocated memory is put in `environ'. Also, since `environ' can be changed at anytime in a multi-thread program, emit a warning stipulating that the result is undefined behavior if multiple threads are created in the program. Consider for example a thread iterating over `environ' while another one do a call to putenv(). The latter would do a realloc() on `environ' and thus the old array read by the former now contains garbage. On system where clearenv() is not present, an atomic store of NULL with sequential consistency to `environ' should be sufficient but see the NOTES of clearenv(3). * libguile/posix.c (scm_environ): Do not store GC allocated memory in environ. --- libguile/posix.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libguile/posix.c b/libguile/posix.c index 3adc743c4..808a3f93b 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1736,11 +1736,28 @@ SCM_DEFINE (scm_environ, "environ", 0, 1, 0, "then the return value is unspecified.") #define FUNC_NAME s_scm_environ { + /* Accessing `environ' directly in a multi-threaded program is + undefined behavior since at anytime it could point to anything else + while reading it. Not only that, but all accesses are protected by + an internal mutex of libc. Thus, it is only truly safe to modify + the environment directly in a single-threaded program. */ + if (scm_ilength (scm_all_threads ()) != 1) + scm_display + (scm_from_latin1_string + ("warning: call to environ while multiple threads are running;\n" + " further behavior unspecified.\n"), + scm_current_warning_port ()); + if (SCM_UNBNDP (env)) return scm_makfromstrs (-1, environ); else { - environ = scm_i_allocate_string_pointers (env); + clearenv(); + while (!scm_is_null (env)) + { + scm_putenv (scm_car (env)); + env = scm_cdr (env); + } return SCM_UNSPECIFIED; } } -- 2.39.2 From unknown Tue Aug 19 18:07:57 2025 MIME-Version: 1.0 X-Mailer: MIME-tools 5.505 (Entity 5.505) X-Loop: help-debbugs@gnu.org From: help-debbugs@gnu.org (GNU bug Tracking System) To: Olivier Dion Subject: bug#62729: closed (Re: bug#62729: [PATCH] Fix dangling pointers in `environ') Message-ID: References: <87sf9nr4nl.fsf@gnu.org> <20230408204801.10408-1-olivier.dion@polymtl.ca> X-Gnu-PR-Message: they-closed 62729 X-Gnu-PR-Package: guile X-Gnu-PR-Keywords: patch Reply-To: 62729@debbugs.gnu.org Date: Sun, 16 Jul 2023 20:20:02 +0000 Content-Type: multipart/mixed; boundary="----------=_1689538802-13651-1" This is a multi-part message in MIME format... ------------=_1689538802-13651-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Your bug report #62729: [PATCH] Fix dangling pointers in `environ' which was filed against the guile package, has been closed. The explanation is attached below, along with your original report. If you require more details, please reply to 62729@debbugs.gnu.org. --=20 62729: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D62729 GNU Bug Tracking System Contact help-debbugs@gnu.org with problems ------------=_1689538802-13651-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at 62729-done) by debbugs.gnu.org; 16 Jul 2023 20:19:04 +0000 Received: from localhost ([127.0.0.1]:48641 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qL8Ct-0003Wp-Ug for submit@debbugs.gnu.org; Sun, 16 Jul 2023 16:19:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43770) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qL8Cs-0003WL-87 for 62729-done@debbugs.gnu.org; Sun, 16 Jul 2023 16:19:03 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qL8Cm-0005lj-Gn; Sun, 16 Jul 2023 16:18:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:In-Reply-To:Date:References:Subject:To: From; bh=vxEMgBrIFfvLmK5pQtcitLox94SCp4N/HBGKL6kv/1M=; b=o5NhFLnCtQJUJBjErlmQ W0pgDcab3aLtUKJBP+80kujZIXSa+18kF4PInpglZKuSmiYy8kD6j/lDuhMuMcg7mxXAPfV6SPum7 AYWRA8eoSoXydQx6lJN8hC4S9SZG1EuKpKEBictdePHYYR7YZofeILJVgszO4miL23TNJRCm05V6/ eQpafklaiIQSVc2W3wYFFb8g1c56vVM5O/a9TCoZ0/52ybdNba84V/e/yLIuSfBJ4Va1zFr5gLPIw pCfh6ET20MnQkhdvpDAhtU4axBz1ZlErmQxVZMDGem6vBMA3KCWxobeVnQwVW/exvKgBBzWpUh2ak 4xfxuVl3Asm23g==; Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (helo=ribbon) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qL8Cm-0001uQ-4Y; Sun, 16 Jul 2023 16:18:56 -0400 From: =?utf-8?Q?Ludovic_Court=C3=A8s?= To: Olivier Dion Subject: Re: bug#62729: [PATCH] Fix dangling pointers in `environ' References: <20230408204801.10408-1-olivier.dion@polymtl.ca> Date: Sun, 16 Jul 2023 22:18:54 +0200 In-Reply-To: <20230408204801.10408-1-olivier.dion@polymtl.ca> (Olivier Dion's message of "Sat, 8 Apr 2023 16:48:01 -0400") Message-ID: <87sf9nr4nl.fsf@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 62729-done Cc: 62729-done@debbugs.gnu.org, Olivier Dion X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) Hi Olivier, Olivier Dion skribis: > From: Olivier Dion > > When calling `environ', Guile set the global variable `environ' to a > list allocated with the GC. Strings in it are also allocated with the > GC. > > However, if an user call the Scheme setenv() procedure, the resulting > call to putenv() in libc might reallocate `environ' to a new pointer > while copying sub-pointers owned by Guile in it. > > This results in the GC marking these strings for reclamation when they > are actually still present in `environ'. Thus, the values in the > environment are now undefined. > > To fix this, Guile should only manipulate the `environ' using the > standard libc functions. This ensures that concurrent modification of > it is safe in multi-threaded program. Therefore, the procedure > `environ' now call the libc clearenv() procedure to purge the > environment. Then, the desired values are put in `environ' using > scm_putenv(). At the end, no GC allocated memory is put in `environ'. > > Also, since `environ' can be changed at anytime in a multi-thread > program, emit a warning stipulating that the result is undefined > behavior if multiple threads are created in the program. Consider for > example a thread iterating over `environ' while another one do a call to > putenv(). The latter would do a realloc() on `environ' and thus the old > array read by the former now contains garbage. > > On system where clearenv() is not present, an atomic store of NULL with > sequential consistency to `environ' should be sufficient but see the > NOTES of clearenv(3). > > * libguile/posix.c (scm_environ): Do not store GC allocated memory in > environ. Thanks for the clear explanation and patch. Finally applied with an added comment in the code. Ludo=E2=80=99. ------------=_1689538802-13651-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at submit) by debbugs.gnu.org; 8 Apr 2023 20:48:26 +0000 Received: from localhost ([127.0.0.1]:59706 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1plFU1-0004Ny-Be for submit@debbugs.gnu.org; Sat, 08 Apr 2023 16:48:25 -0400 Received: from lists.gnu.org ([209.51.188.17]:58906) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1plFTy-0004Nc-Dy for submit@debbugs.gnu.org; Sat, 08 Apr 2023 16:48:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plFTx-0007fW-BL for bug-guile@gnu.org; Sat, 08 Apr 2023 16:48:21 -0400 Received: from smtp.polymtl.ca ([132.207.4.11]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1plFTu-000528-SL for bug-guile@gnu.org; Sat, 08 Apr 2023 16:48:20 -0400 Received: from laura.hitronhub.home (modemcable094.169-200-24.mc.videotron.ca [24.200.169.94]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id 338Km2lk007168 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 8 Apr 2023 16:48:10 -0400 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp.polymtl.ca 338Km2lk007168 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=polymtl.ca; s=default; t=1680986891; bh=B8nLyrfW99d6XL/3kTuK8p53nbp8VZrNm7bYIyb3gcw=; h=From:To:Cc:Subject:Date:From; b=O8zoNnl7zwvoZBoXmmsd19xaon9dyHVVzdrd8eqCq6KQa7x7R6ngZFlIoon7ofZn4 SUB3vUmmVZVMmHdR6aqKt9jmYnL093CnyoysQszLr664pLQrxMd1EL78p3+ejy7Cc2 J3zZJlWLJfE1Z/G0JbEmaRwf6OjOYf/hK+SfL6JA= From: Olivier Dion To: bug-guile@gnu.org Subject: [PATCH] Fix dangling pointers in `environ' Date: Sat, 8 Apr 2023 16:48:01 -0400 Message-Id: <20230408204801.10408-1-olivier.dion@polymtl.ca> X-Mailer: git-send-email 2.39.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Poly-FromMTA: (modemcable094.169-200-24.mc.videotron.ca [24.200.169.94]) at Sat, 8 Apr 2023 20:48:02 +0000 Received-SPF: pass client-ip=132.207.4.11; envelope-from=olivier.dion@polymtl.ca; helo=smtp.polymtl.ca X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-Debbugs-Envelope-To: submit Cc: Olivier Dion X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) From: Olivier Dion When calling `environ', Guile set the global variable `environ' to a list allocated with the GC. Strings in it are also allocated with the GC. However, if an user call the Scheme setenv() procedure, the resulting call to putenv() in libc might reallocate `environ' to a new pointer while copying sub-pointers owned by Guile in it. This results in the GC marking these strings for reclamation when they are actually still present in `environ'. Thus, the values in the environment are now undefined. To fix this, Guile should only manipulate the `environ' using the standard libc functions. This ensures that concurrent modification of it is safe in multi-threaded program. Therefore, the procedure `environ' now call the libc clearenv() procedure to purge the environment. Then, the desired values are put in `environ' using scm_putenv(). At the end, no GC allocated memory is put in `environ'. Also, since `environ' can be changed at anytime in a multi-thread program, emit a warning stipulating that the result is undefined behavior if multiple threads are created in the program. Consider for example a thread iterating over `environ' while another one do a call to putenv(). The latter would do a realloc() on `environ' and thus the old array read by the former now contains garbage. On system where clearenv() is not present, an atomic store of NULL with sequential consistency to `environ' should be sufficient but see the NOTES of clearenv(3). * libguile/posix.c (scm_environ): Do not store GC allocated memory in environ. --- libguile/posix.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libguile/posix.c b/libguile/posix.c index 3adc743c4..808a3f93b 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1736,11 +1736,28 @@ SCM_DEFINE (scm_environ, "environ", 0, 1, 0, "then the return value is unspecified.") #define FUNC_NAME s_scm_environ { + /* Accessing `environ' directly in a multi-threaded program is + undefined behavior since at anytime it could point to anything else + while reading it. Not only that, but all accesses are protected by + an internal mutex of libc. Thus, it is only truly safe to modify + the environment directly in a single-threaded program. */ + if (scm_ilength (scm_all_threads ()) != 1) + scm_display + (scm_from_latin1_string + ("warning: call to environ while multiple threads are running;\n" + " further behavior unspecified.\n"), + scm_current_warning_port ()); + if (SCM_UNBNDP (env)) return scm_makfromstrs (-1, environ); else { - environ = scm_i_allocate_string_pointers (env); + clearenv(); + while (!scm_is_null (env)) + { + scm_putenv (scm_car (env)); + env = scm_cdr (env); + } return SCM_UNSPECIFIED; } } -- 2.39.2 ------------=_1689538802-13651-1--