From 9d3c9265b30269c097d971a828f2e48111e2cd22 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Fri, 16 Oct 2026 18:41:17 +0200 Subject: [PATCH 1/2] ext/session: Open session files with O_CLOEXEC Set close-on-exec atomically when opening the session file instead of issuing a separate fcntl(F_SETFD) call afterwards. This saves one syscall per request and closes the window in which the descriptor could leak into a child process forked by another thread. The fcntl() fallback is kept for platforms without O_CLOEXEC. --- ext/session/mod_files.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 194e9433af24..121e64a68e88 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -175,7 +175,11 @@ static void ps_files_open(ps_files *data, /* const */ zend_string *key) data->last_key = zend_string_copy(key); /* O_NOFOLLOW to prevent us from following evil symlinks */ - data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY | O_NOFOLLOW, data->filemode); + data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY | O_NOFOLLOW +#ifdef O_CLOEXEC + | O_CLOEXEC +#endif + , data->filemode); if (data->fd != -1) { #ifndef PHP_WIN32 @@ -198,7 +202,7 @@ static void ps_files_open(ps_files *data, /* const */ zend_string *key) ret = flock(data->fd, LOCK_EX); } while (ret == -1 && errno == EINTR); -#ifdef F_SETFD +#if defined(F_SETFD) && !defined(O_CLOEXEC) # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif From d85d3561c4f5ee1399da575dd590b5dd849b9212 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Fri, 16 Oct 2026 21:01:40 +0200 Subject: [PATCH 2/2] ext/session: Build open() flags outside the macro call --- ext/session/mod_files.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 121e64a68e88..2e2d798431d4 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -175,11 +175,11 @@ static void ps_files_open(ps_files *data, /* const */ zend_string *key) data->last_key = zend_string_copy(key); /* O_NOFOLLOW to prevent us from following evil symlinks */ - data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY | O_NOFOLLOW + int flags = O_CREAT | O_RDWR | O_BINARY | O_NOFOLLOW; #ifdef O_CLOEXEC - | O_CLOEXEC + flags |= O_CLOEXEC; #endif - , data->filemode); + data->fd = VCWD_OPEN_MODE(buf, flags, data->filemode); if (data->fd != -1) { #ifndef PHP_WIN32