Skip to content

Commit 72e3af9

Browse files
committed
Use O_CLOEXEC to avoid race conditions
1 parent 178e10e commit 72e3af9

11 files changed

Lines changed: 342 additions & 22 deletions

File tree

.wolfssl_known_macro_extras

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER
219219
ECCSI_ORDER_MORE_BITS_THAN_PRIME
220220
ECC_DUMP_OID
221221
ECDHE_SIZE
222+
EFD_CLOEXEC
222223
ENABLED_BSDKM_REGISTER
223224
ENABLE_SECURE_SOCKETS_LOGS
224225
ESP32
@@ -234,6 +235,7 @@ ETHERNET_AVAILABLE
234235
ETHERNET_H
235236
EV_TRIGGER
236237
EXTERNAL_LOADER_APP
238+
FD_CLOEXEC
237239
FIPS_OPTEST_FULL_RUN_AT_MODULE_INIT
238240
FORCE_FAILURE_GETRANDOM
239241
FP_ECC_CONTROL
@@ -315,6 +317,7 @@ ID_TRNG
315317
IGNORE_KEY_EXTENSIONS
316318
IGNORE_NETSCAPE_CERT_TYPE
317319
INCLUDE_uxTaskGetStackHighWaterMark
320+
IN_CLOEXEC
318321
INTEGRITY
319322
INTIMEVER
320323
IOTSAFE_NO_GETDATA
@@ -468,6 +471,7 @@ NO_WOLFSSL_XILINX_TAG_MALLOC
468471
NRF52
469472
NRF52_SERIES
470473
NRF_ERROR_MODULE_ALREADY_INITIALIZED
474+
O_CLOEXEC
471475
OLD_HELLO_ALLOWED
472476
OPENSSL_EXTRA_BSD
473477
OPENSSL_EXTRA_NO_ASN1
@@ -477,6 +481,7 @@ OS_WINDOWS
477481
OTHERBOARD
478482
OTHER_BOARD
479483
PEER_INFO
484+
PERF_FLAG_FD_CLOEXEC
480485
PKA_ECC_SCALAR_MUL_IN_B_COEFF
481486
PLATFORMIO
482487
PLUTON_CRYPTO_ECC
@@ -519,6 +524,7 @@ SL_SE_KEY_TYPE_ECC_X25519
519524
SL_SE_KEY_TYPE_ECC_X448
520525
SL_SE_PRF_HMAC_SHA1
521526
SNIFFER_SINGLE_SESSION_CACHE
527+
SOCK_CLOEXEC
522528
SOFTDEVICE_PRESENT
523529
SO_NOSIGPIPE
524530
SO_REUSEPORT

src/crl.c

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,13 +1659,19 @@ static int SwapLists(WOLFSSL_CRL* crl)
16591659
#include <sys/time.h>
16601660
#include <fcntl.h>
16611661
#include <unistd.h>
1662+
#include <errno.h>
16621663

16631664
#ifdef __MACH__
16641665
#define XEVENT_MODE O_EVTONLY
16651666
#elif defined(__FreeBSD__)
16661667
#define XEVENT_MODE O_RDONLY
16671668
#endif
16681669

1670+
/* Fall back to no-op if O_CLOEXEC is unavailable on this platform. */
1671+
#ifndef O_CLOEXEC
1672+
#define O_CLOEXEC 0
1673+
#endif
1674+
16691675

16701676
/* we need a unique kqueue user filter fd for crl in case user is doing custom
16711677
* events too */
@@ -1710,6 +1716,13 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
17101716
SignalSetup(crl, MONITOR_SETUP_E);
17111717
return NULL;
17121718
}
1719+
#ifdef FD_CLOEXEC
1720+
{
1721+
int fdFlags = fcntl(crl->mfd, F_GETFD);
1722+
if (fdFlags >= 0)
1723+
(void)fcntl(crl->mfd, F_SETFD, fdFlags | FD_CLOEXEC);
1724+
}
1725+
#endif
17131726

17141727
/* listen for custom shutdown event */
17151728
EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
@@ -1724,7 +1737,17 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
17241737
fDER = -1;
17251738

17261739
if (crl->monitors[0].path) {
1727-
fPEM = open(crl->monitors[0].path, XEVENT_MODE);
1740+
fPEM = open(crl->monitors[0].path, XEVENT_MODE | O_CLOEXEC);
1741+
#ifdef FD_CLOEXEC
1742+
if (fPEM == -1 && errno == EINVAL) {
1743+
fPEM = open(crl->monitors[0].path, XEVENT_MODE);
1744+
if (fPEM >= 0) {
1745+
int fdFlags = fcntl(fPEM, F_GETFD);
1746+
if (fdFlags >= 0)
1747+
(void)fcntl(fPEM, F_SETFD, fdFlags | FD_CLOEXEC);
1748+
}
1749+
}
1750+
#endif
17281751
if (fPEM == -1) {
17291752
WOLFSSL_MSG("PEM event dir open failed");
17301753
SignalSetup(crl, MONITOR_SETUP_E);
@@ -1734,7 +1757,17 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
17341757
}
17351758

17361759
if (crl->monitors[1].path) {
1737-
fDER = open(crl->monitors[1].path, XEVENT_MODE);
1760+
fDER = open(crl->monitors[1].path, XEVENT_MODE | O_CLOEXEC);
1761+
#ifdef FD_CLOEXEC
1762+
if (fDER == -1 && errno == EINVAL) {
1763+
fDER = open(crl->monitors[1].path, XEVENT_MODE);
1764+
if (fDER >= 0) {
1765+
int fdFlags = fcntl(fDER, F_GETFD);
1766+
if (fdFlags >= 0)
1767+
(void)fcntl(fDER, F_SETFD, fdFlags | FD_CLOEXEC);
1768+
}
1769+
}
1770+
#endif
17381771
if (fDER == -1) {
17391772
WOLFSSL_MSG("DER event dir open failed");
17401773
if (fPEM != -1)
@@ -1801,6 +1834,13 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
18011834
#include <sys/inotify.h>
18021835
#include <sys/eventfd.h>
18031836
#include <unistd.h>
1837+
#include <fcntl.h>
1838+
#include <errno.h>
1839+
1840+
/* Fall back to no-op if EFD_CLOEXEC is unavailable. */
1841+
#ifndef EFD_CLOEXEC
1842+
#define EFD_CLOEXEC 0
1843+
#endif
18041844

18051845

18061846
#ifndef max
@@ -1836,14 +1876,45 @@ static THREAD_RETURN WOLFSSL_THREAD DoMonitor(void* arg)
18361876

18371877
WOLFSSL_ENTER("DoMonitor");
18381878

1839-
crl->mfd = eventfd(0, 0); /* our custom shutdown event */
1879+
crl->mfd = eventfd(0, EFD_CLOEXEC); /* our custom shutdown event */
1880+
#ifdef FD_CLOEXEC
1881+
if (crl->mfd < 0 && errno == EINVAL) {
1882+
crl->mfd = eventfd(0, 0);
1883+
if (crl->mfd >= 0) {
1884+
int fdFlags = fcntl(crl->mfd, F_GETFD);
1885+
if (fdFlags >= 0)
1886+
(void)fcntl(crl->mfd, F_SETFD, fdFlags | FD_CLOEXEC);
1887+
}
1888+
}
1889+
#endif
18401890
if (crl->mfd < 0) {
18411891
WOLFSSL_MSG("eventfd failed");
18421892
SignalSetup(crl, MONITOR_SETUP_E);
18431893
return NULL;
18441894
}
18451895

1896+
#ifdef IN_CLOEXEC
1897+
notifyFd = inotify_init1(IN_CLOEXEC);
1898+
if (notifyFd < 0 && (errno == ENOSYS || errno == EINVAL)) {
1899+
notifyFd = inotify_init();
1900+
#ifdef FD_CLOEXEC
1901+
if (notifyFd >= 0) {
1902+
int fdFlags = fcntl(notifyFd, F_GETFD);
1903+
if (fdFlags >= 0)
1904+
(void)fcntl(notifyFd, F_SETFD, fdFlags | FD_CLOEXEC);
1905+
}
1906+
#endif
1907+
}
1908+
#else
18461909
notifyFd = inotify_init();
1910+
#ifdef FD_CLOEXEC
1911+
if (notifyFd >= 0) {
1912+
int fdFlags = fcntl(notifyFd, F_GETFD);
1913+
if (fdFlags >= 0)
1914+
(void)fcntl(notifyFd, F_SETFD, fdFlags | FD_CLOEXEC);
1915+
}
1916+
#endif
1917+
#endif
18471918
if (notifyFd < 0) {
18481919
WOLFSSL_MSG("inotify failed");
18491920
(void)close(crl->mfd);

src/ssl.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19568,6 +19568,9 @@ int wolfSSL_RAND_write_file(const char* fname)
1956819568
defined(HAVE_SYS_UN_H)
1956919569
#define WOLFSSL_EGD_NBLOCK 0x01
1957019570
#include <sys/un.h>
19571+
#ifndef SOCK_CLOEXEC
19572+
#define SOCK_CLOEXEC 0
19573+
#endif
1957119574
#endif
1957219575

1957319576
/* This collects entropy from the path nm and seeds the global PRNG with it.
@@ -19601,7 +19604,17 @@ int wolfSSL_RAND_egd(const char* nm)
1960119604
return WOLFSSL_FATAL_ERROR;
1960219605
}
1960319606

19604-
fd = socket(AF_UNIX, SOCK_STREAM, 0);
19607+
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
19608+
#ifdef FD_CLOEXEC
19609+
if (fd < 0 && errno == EINVAL) {
19610+
fd = socket(AF_UNIX, SOCK_STREAM, 0);
19611+
if (fd >= 0) {
19612+
int fdFlags = fcntl(fd, F_GETFD);
19613+
if (fdFlags >= 0)
19614+
(void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC);
19615+
}
19616+
}
19617+
#endif
1960519618
if (fd < 0) {
1960619619
WOLFSSL_MSG("Error creating socket");
1960719620
WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);

src/wolfio.c

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
#define WOLFSSL_STRERROR_BUFFER_SIZE 256
2525
#endif
2626

27+
/* Enable GNU extensions for accept4() on Linux/glibc. Must be defined
28+
* before any system headers are included. Excluded for Zephyr and other
29+
* embedded RTOSes whose libc layers conflict with glibc-style definitions
30+
* (e.g., Zephyr's socket_select.h vs. glibc's fd_set). */
31+
#if (defined(__linux__) || defined(__ANDROID__)) && \
32+
!defined(WOLFSSL_ZEPHYR) && !defined(_GNU_SOURCE)
33+
#define _GNU_SOURCE 1
34+
#endif
35+
2736
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
2837

2938
#ifndef WOLFCRYPT_ONLY
@@ -42,6 +51,12 @@
4251
#include <wolfssl/wolfio.h>
4352
#include <wolfssl/wolfcrypt/logging.h>
4453

54+
/* SOCK_CLOEXEC sets close-on-exec atomically when the socket is created;
55+
* fall back to a no-op flag value where it isn't supported. */
56+
#ifndef SOCK_CLOEXEC
57+
#define SOCK_CLOEXEC 0
58+
#endif
59+
4560
#ifdef NUCLEUS_PLUS_2_3
4661
/* Holds last Nucleus networking error number */
4762
int Nucleus_Net_Errno;
@@ -1494,7 +1509,17 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
14941509
}
14951510
#endif
14961511

1497-
*sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
1512+
*sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
1513+
#if !defined(USE_WINDOWS_API) && defined(FD_CLOEXEC)
1514+
if (*sockfd <= SOCKET_INVALID && errno == EINVAL) {
1515+
*sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
1516+
if (*sockfd > SOCKET_INVALID) {
1517+
int fdFlags = fcntl(*sockfd, F_GETFD);
1518+
if (fdFlags >= 0)
1519+
(void)fcntl(*sockfd, F_SETFD, fdFlags | FD_CLOEXEC);
1520+
}
1521+
}
1522+
#endif
14981523
#ifdef USE_WINDOWS_API
14991524
if (*sockfd == SOCKET_INVALID)
15001525
#else
@@ -1572,12 +1597,32 @@ int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
15721597
sin->sin6_family = AF_INET6;
15731598
sin->sin6_addr = in6addr_any;
15741599
sin->sin6_port = XHTONS(port);
1575-
*sockfd = (SOCKET_T)socket(AF_INET6, SOCK_STREAM, 0);
1600+
*sockfd = (SOCKET_T)socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
1601+
#if defined(FD_CLOEXEC)
1602+
if (*sockfd <= SOCKET_INVALID && errno == EINVAL) {
1603+
*sockfd = (SOCKET_T)socket(AF_INET6, SOCK_STREAM, 0);
1604+
if (*sockfd > SOCKET_INVALID) {
1605+
int fdFlags = fcntl(*sockfd, F_GETFD);
1606+
if (fdFlags >= 0)
1607+
(void)fcntl(*sockfd, F_SETFD, fdFlags | FD_CLOEXEC);
1608+
}
1609+
}
1610+
#endif
15761611
#else
15771612
sin->sin_family = AF_INET;
15781613
sin->sin_addr.s_addr = INADDR_ANY;
15791614
sin->sin_port = XHTONS(port);
1580-
*sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM, 0);
1615+
*sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
1616+
#if defined(FD_CLOEXEC)
1617+
if (*sockfd <= SOCKET_INVALID && errno == EINVAL) {
1618+
*sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM, 0);
1619+
if (*sockfd > SOCKET_INVALID) {
1620+
int fdFlags = fcntl(*sockfd, F_GETFD);
1621+
if (fdFlags >= 0)
1622+
(void)fcntl(*sockfd, F_SETFD, fdFlags | FD_CLOEXEC);
1623+
}
1624+
}
1625+
#endif
15811626
#endif
15821627

15831628
#ifdef USE_WINDOWS_API
@@ -1623,7 +1668,31 @@ int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
16231668
#ifdef HAVE_SOCKADDR
16241669
int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
16251670
{
1626-
return (int)accept(sockfd, peer_addr, peer_len);
1671+
int fd;
1672+
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_ZEPHYR) && \
1673+
(defined(__linux__) || defined(__ANDROID__))
1674+
fd = (int)accept4(sockfd, peer_addr, peer_len, SOCK_CLOEXEC);
1675+
if (fd < 0 && (errno == ENOSYS || errno == EINVAL)) {
1676+
fd = (int)accept(sockfd, peer_addr, peer_len);
1677+
#ifdef FD_CLOEXEC
1678+
if (fd >= 0) {
1679+
int fdFlags = fcntl(fd, F_GETFD);
1680+
if (fdFlags >= 0)
1681+
(void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC);
1682+
}
1683+
#endif
1684+
}
1685+
#else
1686+
fd = (int)accept(sockfd, peer_addr, peer_len);
1687+
#if defined(FD_CLOEXEC) && !defined(USE_WINDOWS_API)
1688+
if (fd >= 0) {
1689+
int fdFlags = fcntl(fd, F_GETFD);
1690+
if (fdFlags >= 0)
1691+
(void)fcntl(fd, F_SETFD, fdFlags | FD_CLOEXEC);
1692+
}
1693+
#endif
1694+
#endif
1695+
return fd;
16271696
}
16281697
#endif /* HAVE_SOCKADDR */
16291698

wolfcrypt/benchmark/benchmark.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1574,16 +1574,34 @@ static const char* bench_result_words3[][5] = {
15741574
#include <linux/perf_event.h>
15751575
#include <sys/syscall.h>
15761576
#include <unistd.h>
1577+
#include <fcntl.h>
1578+
#include <errno.h>
1579+
1580+
#ifndef PERF_FLAG_FD_CLOEXEC
1581+
#define PERF_FLAG_FD_CLOEXEC (1UL << 3)
1582+
#endif
15771583

15781584
static THREAD_LS_T word64 begin_cycles;
15791585
static THREAD_LS_T word64 total_cycles;
15801586
static THREAD_LS_T int cycles = -1;
15811587
static THREAD_LS_T struct perf_event_attr atr;
15821588

1589+
/* Try with PERF_FLAG_FD_CLOEXEC first; on older kernels (< 3.14) this
1590+
* fails with EINVAL, so fall back to flags=0 and set FD_CLOEXEC via
1591+
* fcntl() as a best-effort. */
15831592
#define INIT_CYCLE_COUNTER do { \
15841593
atr.type = PERF_TYPE_HARDWARE; \
15851594
atr.config = PERF_COUNT_HW_CPU_CYCLES; \
1586-
cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, 0); \
1595+
cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, \
1596+
PERF_FLAG_FD_CLOEXEC); \
1597+
if (cycles < 0 && errno == EINVAL) { \
1598+
cycles = (int)syscall(__NR_perf_event_open, &atr, 0, -1, -1, 0); \
1599+
if (cycles >= 0) { \
1600+
int _fdFlags = fcntl(cycles, F_GETFD); \
1601+
if (_fdFlags >= 0) \
1602+
(void)fcntl(cycles, F_SETFD, _fdFlags | FD_CLOEXEC); \
1603+
} \
1604+
} \
15871605
} while (0);
15881606

15891607
#define BEGIN_CYCLES read(cycles, &begin_cycles, sizeof(begin_cycles));

0 commit comments

Comments
 (0)