From 8c166858ac0e87dfdb6c018b31ef5e291c8ec2e6 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Thu, 16 Aug 2018 22:08:19 +0200 Subject: [PATCH 1/3] all: Make opened FDs CLOEXEC Since all non-debug uses already use the _cairo_fopen() wrapper, make it use the "e" flag so that the underlying FD will be opened with O_CLOEXEC. --- src/cairo-misc.c | 2 +- src/cairoint.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cairo-misc.c b/src/cairo-misc.c index 6e63bc7..fe66f53 100644 --- a/src/cairo-misc.c +++ b/src/cairo-misc.c @@ -901,7 +901,7 @@ _cairo_strtod (const char *nptr, char **endptr) * NULL **/ cairo_status_t -_cairo_fopen (const char *filename, const char *mode, FILE **file_out) +(_cairo_fopen) (const char *filename, const char *mode, FILE **file_out) { FILE *result; #ifdef _WIN32 /* also defined on x86_64 */ diff --git a/src/cairoint.h b/src/cairoint.h index cfae18c..05dc098 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1935,6 +1935,10 @@ _cairo_observers_notify (cairo_list_t *observers, void *arg); cairo_private cairo_status_t _cairo_fopen (const char *filename, const char *mode, FILE **file_out); +#ifdef __GLIBC__ +#define _cairo_fopen(filename, mode, file_out) _cairo_fopen (filename, mode "e", file_out) +#endif + /* Avoid unnecessary PLT entries. */ slim_hidden_proto (cairo_clip_preserve); slim_hidden_proto (cairo_close_path); -- 2.9.4 From 3f3c1bc22f62ec7c5ac7596da55cc1a212425b45 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Thu, 16 Aug 2018 22:08:19 +0200 Subject: [PATCH 2/3] drm: Open device with O_CLOEXEC --- src/drm/cairo-drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drm/cairo-drm.c b/src/drm/cairo-drm.c index 661e181..c09bc56 100644 --- a/src/drm/cairo-drm.c +++ b/src/drm/cairo-drm.c @@ -234,7 +234,7 @@ cairo_drm_device_get (struct udev_device *device) if (path == NULL) path = "/dev/dri/card0"; /* XXX buggy udev? */ - fd = open (path, O_RDWR); + fd = open (path, O_RDWR | O_CLOEXEC); if (fd == -1) { /* XXX more likely to be a permissions issue... */ _cairo_error_throw (CAIRO_STATUS_FILE_NOT_FOUND); -- 2.9.4 From f0c54541950aa02123c723237c4c2249239a2652 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Thu, 16 Aug 2018 22:08:19 +0200 Subject: [PATCH 3/3] ps: Create tempfile with CLOEXEC Add _cairo_tmpfile() that wraps _cairo_win32_tmpfile on WIN32, and uses open(O_TMPFILE | O_CLOEXEC) if O_TMPFILE is available, and falls back to using tmpfile() and setting FD_CLOEXEC manually. --- src/cairo-misc.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/cairo-ps-surface.c | 2 +- src/cairoint.h | 3 +++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/cairo-misc.c b/src/cairo-misc.c index fe66f53..efdfdbe 100644 --- a/src/cairo-misc.c +++ b/src/cairo-misc.c @@ -44,6 +44,8 @@ #include #include #include +#include + #ifdef HAVE_XLOCALE_H #include #endif @@ -1009,6 +1011,44 @@ _cairo_win32_tmpfile (void) #endif /* _WIN32 */ +FILE * +_cairo_tmpfile (void) +{ +#ifndef _WIN32 + int fd; + FILE *file; + int flags; + +#ifdef O_TMPFILE + fd = open(P_tmpdir, + O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, + 0600); + if (errno == ENOENT) + fd = open("/tmp", + O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, + 0600); + if (fd != -1) + return fdopen (fd, "wb+"); + + /* Fallback */ +#endif /* O_TMPFILE */ + + file = tmpfile(); + if (file == NULL) + return NULL; + + /* Manually set CLOEXEC */ + fd = fileno(file); + flags = fcntl(fd, F_GETFD); + if (flags >= 0 && !(flags & FD_CLOEXEC)) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + + return file; +#else + return _cairo_win32_tmpfile(); +#endif /* !_WIN32 */ +} + typedef struct _cairo_intern_string { cairo_hash_entry_t hash_entry; int len; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 599eff4..484af67 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1153,7 +1153,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->final_stream = stream; - surface->tmpfile = tmpfile (); + surface->tmpfile = _cairo_tmpfile (); if (surface->tmpfile == NULL) { switch (errno) { case ENOMEM: diff --git a/src/cairoint.h b/src/cairoint.h index 05dc098..f398d54 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1939,6 +1939,9 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out); #define _cairo_fopen(filename, mode, file_out) _cairo_fopen (filename, mode "e", file_out) #endif +cairo_private FILE * +_cairo_tmpfile(void); + /* Avoid unnecessary PLT entries. */ slim_hidden_proto (cairo_clip_preserve); slim_hidden_proto (cairo_close_path); -- 2.9.4