diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 0e58d4f11b0..9f52a4cb5af 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -219,6 +219,7 @@ DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER ECCSI_ORDER_MORE_BITS_THAN_PRIME ECC_DUMP_OID ECDHE_SIZE +EFD_CLOEXEC ENABLED_BSDKM_REGISTER ENABLE_SECURE_SOCKETS_LOGS ESP32 @@ -234,6 +235,7 @@ ETHERNET_AVAILABLE ETHERNET_H EV_TRIGGER EXTERNAL_LOADER_APP +FD_CLOEXEC FIPS_OPTEST_FULL_RUN_AT_MODULE_INIT FORCE_FAILURE_GETRANDOM FP_ECC_CONTROL @@ -317,6 +319,7 @@ IGNORE_NETSCAPE_CERT_TYPE INCLUDE_uxTaskGetStackHighWaterMark INTEGRITY INTIMEVER +IN_CLOEXEC IOTSAFE_NO_GETDATA IOTSAFE_SIG_8BIT_LENGTH KCAPI_USE_XMALLOC @@ -476,7 +479,9 @@ OPENSSL_NO_PK OS_WINDOWS OTHERBOARD OTHER_BOARD +O_CLOEXEC PEER_INFO +PERF_FLAG_FD_CLOEXEC PKA_ECC_SCALAR_MUL_IN_B_COEFF PLATFORMIO PLUTON_CRYPTO_ECC @@ -519,6 +524,7 @@ SL_SE_KEY_TYPE_ECC_X25519 SL_SE_KEY_TYPE_ECC_X448 SL_SE_PRF_HMAC_SHA1 SNIFFER_SINGLE_SESSION_CACHE +SOCK_CLOEXEC SOFTDEVICE_PRESENT SO_NOSIGPIPE SO_REUSEPORT @@ -1116,6 +1122,7 @@ __sun __svr4__ __thumb__ __ti__ +__unix__ __x86_64__ __xtensa__ byte diff --git a/src/crl.c b/src/crl.c index 62c207de526..540a6d23acf 100644 --- a/src/crl.c +++ b/src/crl.c @@ -1659,6 +1659,7 @@ static int SwapLists(WOLFSSL_CRL* crl) #include #include #include +#include #ifdef __MACH__ #define XEVENT_MODE O_EVTONLY @@ -1667,6 +1668,7 @@ static int SwapLists(WOLFSSL_CRL* crl) #endif + /* we need a unique kqueue user filter fd for crl in case user is doing custom * events too */ #ifndef CRL_CUSTOM_FD @@ -1710,6 +1712,7 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg) SignalSetup(crl, MONITOR_SETUP_E); return NULL; } + wc_set_cloexec(crl->mfd); /* listen for custom shutdown event */ EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL); @@ -1724,7 +1727,7 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg) fDER = -1; if (crl->monitors[0].path) { - fPEM = open(crl->monitors[0].path, XEVENT_MODE); + fPEM = wc_open_cloexec(crl->monitors[0].path, XEVENT_MODE); if (fPEM == -1) { WOLFSSL_MSG("PEM event dir open failed"); SignalSetup(crl, MONITOR_SETUP_E); @@ -1734,7 +1737,7 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg) } if (crl->monitors[1].path) { - fDER = open(crl->monitors[1].path, XEVENT_MODE); + fDER = wc_open_cloexec(crl->monitors[1].path, XEVENT_MODE); if (fDER == -1) { WOLFSSL_MSG("DER event dir open failed"); if (fPEM != -1) @@ -1801,6 +1804,13 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg) #include #include #include +#include +#include + +/* Fall back to no-op if EFD_CLOEXEC is unavailable. */ +#ifndef EFD_CLOEXEC + #define EFD_CLOEXEC 0 +#endif #ifndef max @@ -1836,14 +1846,29 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg) WOLFSSL_ENTER("DoMonitor"); - crl->mfd = eventfd(0, 0); /* our custom shutdown event */ + crl->mfd = eventfd(0, EFD_CLOEXEC); /* our custom shutdown event */ +#ifdef FD_CLOEXEC + if (crl->mfd < 0 && errno == EINVAL) { + crl->mfd = eventfd(0, 0); + wc_set_cloexec(crl->mfd); + } +#endif if (crl->mfd < 0) { WOLFSSL_MSG("eventfd failed"); SignalSetup(crl, MONITOR_SETUP_E); return NULL; } +#ifdef IN_CLOEXEC + notifyFd = inotify_init1(IN_CLOEXEC); + if (notifyFd < 0 && (errno == ENOSYS || errno == EINVAL)) { + notifyFd = inotify_init(); + wc_set_cloexec(notifyFd); + } +#else notifyFd = inotify_init(); + wc_set_cloexec(notifyFd); +#endif if (notifyFd < 0) { WOLFSSL_MSG("inotify failed"); (void)close(crl->mfd); diff --git a/src/ssl.c b/src/ssl.c index 58cd6701c02..c36671b51d0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -19601,7 +19601,7 @@ int wolfSSL_RAND_egd(const char* nm) return WOLFSSL_FATAL_ERROR; } - fd = socket(AF_UNIX, SOCK_STREAM, 0); + fd = wc_socket_cloexec(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { WOLFSSL_MSG("Error creating socket"); WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/src/wolfio.c b/src/wolfio.c index c6ffe7da11b..fe891da2349 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -42,6 +42,7 @@ #include #include + #ifdef NUCLEUS_PLUS_2_3 /* Holds last Nucleus networking error number */ int Nucleus_Net_Errno; @@ -1494,7 +1495,7 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) } #endif - *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); + *sockfd = (SOCKET_T)wc_socket_cloexec(addr.ss_family, SOCK_STREAM, 0); #ifdef USE_WINDOWS_API if (*sockfd == SOCKET_INVALID) #else @@ -1572,12 +1573,12 @@ int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port) sin->sin6_family = AF_INET6; sin->sin6_addr = in6addr_any; sin->sin6_port = XHTONS(port); - *sockfd = (SOCKET_T)socket(AF_INET6, SOCK_STREAM, 0); + *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET6, SOCK_STREAM, 0); #else sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; sin->sin_port = XHTONS(port); - *sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM, 0); + *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET, SOCK_STREAM, 0); #endif #ifdef USE_WINDOWS_API @@ -1623,7 +1624,7 @@ int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port) #ifdef HAVE_SOCKADDR int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len) { - return (int)accept(sockfd, peer_addr, peer_len); + return wc_accept_cloexec((int)sockfd, peer_addr, peer_len); } #endif /* HAVE_SOCKADDR */ diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 5d8e8efb898..18cedaeace6 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1574,16 +1574,30 @@ static const char* bench_result_words3[][5] = { #include #include #include + #include + #include + + #ifndef PERF_FLAG_FD_CLOEXEC + #define PERF_FLAG_FD_CLOEXEC (1UL << 3) + #endif static THREAD_LS_T word64 begin_cycles; static THREAD_LS_T word64 total_cycles; static THREAD_LS_T int cycles = -1; static THREAD_LS_T struct perf_event_attr atr; + /* Try with PERF_FLAG_FD_CLOEXEC first; on older kernels (< 3.14) this + * fails with EINVAL, so fall back to flags=0 and set FD_CLOEXEC via + * fcntl() as a best-effort. */ #define INIT_CYCLE_COUNTER do { \ atr.type = PERF_TYPE_HARDWARE; \ atr.config = PERF_COUNT_HW_CPU_CYCLES; \ - cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, 0); \ + cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, \ + PERF_FLAG_FD_CLOEXEC); \ + if (cycles < 0 && errno == EINVAL) { \ + cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, 0); \ + wc_set_cloexec(cycles); \ + } \ } while (0); #define BEGIN_CYCLES read(cycles, &begin_cycles, sizeof(begin_cycles)); diff --git a/wolfcrypt/src/port/af_alg/afalg_hash.c b/wolfcrypt/src/port/af_alg/afalg_hash.c index 429bb7d04b4..c0e945b5d23 100644 --- a/wolfcrypt/src/port/af_alg/afalg_hash.c +++ b/wolfcrypt/src/port/af_alg/afalg_hash.c @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if defined(__linux__) && !defined(_GNU_SOURCE) + #define _GNU_SOURCE 1 +#endif + #include #if defined(WOLFSSL_AFALG_HASH) || (defined(WOLFSSL_AFALG_XILINX_SHA3) \ @@ -26,6 +30,8 @@ #include #include +#include +#include static const char WC_TYPE_HASH[] = "hash"; @@ -223,8 +229,8 @@ static int AfalgHashCopy(wolfssl_AFALG_Hash* src, wolfssl_AFALG_Hash* dst) } #endif - dst->rdFd = accept(src->rdFd, NULL, 0); - dst->alFd = accept(src->alFd, NULL, 0); + dst->rdFd = wc_accept_cloexec(src->rdFd, NULL, NULL); + dst->alFd = wc_accept_cloexec(src->alFd, NULL, NULL); if (dst->rdFd == WC_SOCK_NOTSET || dst->alFd == WC_SOCK_NOTSET) { AfalgHashFree(dst); diff --git a/wolfcrypt/src/port/af_alg/wc_afalg.c b/wolfcrypt/src/port/af_alg/wc_afalg.c index b5a1f878ad5..cda5e043db8 100644 --- a/wolfcrypt/src/port/af_alg/wc_afalg.c +++ b/wolfcrypt/src/port/af_alg/wc_afalg.c @@ -19,12 +19,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if defined(__linux__) && !defined(_GNU_SOURCE) + #define _GNU_SOURCE 1 +#endif + #include #if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX) #include #include +#include +#include +#include + /* Sets the type of socket address to use */ @@ -56,7 +64,7 @@ int wc_Afalg_Accept(struct sockaddr_alg* in, int inSz, int sock) return WC_AFALG_SOCK_E; } - return accept(sock, NULL, 0); + return wc_accept_cloexec(sock, NULL, NULL); } @@ -66,7 +74,8 @@ int wc_Afalg_Socket(void) { int sock; - if ((sock = socket(AF_ALG, SOCK_SEQPACKET, 0)) < 0) { + sock = wc_socket_cloexec(AF_ALG, SOCK_SEQPACKET, 0); + if (sock < 0) { WOLFSSL_MSG("Failed to get AF_ALG socket"); return WC_AFALG_SOCK_E; } diff --git a/wolfcrypt/src/port/caam/wolfcaam_qnx.c b/wolfcrypt/src/port/caam/wolfcaam_qnx.c index 71d5cbfb61e..eab9cdd5725 100644 --- a/wolfcrypt/src/port/caam/wolfcaam_qnx.c +++ b/wolfcrypt/src/port/caam/wolfcaam_qnx.c @@ -34,7 +34,6 @@ #include #include -#include /* for devctl use */ int caamFd = -1; @@ -48,7 +47,7 @@ int wc_CAAMInitInterface() return -1; } - caamFd = open("/dev/wolfCrypt", O_RDWR); + caamFd = wc_open_cloexec("/dev/wolfCrypt", O_RDWR); if (caamFd < 0) { WOLFSSL_MSG("Could not open /dev/wolfCrypt"); return -1; diff --git a/wolfcrypt/src/port/devcrypto/wc_devcrypto.c b/wolfcrypt/src/port/devcrypto/wc_devcrypto.c index 21fb9808000..9a939157b4f 100644 --- a/wolfcrypt/src/port/devcrypto/wc_devcrypto.c +++ b/wolfcrypt/src/port/devcrypto/wc_devcrypto.c @@ -26,11 +26,13 @@ static volatile int fd; #include +#include int wc_DevCryptoInit(void) { /* create descriptor */ - if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) { + fd = wc_open_cloexec("/dev/crypto", O_RDWR); + if (fd < 0) { WOLFSSL_MSG("Error opening /dev/crypto is cryptodev module loaded?"); return WC_DEVCRYPTO_E; } diff --git a/wolfcrypt/src/port/intel/quickassist_mem.c b/wolfcrypt/src/port/intel/quickassist_mem.c index 63d01d9f325..7d44572a930 100644 --- a/wolfcrypt/src/port/intel/quickassist_mem.c +++ b/wolfcrypt/src/port/intel/quickassist_mem.c @@ -57,6 +57,8 @@ #include #include #include +#include + #ifdef SAL_IOMMU_CODE #include @@ -714,7 +716,7 @@ CpaStatus qaeMemInit(void) { if (g_qaeMemFd < 0) { #ifndef QAT_V2 - g_qaeMemFd = open(QAE_MEM, O_RDWR); + g_qaeMemFd = wc_open_cloexec(QAE_MEM, O_RDWR); if (g_qaeMemFd < 0) { printf("unable to open %s %d\n", QAE_MEM, g_qaeMemFd); return CPA_STATUS_FAIL; diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 9fa318c7608..430edda1d93 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -204,8 +204,8 @@ This library contains implementation for the random number generator. #elif defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD) #include "wolfssl/wolfcrypt/port/maxim/max3266x.h" #else + #include #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM) - #include #include #endif /* include headers that may be needed to get good seed */ @@ -3829,7 +3829,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) if (!os->seedFdOpen) { #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */ - os->fd = open("/dev/urandom", O_RDONLY); + os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY); #if defined(DEBUG_WOLFSSL) WOLFSSL_MSG("opened /dev/urandom."); #endif /* DEBUG_WOLFSSL */ @@ -3837,7 +3837,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #endif /* NO_DEV_URANDOM */ { /* may still have /dev/random */ - os->fd = open("/dev/random", O_RDONLY); + os->fd = wc_open_cloexec("/dev/random", O_RDONLY); #if defined(DEBUG_WOLFSSL) WOLFSSL_MSG("opened /dev/random."); #endif /* DEBUG_WOLFSSL */ @@ -3855,7 +3855,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */ #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */ - os->fd = open("/dev/urandom", O_RDONLY); + os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY); #if defined(DEBUG_WOLFSSL) WOLFSSL_MSG("opened /dev/urandom."); #endif /* DEBUG_WOLFSSL */ @@ -3863,7 +3863,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #endif /* !NO_DEV_URANDOM */ { /* may still have /dev/random */ - os->fd = open("/dev/random", O_RDONLY); + os->fd = wc_open_cloexec("/dev/random", O_RDONLY); #if defined(DEBUG_WOLFSSL) WOLFSSL_MSG("opened /dev/random."); #endif /* DEBUG_WOLFSSL */ @@ -3944,7 +3944,7 @@ int wc_hwrng_generate_block(byte *output, word32 sz) { int fd; int ret = 0; - fd = open("/dev/hwrng", O_RDONLY); + fd = wc_open_cloexec("/dev/hwrng", O_RDONLY); if (fd == -1) return OPEN_RAN_E; while(sz) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 92283abdfe7..4d80ef8a07d 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -19,6 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#if (defined(__linux__) || defined(__ANDROID__)) && \ + !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) && \ + !defined(_GNU_SOURCE) + #define _GNU_SOURCE 1 +#endif + /* wolfCrypt Porting Build Options: @@ -5130,6 +5136,76 @@ char* wolfSSL_strnstr(const char* s1, const char* s2, unsigned int n) #endif /* not SINGLE_THREADED */ +#if (defined(__unix__) || defined(__APPLE__)) && \ + !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) + +#include +#include +#include + +#ifndef O_CLOEXEC + #define O_CLOEXEC 0 +#endif +#ifndef SOCK_CLOEXEC + #define SOCK_CLOEXEC 0 +#endif + +void wc_set_cloexec(int fd) +{ +#ifdef FD_CLOEXEC + int fdFlags; + if (fd < 0) + return; + fdFlags = fcntl(fd, F_GETFD); + if (fdFlags >= 0) + (void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC); +#else + (void)fd; +#endif +} + +int wc_open_cloexec(const char* path, int flags) +{ + int fd = open(path, flags | O_CLOEXEC); +#ifdef FD_CLOEXEC + if (fd < 0 && errno == EINVAL) { + fd = open(path, flags); + wc_set_cloexec(fd); + } +#endif + return fd; +} + +int wc_socket_cloexec(int domain, int type, int protocol) +{ + int fd = socket(domain, type | SOCK_CLOEXEC, protocol); +#ifdef FD_CLOEXEC + if (fd < 0 && errno == EINVAL) { + fd = socket(domain, type, protocol); + wc_set_cloexec(fd); + } +#endif + return fd; +} + +int wc_accept_cloexec(int sockfd, void* addr, void* addrlen) +{ + int fd; +#if defined(__linux__) || defined(__ANDROID__) + fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen, + SOCK_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != ENOSYS && errno != EINVAL) + return fd; +#endif + fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen); + wc_set_cloexec(fd); + return fd; +} + +#endif /* (__unix__ || __APPLE__) && !WOLFSSL_LINUXKM && !WOLFSSL_ZEPHYR */ + #if defined(WOLFSSL_LINUXKM) && defined(CONFIG_ARM64) && \ defined(WC_SYM_RELOC_TABLES) #ifndef CONFIG_ARCH_TEGRA diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index ade6b6c1da8..799066884a7 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -1860,6 +1860,24 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #define WC_GENERATE_SEED_DEFAULT wc_GenerateSeed #endif +#if (defined(__unix__) || defined(__APPLE__)) && \ + !defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_ZEPHYR) + WOLFSSL_LOCAL void wc_set_cloexec(int fd); + WOLFSSL_LOCAL int wc_open_cloexec(const char* path, int flags); + WOLFSSL_LOCAL int wc_socket_cloexec(int domain, int type, int protocol); + WOLFSSL_LOCAL int wc_accept_cloexec(int sockfd, void* addr, void* addrlen); +#else + /* Platforms without POSIX close-on-exec semantics (Windows, OS/2 OW, + * Linux kernel module, Zephyr, etc.): pass through to plain syscalls + * where the underlying headers are available in the caller. */ + #define wc_set_cloexec(fd) ((void)(fd)) + #define wc_open_cloexec(path, flags) open((path), (flags)) + #define wc_socket_cloexec(domain, type, protocol) \ + socket((domain), (type), (protocol)) + #define wc_accept_cloexec(sockfd, addr, addrlen) \ + accept((sockfd), (addr), (addrlen)) +#endif + #ifdef __cplusplus } /* extern "C" */ #endif