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
This commit is contained in:
parent
4b522a02c3
commit
49d8ff38e7
@ -27,3 +27,6 @@
|
|||||||
|
|
||||||
/* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */
|
/* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */
|
||||||
#mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
|
#mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
|
||||||
|
|
||||||
|
/* Define if fdwalk is available in libc */
|
||||||
|
#mesondefine HAVE_FDWALK
|
||||||
|
@ -62,7 +62,11 @@ var RunDialog = new Lang.Class({
|
|||||||
'rt': () => {
|
'rt': () => {
|
||||||
Main.reloadThemeResource();
|
Main.reloadThemeResource();
|
||||||
Main.loadTheme();
|
Main.loadTheme();
|
||||||
}
|
},
|
||||||
|
|
||||||
|
'check_cloexec_fds': () => {
|
||||||
|
Shell.util_check_cloexec_fds();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,6 +173,10 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
|
|||||||
cc.has_header_symbol('langinfo.h', '_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(
|
config_h = configure_file(
|
||||||
input: 'config.h.meson',
|
input: 'config.h.meson',
|
||||||
output: 'config.h',
|
output: 'config.h',
|
||||||
|
108
src/shell-util.c
108
src/shell-util.c
@ -2,8 +2,15 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
@ -514,3 +521,104 @@ shell_util_composite_capture_images (ClutterCapture *captures,
|
|||||||
|
|
||||||
return image;
|
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");
|
||||||
|
}
|
||||||
|
@ -60,6 +60,8 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
|
|||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
|
void shell_util_check_cloexec_fds (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __SHELL_UTIL_H__ */
|
#endif /* __SHELL_UTIL_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user