mirror of
https://github.com/espressif/openthread.git
synced 2026-09-03 15:50:06 +00:00
[posix] close files on exec (#3977)
This commit adds the *_CLOEXEC flags when opening files. This ensures files are closed when spawning new processes. * use LOG_DAEMON as syslog facility * remove setenv() when forkpty
This commit is contained in:
@@ -78,7 +78,7 @@ otError utilsFlashInit(void)
|
||||
create = true;
|
||||
}
|
||||
|
||||
sFlashFd = open(fileName, O_RDWR | O_CREAT, 0600);
|
||||
sFlashFd = open(fileName, O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||
lseek(sFlashFd, 0, SEEK_SET);
|
||||
|
||||
otEXPECT_ACTION(sFlashFd >= 0, error = OT_ERROR_FAILED);
|
||||
|
||||
@@ -320,7 +320,7 @@ int HdlcInterface::OpenFile(const char *aFile, const char *aConfig)
|
||||
int fd = -1;
|
||||
int rval = 0;
|
||||
|
||||
fd = open(aFile, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
fd = open(aFile, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open uart failed");
|
||||
@@ -480,8 +480,9 @@ exit:
|
||||
#if OPENTHREAD_CONFIG_POSIX_APP_ENABLE_PTY_DEVICE
|
||||
int HdlcInterface::ForkPty(const char *aCommand, const char *aArguments)
|
||||
{
|
||||
int fd = -1;
|
||||
int pid = -1;
|
||||
int fd = -1;
|
||||
int pid = -1;
|
||||
int rval = -1;
|
||||
|
||||
{
|
||||
struct termios tios;
|
||||
@@ -490,54 +491,30 @@ int HdlcInterface::ForkPty(const char *aCommand, const char *aArguments)
|
||||
cfmakeraw(&tios);
|
||||
tios.c_cflag = CS8 | HUPCL | CREAD | CLOCAL;
|
||||
|
||||
pid = forkpty(&fd, NULL, &tios, NULL);
|
||||
VerifyOrExit(pid >= 0);
|
||||
VerifyOrExit((pid = forkpty(&fd, NULL, &tios, NULL)) != -1, perror("forkpty()"));
|
||||
}
|
||||
|
||||
if (0 == pid)
|
||||
{
|
||||
const int kMaxCommand = 255;
|
||||
char cmd[kMaxCommand];
|
||||
int rval;
|
||||
struct rlimit limit;
|
||||
|
||||
rval = getrlimit(RLIMIT_NOFILE, &limit);
|
||||
rval = setenv("SHELL", SOCKET_UTILS_DEFAULT_SHELL, 0);
|
||||
|
||||
VerifyOrExit(rval == 0, perror("setenv failed"));
|
||||
|
||||
// Close all file descriptors larger than STDERR_FILENO.
|
||||
for (rlim_t i = (STDERR_FILENO + 1); i < limit.rlim_cur; i++)
|
||||
{
|
||||
close(static_cast<int>(i));
|
||||
}
|
||||
const int kMaxCommand = 255;
|
||||
char cmd[kMaxCommand];
|
||||
|
||||
rval = snprintf(cmd, sizeof(cmd), "exec %s %s", aCommand, aArguments);
|
||||
VerifyOrExit(rval > 0 && static_cast<size_t>(rval) < sizeof(cmd),
|
||||
otLogCritPlat("NCP file and configuration is too long!"));
|
||||
fprintf(stderr, "NCP file and configuration is too long!");
|
||||
rval = -1);
|
||||
|
||||
execl(getenv("SHELL"), getenv("SHELL"), "-c", cmd, NULL);
|
||||
perror("open pty failed");
|
||||
exit(OT_EXIT_INVALID_ARGUMENTS);
|
||||
VerifyOrExit((rval = execl(SOCKET_UTILS_DEFAULT_SHELL, SOCKET_UTILS_DEFAULT_SHELL, "-c", cmd, NULL)) != -1,
|
||||
perror("execl(OT_RCP)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
int rval = fcntl(fd, F_GETFL);
|
||||
|
||||
if (rval != -1)
|
||||
{
|
||||
rval = fcntl(fd, F_SETFL, rval | O_NONBLOCK);
|
||||
}
|
||||
|
||||
if (rval == -1)
|
||||
{
|
||||
perror("set nonblock failed");
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
VerifyOrExit((rval = fcntl(fd, F_GETFL)) != -1, perror("fcntl(F_GETFL)"));
|
||||
VerifyOrExit((rval = fcntl(fd, F_SETFL, rval | O_NONBLOCK | O_CLOEXEC)) != -1, perror("fcntl(F_SETFL)"));
|
||||
}
|
||||
|
||||
exit:
|
||||
VerifyOrDie(rval == 0, OT_EXIT_FAILURE);
|
||||
return fd;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_POSIX_APP_ENABLE_PTY_DEVICE
|
||||
|
||||
@@ -46,7 +46,7 @@ void platformLoggingInit(const char *aName)
|
||||
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
|
||||
(OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
|
||||
|
||||
openlog(aName, LOG_PID, LOG_USER);
|
||||
openlog(aName, LOG_PID, LOG_DAEMON);
|
||||
setlogmask(setlogmask(0) & LOG_UPTO(LOG_DEBUG));
|
||||
|
||||
#else
|
||||
|
||||
@@ -30,11 +30,14 @@
|
||||
#include "platform-posix.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/platform/misc.h>
|
||||
|
||||
#include "code_utils.h"
|
||||
#include "openthread-system.h"
|
||||
#include "common/logging.hpp"
|
||||
|
||||
@@ -123,3 +126,27 @@ void VerifyOrDie(bool aCondition, int aExitCode)
|
||||
exit(aExitCode);
|
||||
}
|
||||
}
|
||||
|
||||
int SocketWithCloseExec(int aDomain, int aType, int aProtocol)
|
||||
{
|
||||
int rval = 0;
|
||||
int fd = -1;
|
||||
|
||||
#ifdef __APPLE__
|
||||
otEXPECT_ACTION((fd = socket(aDomain, aType, aProtocol)) != -1, perror("socket(SOCK_CLOEXEC)"));
|
||||
|
||||
otEXPECT_ACTION((rval = fcntl(fd, F_GETFD, 0)) != -1, perror("fcntl(F_GETFD)"));
|
||||
otEXPECT_ACTION((rval = fcntl(fd, F_SETFD, rval | FD_CLOEXEC)) != -1, perror("fcntl(F_SETFD)"));
|
||||
#else
|
||||
otEXPECT_ACTION((fd = socket(aDomain, aType | SOCK_CLOEXEC, aProtocol)) != -1, perror("socket(SOCK_CLOEXEC)"));
|
||||
#endif
|
||||
|
||||
exit:
|
||||
if (rval == -1 && fd != -1)
|
||||
{
|
||||
VerifyOrDie(close(fd) == 0, OT_EXIT_FAILURE);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -386,8 +386,8 @@ void platformNetifInit(otInstance *aInstance)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
sIpFd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
|
||||
VerifyOrExit(sIpFd > 0);
|
||||
sIpFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
|
||||
VerifyOrExit(sIpFd >= 0);
|
||||
|
||||
sNetlinkFd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||
VerifyOrExit(sNetlinkFd > 0);
|
||||
@@ -403,7 +403,7 @@ void platformNetifInit(otInstance *aInstance)
|
||||
VerifyOrExit(bind(sNetlinkFd, reinterpret_cast<struct sockaddr *>(&sa), sizeof(sa)) == 0);
|
||||
}
|
||||
|
||||
sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR);
|
||||
sTunFd = open(OPENTHREAD_POSIX_TUN_DEVICE, O_RDWR | O_CLOEXEC);
|
||||
VerifyOrExit(sTunFd > 0, otLogCritPlat("Unable to open tun device %s", OPENTHREAD_POSIX_TUN_DEVICE));
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
@@ -399,6 +399,20 @@ void VerifyOrDie(bool aCondition, int aExitCode);
|
||||
*/
|
||||
void SuccessOrDie(otError aError);
|
||||
|
||||
/**
|
||||
* This function creates a socket with SOCK_CLOEXEC flag set.
|
||||
*
|
||||
* @param[in] aDomain The communication domain.
|
||||
* @param[in] aType The semantics of communication.
|
||||
* @param[in] aProtocol The protocol to use.
|
||||
*
|
||||
* @returns The file descriptor of the created socket.
|
||||
*
|
||||
* @retval -1 Failed to create socket.
|
||||
*
|
||||
*/
|
||||
int SocketWithCloseExec(int aDomain, int aType, int aProtocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -77,7 +77,7 @@ static int swapOpen(void)
|
||||
int fd;
|
||||
|
||||
getSettingsFileName(fileName, true);
|
||||
fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||
fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
|
||||
VerifyOrDie(fd != -1);
|
||||
|
||||
return fd;
|
||||
@@ -152,7 +152,7 @@ void otPlatSettingsInit(otInstance *aInstance)
|
||||
char fileName[kMaxFileNameSize];
|
||||
|
||||
getSettingsFileName(fileName, false);
|
||||
sSettingsFd = open(fileName, O_RDWR | O_CREAT, 0600);
|
||||
sSettingsFd = open(fileName, O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||
}
|
||||
|
||||
VerifyOrDie(sSettingsFd != -1);
|
||||
|
||||
@@ -84,7 +84,7 @@ void otSimInit(void)
|
||||
sockaddr.sin_port = htons(kBasePort + sPortOffset + sNodeId);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
sSockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
sSockFd = SocketWithCloseExec(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (sSockFd == -1)
|
||||
{
|
||||
|
||||
@@ -60,17 +60,6 @@ static bool sEnabled = false;
|
||||
static const uint8_t *sWriteBuffer = NULL;
|
||||
static uint16_t sWriteLength = 0;
|
||||
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
static void set_flag_cloexec(int a_fd)
|
||||
{
|
||||
int ret = fcntl(a_fd, F_GETFD, 0);
|
||||
VerifyOrDie(ret != -1, OT_EXIT_FAILURE);
|
||||
ret |= FD_CLOEXEC;
|
||||
ret = fcntl(a_fd, F_SETFD, ret);
|
||||
VerifyOrDie(ret != -1, OT_EXIT_FAILURE);
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
|
||||
otError otPlatUartEnable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -78,17 +67,14 @@ otError otPlatUartEnable(void)
|
||||
struct sockaddr_un sockname;
|
||||
int ret;
|
||||
|
||||
sUartSocket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
sUartSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (sUartSocket == -1)
|
||||
{
|
||||
perror("socket");
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
|
||||
set_flag_cloexec(sUartSocket);
|
||||
|
||||
sUartLock = open(OPENTHREAD_POSIX_APP_SOCKET_LOCK, O_CREAT | O_RDONLY, 0600);
|
||||
sUartLock = open(OPENTHREAD_POSIX_APP_SOCKET_LOCK, O_CREAT | O_RDONLY | O_CLOEXEC, 0600);
|
||||
|
||||
if (sUartLock == -1)
|
||||
{
|
||||
@@ -96,8 +82,6 @@ otError otPlatUartEnable(void)
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
|
||||
set_flag_cloexec(sUartLock);
|
||||
|
||||
if (flock(sUartLock, LOCK_EX | LOCK_NB) == -1)
|
||||
{
|
||||
perror("flock");
|
||||
@@ -290,7 +274,10 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co
|
||||
}
|
||||
else if (rval <= 0)
|
||||
{
|
||||
perror("UART read");
|
||||
if (rval != 0)
|
||||
{
|
||||
perror("read(UART)");
|
||||
}
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
close(sSessionSocket);
|
||||
sSessionSocket = -1;
|
||||
|
||||
@@ -217,8 +217,8 @@ otError otPlatUdpSocket(otUdpSocket *aUdpSocket)
|
||||
|
||||
assert(aUdpSocket->mHandle == NULL);
|
||||
|
||||
fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
VerifyOrExit(fd > 0, error = OT_ERROR_FAILED);
|
||||
fd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
VerifyOrExit(fd >= 0, error = OT_ERROR_FAILED);
|
||||
|
||||
aUdpSocket->mHandle = FdToHandle(fd);
|
||||
|
||||
|
||||
@@ -1138,7 +1138,7 @@ static bool setup_spi_dev(const char *path)
|
||||
int ret;
|
||||
sSpiDevPath = path;
|
||||
|
||||
fd = open(path, O_RDWR);
|
||||
fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open");
|
||||
@@ -1212,7 +1212,7 @@ static bool setup_res_gpio(const char *path)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
setup_fd = open(dir_path, O_WRONLY);
|
||||
setup_fd = open(dir_path, O_WRONLY | O_CLOEXEC);
|
||||
|
||||
if (setup_fd >= 0)
|
||||
{
|
||||
@@ -1223,7 +1223,7 @@ static bool setup_res_gpio(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
sResGpioValueFd = open(value_path, O_WRONLY);
|
||||
sResGpioValueFd = open(value_path, O_WRONLY | O_CLOEXEC);
|
||||
|
||||
bail:
|
||||
|
||||
@@ -1308,7 +1308,7 @@ static bool setup_int_gpio(const char *path)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
setup_fd = open(dir_path, O_WRONLY);
|
||||
setup_fd = open(dir_path, O_WRONLY | O_CLOEXEC);
|
||||
|
||||
if (setup_fd >= 0)
|
||||
{
|
||||
@@ -1322,7 +1322,7 @@ static bool setup_int_gpio(const char *path)
|
||||
close(setup_fd);
|
||||
}
|
||||
|
||||
setup_fd = open(edge_path, O_WRONLY);
|
||||
setup_fd = open(edge_path, O_WRONLY | O_CLOEXEC);
|
||||
|
||||
if (setup_fd >= 0)
|
||||
{
|
||||
@@ -1339,7 +1339,7 @@ static bool setup_int_gpio(const char *path)
|
||||
setup_fd = -1;
|
||||
}
|
||||
|
||||
sIntGpioValueFd = open(value_path, O_RDONLY);
|
||||
sIntGpioValueFd = open(value_path, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
bail:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user