From b90c89766b1e13afc82c2aba2ebd5d54c83c067f Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 26 Nov 2021 08:10:37 +0100 Subject: [PATCH] Set CLOEXEC flag on sockets If SOCK_CLOEXEC exists, then set the flag on socket creation. Otherwise, use fcntl() (or SetHandleInformation() on Windows) to set the flag afterwards. This avoids the sockets to be inherited in child processes. Refs #2783 --- app/meson.build | 3 +++ app/src/util/net.c | 53 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/app/meson.build b/app/meson.build index 1561fdcd..1baf34fc 100644 --- a/app/meson.build +++ b/app/meson.build @@ -149,6 +149,9 @@ foreach f : check_functions endif endforeach +conf.set('HAVE_SOCK_CLOEXEC', host_machine.system() != 'windows' and + cc.has_header_symbol('sys/socket.h', 'SOCK_CLOEXEC')) + # the version, updated on release conf.set_quoted('SCRCPY_VERSION', meson.project_version()) diff --git a/app/src/util/net.c b/app/src/util/net.c index 8c51d12b..ec678d2e 100644 --- a/app/src/util/net.c +++ b/app/src/util/net.c @@ -1,6 +1,7 @@ #include "net.h" #include +#include #include #include @@ -10,17 +11,20 @@ # include typedef int socklen_t; typedef SOCKET sc_raw_socket; +# define SC_RAW_SOCKET_NONE INVALID_SOCKET #else # include # include # include # include # include +# include # define SOCKET_ERROR -1 typedef struct sockaddr_in SOCKADDR_IN; typedef struct sockaddr SOCKADDR; typedef struct in_addr IN_ADDR; typedef int sc_raw_socket; +# define SC_RAW_SOCKET_NONE -1 #endif bool @@ -79,6 +83,35 @@ unwrap(sc_socket socket) { #endif } +static inline bool +sc_raw_socket_close(sc_raw_socket raw_sock) { +#ifndef _WIN32 + return !close(raw_sock); +#else + return !closesocket(raw_sock); +#endif +} + +#ifndef HAVE_SOCK_CLOEXEC +// If SOCK_CLOEXEC does not exist, the flag must be set manually once the +// socket is created +static bool +set_cloexec_flag(sc_raw_socket raw_sock) { +#ifndef _WIN32 + if (fcntl(raw_sock, F_SETFD, FD_CLOEXEC) == -1) { + perror("fcntl F_SETFD"); + return false; + } +#else + if (!SetHandleInformation((HANDLE) raw_sock, HANDLE_FLAG_INHERIT, 0)) { + LOGE("SetHandleInformation socket failed"); + return false; + } +#endif + return true; +} +#endif + static void net_perror(const char *s) { #ifdef _WIN32 @@ -97,7 +130,16 @@ net_perror(const char *s) { sc_socket net_socket(void) { +#ifdef HAVE_SOCK_CLOEXEC + sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); +#else sc_raw_socket raw_sock = socket(AF_INET, SOCK_STREAM, 0); + if (raw_sock != SC_RAW_SOCKET_NONE && !set_cloexec_flag(raw_sock)) { + sc_raw_socket_close(raw_sock); + return SC_SOCKET_NONE; + } +#endif + sc_socket sock = wrap(raw_sock); if (sock == SC_SOCKET_NONE) { net_perror("socket"); @@ -156,8 +198,18 @@ net_accept(sc_socket server_socket) { SOCKADDR_IN csin; socklen_t sinsize = sizeof(csin); + +#ifdef HAVE_SOCK_CLOEXEC + sc_raw_socket raw_sock = + accept4(raw_server_socket, (SOCKADDR *) &csin, &sinsize, SOCK_CLOEXEC); +#else sc_raw_socket raw_sock = accept(raw_server_socket, (SOCKADDR *) &csin, &sinsize); + if (raw_sock != SC_RAW_SOCKET_NONE && !set_cloexec_flag(raw_sock)) { + sc_raw_socket_close(raw_sock); + return SC_SOCKET_NONE; + } +#endif return wrap(raw_sock); } @@ -211,7 +263,6 @@ net_interrupt(sc_socket socket) { #endif } -#include bool net_close(sc_socket socket) { sc_raw_socket raw_sock = unwrap(socket);