From 3dc77fef24ba9122c31ec2f44d70f9c49aae771e Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 14:19:37 +0100 Subject: [PATCH 1/7] gsocket: Use accept4 () for race-free setting of the close-on-exec flag The code was already setting the close-on-exec flag for the new socket, just in a racy way. --- gio/gsocket.c | 26 +++++++++++++++++++++++++- meson.build | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/gio/gsocket.c b/gio/gsocket.c index 0ccc53f98..2dc005b63 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -2858,6 +2858,9 @@ g_socket_accept (GSocket *socket, GCancellable *cancellable, GError **error) { +#ifdef HAVE_ACCEPT4 + gboolean try_accept4 = TRUE; +#endif GSocket *new_socket; gint ret; @@ -2871,7 +2874,28 @@ g_socket_accept (GSocket *socket, while (TRUE) { - if ((ret = accept (socket->priv->fd, NULL, 0)) < 0) + gboolean try_accept = TRUE; + +#ifdef HAVE_ACCEPT4 + if (try_accept4) + { + ret = accept4 (socket->priv->fd, NULL, 0, SOCK_CLOEXEC); + if (ret < 0 && errno == ENOSYS) + { + try_accept4 = FALSE; + } + else + { + try_accept = FALSE; + } + } + + g_assert (try_accept4 || try_accept); +#endif + if (try_accept) + ret = accept (socket->priv->fd, NULL, 0); + + if (ret < 0) { int errsv = get_socket_errno (); diff --git a/meson.build b/meson.build index 4630025ca..f9baa409b 100644 --- a/meson.build +++ b/meson.build @@ -606,6 +606,7 @@ if host_system == 'windows' endif functions = [ + 'accept4', 'close_range', 'endmntent', 'endservent', From 14b5207bfa40ab6419abc145680dcfbf190c78bb Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 14:41:19 +0100 Subject: [PATCH 2/7] Add g_unix_open_pipe_internal () for pipes with the close-on-exec flag Based on the existing g_unix_open_pipe () but for internal use where returning a raw errno is needed, not a GError. --- docs/reference/glib/meson.build | 1 + glib/glib-unix.c | 45 ++--------------- glib/glib-unixprivate.h | 87 +++++++++++++++++++++++++++++++++ glib/meson.build | 2 +- 4 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 glib/glib-unixprivate.h diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build index 06685702e..114de49da 100644 --- a/docs/reference/glib/meson.build +++ b/docs/reference/glib/meson.build @@ -38,6 +38,7 @@ if get_option('gtk_doc') 'gutilsprivate.h', 'gvalgrind.h', 'dirent.h', + 'glib-unixprivate.h', 'glib-visibility.h', 'gmodule-visibility.h', ] diff --git a/glib/glib-unix.c b/glib/glib-unix.c index bc152d766..1c9f12599 100644 --- a/glib/glib-unix.c +++ b/glib/glib-unix.c @@ -23,12 +23,8 @@ #include "config.h" -/* To make bionic export pipe2() */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - #include "glib-unix.h" +#include "glib-unixprivate.h" #include "gmain-internal.h" #include @@ -94,48 +90,13 @@ g_unix_open_pipe (int *fds, int flags, GError **error) { - int ecode; - /* We only support FD_CLOEXEC */ g_return_val_if_fail ((flags & (FD_CLOEXEC)) == flags, FALSE); -#ifdef HAVE_PIPE2 - { - int pipe2_flags = 0; - if (flags & FD_CLOEXEC) - pipe2_flags |= O_CLOEXEC; - /* Atomic */ - ecode = pipe2 (fds, pipe2_flags); - if (ecode == -1 && errno != ENOSYS) - return g_unix_set_error_from_errno (error, errno); - else if (ecode == 0) - return TRUE; - /* Fall through on -ENOSYS, we must be running on an old kernel */ - } -#endif - ecode = pipe (fds); - if (ecode == -1) + if (!g_unix_open_pipe_internal (fds, + (flags & FD_CLOEXEC) != 0)) return g_unix_set_error_from_errno (error, errno); - if (flags == 0) - return TRUE; - - ecode = fcntl (fds[0], F_SETFD, flags); - if (ecode == -1) - { - int saved_errno = errno; - close (fds[0]); - close (fds[1]); - return g_unix_set_error_from_errno (error, saved_errno); - } - ecode = fcntl (fds[1], F_SETFD, flags); - if (ecode == -1) - { - int saved_errno = errno; - close (fds[0]); - close (fds[1]); - return g_unix_set_error_from_errno (error, saved_errno); - } return TRUE; } diff --git a/glib/glib-unixprivate.h b/glib/glib-unixprivate.h new file mode 100644 index 000000000..d4c64bd1e --- /dev/null +++ b/glib/glib-unixprivate.h @@ -0,0 +1,87 @@ +/* glib-unixprivate.h - Unix specific integration private functions + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see . + */ + +#ifndef __G_UNIXPRIVATE_H__ +#define __G_UNIXPRIVATE_H__ + +#include "config.h" + +#ifndef G_OS_UNIX +#error "This header may only be used on UNIX" +#endif + +/* To make bionic export pipe2() */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#include "gmacros.h" +#include "gtypes.h" + +#include +#include +#include + +G_BEGIN_DECLS + +static inline gboolean +g_unix_open_pipe_internal (int *fds, + gboolean close_on_exec) + { +#ifdef HAVE_PIPE2 + do + { + int ecode; + + /* Atomic */ + ecode = pipe2 (fds, close_on_exec ? O_CLOEXEC : 0); + if (ecode == -1 && errno != ENOSYS) + return FALSE; + else if (ecode == 0) + return TRUE; + /* Fall through on -ENOSYS, we must be running on an old kernel */ + } + while (FALSE); +#endif + + if (pipe (fds) == -1) + return FALSE; + + if (!close_on_exec) + return TRUE; + + if (fcntl (fds[0], F_SETFD, FD_CLOEXEC) == -1 || + fcntl (fds[1], F_SETFD, FD_CLOEXEC) == -1) + { + int saved_errno = errno; + + close (fds[0]); + close (fds[1]); + fds[0] = -1; + fds[1] = -1; + + errno = saved_errno; + return FALSE; + } + + return TRUE; +} + +G_END_DECLS + +#endif /* __G_UNIXPRIVATE_H__ */ diff --git a/glib/meson.build b/glib/meson.build index 75b3b4018..da76fc005 100644 --- a/glib/meson.build +++ b/glib/meson.build @@ -365,7 +365,7 @@ if host_system == 'windows' glib_sources += files('dirent/wdirent.c') endif else - glib_sources += files('glib-unix.c', 'gspawn.c', 'giounix.c') + glib_sources += files('glib-unix.c', 'glib-unixprivate.h', 'gspawn.c', 'giounix.c') platform_deps = [] endif From 05d2a1d09757feb1aea2926ce7f205a4aa1e2d7f Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 14:44:28 +0100 Subject: [PATCH 3/7] gbacktrace: Use g_unix_open_pipe_internal () for creating pipes This attempts to create the pipes with race-free setting of the close-on-exec flag. --- glib/gbacktrace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c index 9c52a7d29..b708b1636 100644 --- a/glib/gbacktrace.c +++ b/glib/gbacktrace.c @@ -45,6 +45,7 @@ #include #ifdef G_OS_UNIX +#include "glib-unixprivate.h" #include #include #include @@ -397,7 +398,8 @@ stack_trace (const char * const *args) stack_trace_done = FALSE; signal (SIGCHLD, stack_trace_sigchld); - if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1)) + if (!g_unix_open_pipe_internal (in_fd, TRUE) || + !g_unix_open_pipe_internal (out_fd, TRUE)) { perror ("unable to open pipe"); _exit (0); From dd36ee0abfef10aec44cb00972c4de6f95b14e24 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 14:45:50 +0100 Subject: [PATCH 4/7] gtestdbus: Use g_unix_open_pipe_internal () for creating pipes This attempts to create the pipes with race-free setting of the close-on-exec flag. --- gio/gtestdbus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c index 6aedb3eae..34cead176 100644 --- a/gio/gtestdbus.c +++ b/gio/gtestdbus.c @@ -50,6 +50,7 @@ #ifdef G_OS_UNIX #include "glib-unix.h" +#include "glib-unixprivate.h" #endif /* -------------------------------------------------------------------------- */ @@ -248,7 +249,7 @@ watcher_init (void) gint pipe_fds[2]; /* fork a child to clean up when we are killed */ - if (pipe (pipe_fds) != 0) + if (!g_unix_open_pipe_internal (pipe_fds, TRUE)) { errsv = errno; g_warning ("pipe() failed: %s", g_strerror (errsv)); From 0f5d2748719627fafbdcfd67a776002cd6ffae81 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 14:47:00 +0100 Subject: [PATCH 5/7] gtestutils: Document that g_test_trap_fork () won't get close-on-exec fix We don't want to update this function in case some crusty old third party code might be relying on its current behavior. Also, it is deprecated anyway and no code should be using it. --- glib/gtestutils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glib/gtestutils.c b/glib/gtestutils.c index 1a63bfe42..fcf1caff3 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -3858,8 +3858,9 @@ wait_for_child (GPid pid, * Since: 2.16 * * Deprecated: This function is implemented only on Unix platforms, - * and is not always reliable due to problems inherent in - * fork-without-exec. Use g_test_trap_subprocess() instead. + * is not always reliable due to problems inherent in fork-without-exec + * and doesn't set close-on-exec flag on its file descriptors. + * Use g_test_trap_subprocess() instead. */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS gboolean From 3f2e18b07c24686bd7d67839daac3566d634243d Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 16:22:22 +0100 Subject: [PATCH 6/7] Use O_CLOEXEC in {g_,}open () calls for race-free setting of the close-on-exec flag The remaining call sites are either Windows-only, between fork () and exec () or in xdgmime copylib. Hope I haven't missed any site. --- gio/gdbusauthmechanismsha1.c | 6 +++++- gio/glocalfile.c | 12 ++++++++---- gio/glocalfileinfo.c | 8 ++++++-- gio/glocalfileoutputstream.c | 16 ++++++++-------- gio/kqueue/gkqueuefilemonitor.c | 6 +++++- glib/gfileutils.c | 6 +++--- glib/giounix.c | 6 +++++- glib/gkeyfile.c | 8 ++++++-- glib/gmappedfile.c | 6 +++++- gmodule/gmodule.c | 6 +++++- 10 files changed, 56 insertions(+), 24 deletions(-) diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c index fb6488a2a..c8aa08977 100644 --- a/gio/gdbusauthmechanismsha1.c +++ b/gio/gdbusauthmechanismsha1.c @@ -37,6 +37,10 @@ #include "gwin32sid.h" #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "gdbusauthmechanismsha1.h" #include "gcredentials.h" #include "gdbuserror.h" @@ -519,7 +523,7 @@ create_lock_exclusive (const gchar *lock_path, int errsv; gint ret; - ret = g_open (lock_path, O_CREAT | O_EXCL, 0600); + ret = g_open (lock_path, O_CREAT | O_EXCL | O_CLOEXEC, 0600); errsv = errno; if (ret < 0) { diff --git a/gio/glocalfile.c b/gio/glocalfile.c index a6fea94a2..2b43ff47c 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -51,6 +51,10 @@ #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "gfileattribute.h" #include "glocalfile.h" #include "glocalfileinfo.h" @@ -1352,7 +1356,7 @@ g_local_file_read (GFile *file, int fd, ret; GLocalFileStat buf; - fd = g_open (local->filename, O_RDONLY|O_BINARY, 0); + fd = g_open (local->filename, O_RDONLY | O_BINARY | O_CLOEXEC, 0); if (fd == -1) { int errsv = errno; @@ -2227,7 +2231,7 @@ g_local_file_trash (GFile *file, infofile = g_build_filename (infodir, infoname, NULL); g_free (infoname); - fd = g_open (infofile, O_CREAT | O_EXCL, 0666); + fd = g_open (infofile, O_CREAT | O_EXCL | O_CLOEXEC, 0666); errsv = errno; } while (fd == -1 && errsv == EEXIST); @@ -2881,9 +2885,9 @@ g_local_file_measure_size_of_file (gint parent_fd, #ifdef AT_FDCWD #ifdef HAVE_OPEN_O_DIRECTORY - dir_fd = openat (parent_fd, name->data, O_RDONLY|O_DIRECTORY); + dir_fd = openat (parent_fd, name->data, O_RDONLY | O_DIRECTORY | O_CLOEXEC); #else - dir_fd = openat (parent_fd, name->data, O_RDONLY); + dir_fd = openat (parent_fd, name->data, O_RDONLY | O_CLOEXEC); #endif errsv = errno; if (dir_fd < 0) diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 420e9d4b2..dab34c67b 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -92,6 +92,10 @@ #endif #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "glocalfileinfo.h" #include "gioerror.h" #include "gthemedicon.h" @@ -1391,11 +1395,11 @@ get_content_type (const char *basename, sniff_length = 4096; #ifdef O_NOATIME - fd = g_open (path, O_RDONLY | O_NOATIME, 0); + fd = g_open (path, O_RDONLY | O_NOATIME | O_CLOEXEC, 0); errsv = errno; if (fd < 0 && errsv == EPERM) #endif - fd = g_open (path, O_RDONLY, 0); + fd = g_open (path, O_RDONLY | O_CLOEXEC, 0); if (fd != -1) { diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c index 3ce987fba..74a642da8 100644 --- a/gio/glocalfileoutputstream.c +++ b/gio/glocalfileoutputstream.c @@ -700,7 +700,7 @@ _g_local_file_output_stream_open (const char *filename, if (g_cancellable_set_error_if_cancelled (cancellable, error)) return NULL; - open_flags = O_BINARY; + open_flags = O_BINARY | O_CLOEXEC; if (readable) open_flags |= O_RDWR; else @@ -737,7 +737,7 @@ _g_local_file_output_stream_create (const char *filename, mode = mode_from_flags_or_info (flags, reference_info); - open_flags = O_CREAT | O_EXCL | O_BINARY; + open_flags = O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC; if (readable) open_flags |= O_RDWR; else @@ -762,7 +762,7 @@ _g_local_file_output_stream_append (const char *filename, else mode = 0666; - return output_stream_open (filename, O_CREAT | O_APPEND | O_WRONLY | O_BINARY, mode, + return output_stream_open (filename, O_CREAT | O_APPEND | O_WRONLY | O_BINARY | O_CLOEXEC, mode, cancellable, error); } @@ -865,9 +865,9 @@ handle_overwrite_open (const char *filename, /* We only need read access to the original file if we are creating a backup. * We also add O_CREAT to avoid a race if the file was just removed */ if (create_backup || readable) - open_flags = O_RDWR | O_CREAT | O_BINARY; + open_flags = O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC; else - open_flags = O_WRONLY | O_CREAT | O_BINARY; + open_flags = O_WRONLY | O_CREAT | O_BINARY | O_CLOEXEC; /* Some systems have O_NOFOLLOW, which lets us avoid some races * when finding out if the file we opened was a symlink */ @@ -1113,7 +1113,7 @@ handle_overwrite_open (const char *filename, } bfd = g_open (backup_filename, - O_WRONLY | O_CREAT | O_EXCL | O_BINARY, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, _g_stat_mode (&original_stat) & 0777); if (bfd == -1) @@ -1208,9 +1208,9 @@ handle_overwrite_open (const char *filename, } if (readable) - open_flags = O_RDWR | O_CREAT | O_BINARY; + open_flags = O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC; else - open_flags = O_WRONLY | O_CREAT | O_BINARY; + open_flags = O_WRONLY | O_CREAT | O_BINARY | O_CLOEXEC; fd = g_open (filename, open_flags, mode); if (fd == -1) { diff --git a/gio/kqueue/gkqueuefilemonitor.c b/gio/kqueue/gkqueuefilemonitor.c index f69f98e1c..b664753a1 100644 --- a/gio/kqueue/gkqueuefilemonitor.c +++ b/gio/kqueue/gkqueuefilemonitor.c @@ -32,6 +32,10 @@ #include #include +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include #include #include @@ -583,7 +587,7 @@ _kqsub_start_watching (kqueue_sub *sub) struct stat st; struct kevent ev; - sub->fd = open (sub->filename, O_KQFLAG); + sub->fd = open (sub->filename, O_KQFLAG | O_CLOEXEC); if (sub->fd == -1) return FALSE; diff --git a/glib/gfileutils.c b/glib/gfileutils.c index 826c5e242..ef3fc90f2 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -329,7 +329,7 @@ g_mkdir_with_parents (const gchar *pathname, * } * * // DO THIS INSTEAD - * fd = g_open (filename, O_WRONLY | O_NOFOLLOW); + * fd = g_open (filename, O_WRONLY | O_NOFOLLOW | O_CLOEXEC); * if (fd == -1) * { * // check error @@ -908,7 +908,7 @@ get_contents_posix (const gchar *filename, gint fd; /* O_BINARY useful on Cygwin */ - fd = open (filename, O_RDONLY|O_BINARY); + fd = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC); if (fd < 0) { @@ -1083,7 +1083,7 @@ rename_file (const char *old_name, if (do_fsync) { gchar *dir = g_path_get_dirname (new_name); - int dir_fd = g_open (dir, O_RDONLY, 0); + int dir_fd = g_open (dir, O_RDONLY | O_CLOEXEC, 0); if (dir_fd >= 0) { diff --git a/glib/giounix.c b/glib/giounix.c index 067cecf9a..9d9492b28 100644 --- a/glib/giounix.c +++ b/glib/giounix.c @@ -44,6 +44,10 @@ #include #include +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "giochannel.h" #include "gerror.h" @@ -527,7 +531,7 @@ g_io_channel_new_file (const gchar *filename, create_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - fid = g_open (filename, flags, create_mode); + fid = g_open (filename, flags | O_CLOEXEC, create_mode); if (fid == -1) { int err = errno; diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c index fb65d55c5..9a4821bc5 100644 --- a/glib/gkeyfile.c +++ b/glib/gkeyfile.c @@ -53,6 +53,10 @@ #endif /* G_OS_WIN23 */ +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "gconvert.h" #include "gdataset.h" #include "gerror.h" @@ -761,7 +765,7 @@ find_file_in_data_dirs (const gchar *file, path = g_build_filename (data_dir, sub_dir, candidate_file, NULL); - fd = g_open (path, O_RDONLY, 0); + fd = g_open (path, O_RDONLY | O_CLOEXEC, 0); if (fd == -1) { @@ -917,7 +921,7 @@ g_key_file_load_from_file (GKeyFile *key_file, g_return_val_if_fail (key_file != NULL, FALSE); g_return_val_if_fail (file != NULL, FALSE); - fd = g_open (file, O_RDONLY, 0); + fd = g_open (file, O_RDONLY | O_CLOEXEC, 0); errsv = errno; if (fd == -1) diff --git a/glib/gmappedfile.c b/glib/gmappedfile.c index 16b38b358..4d7a89eb2 100644 --- a/glib/gmappedfile.c +++ b/glib/gmappedfile.c @@ -50,6 +50,10 @@ #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "gconvert.h" #include "gerror.h" #include "gfileutils.h" @@ -252,7 +256,7 @@ g_mapped_file_new (const gchar *filename, g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (!error || *error == NULL, NULL); - fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0); + fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY | O_CLOEXEC, 0); if (fd == -1) { int save_errno = errno; diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index 00a2c055f..aafaaf0ad 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -45,6 +45,10 @@ #include /* For open() and close() prototypes. */ #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + #include "gmoduleconf.h" #include "gstdio.h" @@ -388,7 +392,7 @@ parse_libtool_archive (const gchar* libtool_name) GTokenType token; GScanner *scanner; - int fd = g_open (libtool_name, O_RDONLY, 0); + int fd = g_open (libtool_name, O_RDONLY | O_CLOEXEC, 0); if (fd < 0) { gchar *display_libtool_name = g_filename_display_name (libtool_name); From 0e7bf99ec29bfae3f93227095f9ff3a10989eb3a Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sun, 19 Feb 2023 16:46:03 +0100 Subject: [PATCH 7/7] Use "e" mode flag in fopen () calls for race-free setting of the close-on-exec flag All Unix CRTs examined: glibc, musl, BSDs, Apple libc, Android bionic ignore unknown fopen () mode flags, so this flag can be added unconditionally for Unix builds. Only Windows CRT is intolerant of these, so the single case in g_dbus_address_connect () where the fopen () call is shared between Unix and Windows needs appropriate platform-specific handling. Skipped the call sites in libcharset and xdgmime copylibs. --- gio/gdbusaddress.c | 8 +++++++- gio/gunixmounts.c | 2 +- glib/gcharset.c | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index 0983ac49c..b73ff0d6e 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -53,6 +53,12 @@ #include #endif +#ifdef G_OS_WIN32 +#define FO_CLOEXEC "" +#else +#define FO_CLOEXEC "e" +#endif + #include "glibintl.h" /** @@ -711,7 +717,7 @@ g_dbus_address_connect (const gchar *address_entry, int errsv; /* be careful to read only 16 bytes - we also check that the file is only 16 bytes long */ - f = fopen (nonce_file, "rb"); + f = fopen (nonce_file, "rb" FO_CLOEXEC); errsv = errno; if (f == NULL) { diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index 9a02de3b5..4a2f0a248 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -3166,7 +3166,7 @@ _resolve_dev_root (void) /* see if device with similar major:minor as /dev/root is mention * in /etc/mtab (it usually is) */ - f = fopen ("/etc/mtab", "r"); + f = fopen ("/etc/mtab", "re"); if (f != NULL) { struct mntent *entp; diff --git a/glib/gcharset.c b/glib/gcharset.c index 31d46b659..82cd0a7b8 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -446,7 +446,7 @@ read_aliases (const gchar *file, FILE *fp; char buf[256]; - fp = fopen (file,"r"); + fp = fopen (file, "re"); if (!fp) return; while (fgets (buf, 256, fp))