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 <https://github.com/Genymobile/scrcpy/pull/2783>
This commit is contained in:
parent
904f0ae61e
commit
b90c89766b
2 changed files with 55 additions and 1 deletions
|
@ -149,6 +149,9 @@ foreach f : check_functions
|
||||||
endif
|
endif
|
||||||
endforeach
|
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
|
# the version, updated on release
|
||||||
conf.set_quoted('SCRCPY_VERSION', meson.project_version())
|
conf.set_quoted('SCRCPY_VERSION', meson.project_version())
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
|
|
||||||
|
@ -10,17 +11,20 @@
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
typedef SOCKET sc_raw_socket;
|
typedef SOCKET sc_raw_socket;
|
||||||
|
# define SC_RAW_SOCKET_NONE INVALID_SOCKET
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
# include <fcntl.h>
|
||||||
# define SOCKET_ERROR -1
|
# define SOCKET_ERROR -1
|
||||||
typedef struct sockaddr_in SOCKADDR_IN;
|
typedef struct sockaddr_in SOCKADDR_IN;
|
||||||
typedef struct sockaddr SOCKADDR;
|
typedef struct sockaddr SOCKADDR;
|
||||||
typedef struct in_addr IN_ADDR;
|
typedef struct in_addr IN_ADDR;
|
||||||
typedef int sc_raw_socket;
|
typedef int sc_raw_socket;
|
||||||
|
# define SC_RAW_SOCKET_NONE -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -79,6 +83,35 @@ unwrap(sc_socket socket) {
|
||||||
#endif
|
#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
|
static void
|
||||||
net_perror(const char *s) {
|
net_perror(const char *s) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -97,7 +130,16 @@ net_perror(const char *s) {
|
||||||
|
|
||||||
sc_socket
|
sc_socket
|
||||||
net_socket(void) {
|
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);
|
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);
|
sc_socket sock = wrap(raw_sock);
|
||||||
if (sock == SC_SOCKET_NONE) {
|
if (sock == SC_SOCKET_NONE) {
|
||||||
net_perror("socket");
|
net_perror("socket");
|
||||||
|
@ -156,8 +198,18 @@ net_accept(sc_socket server_socket) {
|
||||||
|
|
||||||
SOCKADDR_IN csin;
|
SOCKADDR_IN csin;
|
||||||
socklen_t sinsize = sizeof(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 =
|
sc_raw_socket raw_sock =
|
||||||
accept(raw_server_socket, (SOCKADDR *) &csin, &sinsize);
|
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);
|
return wrap(raw_sock);
|
||||||
}
|
}
|
||||||
|
@ -211,7 +263,6 @@ net_interrupt(sc_socket socket) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
bool
|
bool
|
||||||
net_close(sc_socket socket) {
|
net_close(sc_socket socket) {
|
||||||
sc_raw_socket raw_sock = unwrap(socket);
|
sc_raw_socket raw_sock = unwrap(socket);
|
||||||
|
|
Loading…
Reference in a new issue