unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
From: Olivier Dion via "Bug reports for GUILE, GNU's Ubiquitous Extension Language" <bug-guile@gnu.org>
To: 62729@debbugs.gnu.org
Cc: Olivier Dion <olivier-dion@proton.me>
Subject: bug#62729: [PATCH] Fix dangling pointers in `environ'
Date: Sat,  8 Apr 2023 16:48:01 -0400	[thread overview]
Message-ID: <20230408204801.10408-1-olivier.dion@polymtl.ca> (raw)

From: Olivier Dion <olivier-dion@proton.me>

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






             reply	other threads:[~2023-04-08 20:48 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-08 20:48 Olivier Dion via Bug reports for GUILE, GNU's Ubiquitous Extension Language [this message]
2023-07-16 20:18 ` bug#62729: [PATCH] Fix dangling pointers in `environ' Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230408204801.10408-1-olivier.dion@polymtl.ca \
    --to=bug-guile@gnu.org \
    --cc=62729@debbugs.gnu.org \
    --cc=olivier-dion@proton.me \
    --cc=olivier.dion@polymtl.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).