From 49d8ff38e76e2ebcfc7fe6e3d4dca3f55f56d79a Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 27 Jul 2018 11:30:22 -0500 Subject: [PATCH] Add check_cloexec_fds debug command Add a debug command (to be executed manually via Alt+F2) to check that all of gnome-shell's file descriptors have the CLOEXEC flag set. This is important so that internal file descriptors do not get passed to apps when they are launched. It prints a warning message for every fd that does not have the flag set. fdwalk() is used from the standard library if available (it is not available in glibc), otherwise we use the same implementation as glib has internally. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132 --- config.h.meson | 3 ++ js/ui/runDialog.js | 6 ++- meson.build | 4 ++ src/shell-util.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ src/shell-util.h | 2 + 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/config.h.meson b/config.h.meson index 0dac17b94..141b2240a 100644 --- a/config.h.meson +++ b/config.h.meson @@ -27,3 +27,6 @@ /* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */ #mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS + +/* Define if fdwalk is available in libc */ +#mesondefine HAVE_FDWALK diff --git a/js/ui/runDialog.js b/js/ui/runDialog.js index 606a68396..b514f5b9f 100644 --- a/js/ui/runDialog.js +++ b/js/ui/runDialog.js @@ -62,7 +62,11 @@ var RunDialog = new Lang.Class({ 'rt': () => { Main.reloadThemeResource(); Main.loadTheme(); - } + }, + + 'check_cloexec_fds': () => { + Shell.util_check_cloexec_fds(); + }, }; diff --git a/meson.build b/meson.build index 5750b4fec..cafba27a8 100644 --- a/meson.build +++ b/meson.build @@ -173,6 +173,10 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY', cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY') ) +cdata.set('HAVE_FDWALK', + cc.has_function('fdwalk') +) + config_h = configure_file( input: 'config.h.meson', output: 'config.h', diff --git a/src/shell-util.c b/src/shell-util.c index 70b8c0611..411f5fad7 100644 --- a/src/shell-util.c +++ b/src/shell-util.c @@ -2,8 +2,15 @@ #include "config.h" +#include +#include +#include +#include #include #include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif #include #include @@ -514,3 +521,104 @@ shell_util_composite_capture_images (ClutterCapture *captures, return image; } + +#ifndef HAVE_FDWALK +static int +fdwalk (int (*cb)(void *data, int fd), void *data) +{ + gint open_max; + gint fd; + gint res = 0; + +#ifdef HAVE_SYS_RESOURCE_H + struct rlimit rl; +#endif + +#ifdef __linux__ + DIR *d; + + if ((d = opendir("/proc/self/fd"))) { + struct dirent *de; + + while ((de = readdir(d))) { + glong l; + gchar *e = NULL; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + l = strtol(de->d_name, &e, 10); + if (errno != 0 || !e || *e) + continue; + + fd = (gint) l; + + if ((glong) fd != l) + continue; + + if (fd == dirfd(d)) + continue; + + if ((res = cb (data, fd)) != 0) + break; + } + + closedir(d); + return res; + } + + /* If /proc is not mounted or not accessible we fall back to the old + * rlimit trick */ + +#endif + +#ifdef HAVE_SYS_RESOURCE_H + if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) + open_max = rl.rlim_max; + else +#endif + open_max = sysconf (_SC_OPEN_MAX); + + for (fd = 0; fd < open_max; fd++) + if ((res = cb (data, fd)) != 0) + break; + + return res; +} +#endif + +static int +check_cloexec(void *data, gint fd) +{ + int r; + + if (fd < 3) + return 0; + + r = fcntl (fd, F_GETFD); + if (r < 0) + return 0; + + if (!(r & FD_CLOEXEC)) + g_warning ("fd %d is not CLOEXEC", fd); + + return 0; +} + +/** + * shell_util_check_cloexec_fds: + * + * Walk over all open file descriptors. Check them for the FD_CLOEXEC flag. + * If this flag is not set, log the offending file descriptor number. + * + * It is important that gnome-shell's file descriptors are all marked CLOEXEC, + * so that the shell's open file descriptors are not passed to child processes + * that we launch. + */ +void +shell_util_check_cloexec_fds (void) +{ + fdwalk (check_cloexec, NULL); + g_info ("Open fd CLOEXEC check complete"); +} diff --git a/src/shell-util.h b/src/shell-util.h index 2218594c1..408b55f68 100644 --- a/src/shell-util.h +++ b/src/shell-util.h @@ -60,6 +60,8 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures int width, int height); +void shell_util_check_cloexec_fds (void); + G_END_DECLS #endif /* __SHELL_UTIL_H__ */