Skip to content

Commit 2d862c6

Browse files
authored
Merge pull request #143 from WEBcodeX1/copilot/fix-e8970674-1e57-4eff-becf-ad4317dea7cb
Replace pidfd_getfd() With Unix Domain Socket(s)
2 parents 1b4ceb7 + c4b8dc0 commit 2d862c6

7 files changed

Lines changed: 287 additions & 26 deletions

File tree

src/ASProcessHandler.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,11 @@ void ASProcessHandler::forkProcessASHandler(ASProcessHandlerSHMPointer_t SHMAdre
119119
ERR("Cannot change dir to BackendRootPath Path:" << BackendRootPath.c_str());
120120
}
121121

122-
//- get parent pid filedescriptor
123-
pidfd_t ParentPidFD = Syscall::pidfd_open(getppid(), 0);
124-
125122
const char* Env1 = std::getenv("PATH");
126123
const char* Env2 = std::getenv("PYTHONPATH");
127124

128125
DBG(120, "Process PATH:" << Env1 << " PYTHONPATH:" << Env2);
129-
DBG(200, "Child ASProcessHandler Process PID:" << getpid() << " ParentPidFD:" << ParentPidFD);
126+
DBG(200, "Child ASProcessHandler Process PID:" << getpid());
130127

131128
//- initialize backend
132129
Backend::Processor::init(this);

src/Global.hpp

Lines changed: 113 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33

44
#include <csignal>
55
#include <string>
6+
#include <cstring>
67
#include <unordered_map>
78
#include <vector>
89
#include <exception>
910
#include <cstdlib>
1011

1112
#include <sys/syscall.h>
13+
#include <sys/socket.h>
14+
#include <sys/un.h>
1215
#include <unistd.h>
1316
#include <execinfo.h>
1417

@@ -19,7 +22,6 @@ using namespace std;
1922

2023

2124
typedef unsigned int Filedescriptor_t;
22-
typedef unsigned int pidfd_t;
2325

2426
typedef uint16_t HTTPVersionType_t;
2527
typedef uint16_t HTTPMethodType_t;
@@ -53,7 +55,7 @@ class Signal {
5355

5456
public:
5557

56-
//- disable unwanted signal handlers (SIGINT, SIGPIPE)
58+
// disable unwanted signal handlers (SIGINT, SIGPIPE)
5759
static void disableSignals()
5860
{
5961
signal(SIGINT, SIG_IGN);
@@ -67,16 +69,118 @@ class Syscall {
6769

6870
public:
6971

70-
//- wrapper function for pidfd_open
71-
static int pidfd_open(pid_t pid, unsigned int flags)
72+
// unix domain socket for FD passing - server side (parent process)
73+
static int createFDPassingServer(const char* socket_path)
7274
{
73-
return syscall(SYS_pidfd_open, pid, flags);
75+
int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
76+
if (server_fd < 0) {
77+
return -1;
78+
}
79+
80+
// remove any existing socket file
81+
unlink(socket_path);
82+
83+
struct sockaddr_un server_addr;
84+
memset(&server_addr, 0, sizeof(server_addr));
85+
server_addr.sun_family = AF_UNIX;
86+
strncpy(server_addr.sun_path, socket_path, sizeof(server_addr.sun_path) - 1);
87+
88+
if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
89+
close(server_fd);
90+
return -1;
91+
}
92+
93+
if (listen(server_fd, 50) < 0) {
94+
close(server_fd);
95+
return -1;
96+
}
97+
98+
return server_fd;
7499
}
75100

76-
//- wrapper function for pidfd_getfd
77-
static int pidfd_getfd(int pidfd, int targetfd, unsigned int flags)
101+
// unix domain socket for FD passing - client side (child process)
102+
static int connectFDPassingClient(const char* socket_path)
78103
{
79-
return syscall(SYS_pidfd_getfd, pidfd, targetfd, flags);
104+
int client_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
105+
if (client_fd < 0) {
106+
return -1;
107+
}
108+
109+
struct sockaddr_un server_addr;
110+
memset(&server_addr, 0, sizeof(server_addr));
111+
server_addr.sun_family = AF_UNIX;
112+
strncpy(server_addr.sun_path, socket_path, sizeof(server_addr.sun_path) - 1);
113+
114+
if (connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
115+
close(client_fd);
116+
return -1;
117+
}
118+
119+
return client_fd;
120+
}
121+
122+
// send a file descriptor over Unix domain socket
123+
static int sendFD(int socket_fd, int fd_to_send)
124+
{
125+
struct msghdr msg;
126+
struct iovec iov[1];
127+
char ctrl_buf[CMSG_SPACE(sizeof(int))];
128+
char data[1] = {0};
129+
130+
memset(&msg, 0, sizeof(msg));
131+
memset(ctrl_buf, 0, sizeof(ctrl_buf));
132+
133+
// Setup iovec for dummy data
134+
iov[0].iov_base = data;
135+
iov[0].iov_len = sizeof(data);
136+
137+
msg.msg_iov = iov;
138+
msg.msg_iovlen = 1;
139+
msg.msg_control = ctrl_buf;
140+
msg.msg_controllen = sizeof(ctrl_buf);
141+
142+
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
143+
cmsg->cmsg_level = SOL_SOCKET;
144+
cmsg->cmsg_type = SCM_RIGHTS;
145+
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
146+
*((int*)CMSG_DATA(cmsg)) = fd_to_send;
147+
148+
if (sendmsg(socket_fd, &msg, 0) < 0) {
149+
return -1;
150+
}
151+
152+
return 0;
153+
}
154+
155+
// receive a file descriptor over Unix domain socket
156+
static int recvFD(int socket_fd)
157+
{
158+
struct msghdr msg;
159+
struct iovec iov[1];
160+
char ctrl_buf[CMSG_SPACE(sizeof(int))];
161+
char data[1];
162+
163+
memset(&msg, 0, sizeof(msg));
164+
memset(ctrl_buf, 0, sizeof(ctrl_buf));
165+
166+
iov[0].iov_base = data;
167+
iov[0].iov_len = sizeof(data);
168+
169+
msg.msg_iov = iov;
170+
msg.msg_iovlen = 1;
171+
msg.msg_control = ctrl_buf;
172+
msg.msg_controllen = sizeof(ctrl_buf);
173+
174+
if (recvmsg(socket_fd, &msg, 0) < 0) {
175+
return -1;
176+
}
177+
178+
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
179+
if (cmsg == NULL || cmsg->cmsg_type != SCM_RIGHTS) {
180+
return -1;
181+
}
182+
183+
return *((int*)CMSG_DATA(cmsg));
80184
}
81185

82186
};
@@ -88,7 +192,7 @@ class Permission {
88192

89193
static void dropPrivileges(uint GroupID, uint UserID)
90194
{
91-
//- in case of being root, drop privileges
195+
// in case of being root, drop privileges
92196
if (getuid() == 0) {
93197

94198
if (setgid(GroupID) != 0) {

src/ResultProcessor.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ void ResultProcessor::terminate(int _ignored)
2929
RunServer = false;
3030
}
3131

32+
int ResultProcessor::_getFDFromParent(uint16_t fd)
33+
{
34+
// send the requested FD number to the parent
35+
if (write(_FDPassingSocketFD, &fd, sizeof(fd)) != sizeof(fd)) {
36+
ERR("Failed to send FD request to parent");
37+
return -1;
38+
}
39+
40+
// Receive the FD from the parent
41+
int received_fd = Syscall::recvFD(_FDPassingSocketFD);
42+
43+
if (received_fd < 0) {
44+
ERR("Failed to receive FD from parent");
45+
return -1;
46+
}
47+
48+
DBG(120, "Received FD:" << received_fd << " from parent for requested FD:" << fd);
49+
return received_fd;
50+
}
51+
3252
void ResultProcessor::setVHostOffsets(VHostOffsetsPrecalc_t VHostOffsets) {
3353
_VHostOffsetsPrecalc = VHostOffsets;
3454
}
@@ -56,16 +76,27 @@ pid_t ResultProcessor::forkProcessResultProcessor(ResultProcessorSHMPointer_t SH
5676

5777
if (_ForkResult == 0) {
5878

59-
//- get parent pid filedescriptor
60-
_ParentPidFD = Syscall::pidfd_open(getppid(), 0);
79+
//- connect to parent's FD passing server
80+
const char* socket_path = "/tmp/falcon-fd-passing.sock";
81+
_FDPassingSocketFD = Syscall::connectFDPassingClient(socket_path);
82+
83+
if (_FDPassingSocketFD < 0) {
84+
ERR("ResultProcessor: Failed to connect to FD passing server");
85+
exit(1);
86+
}
87+
88+
DBG(120, "ResultProcessor: Connected to FD passing server");
6189

6290
//- overwrite parent termination handler
6391
setTerminationHandler();
6492

6593
//- spectre userspace protection
6694
prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
6795

68-
DBG(120, "Child ResultProcessor Process PID:" << getpid() << " ParentPidFD:" << _ParentPidFD);
96+
//- drop privileges
97+
Permission::dropPrivileges(RUNAS_USER_DEFAULT, RUNAS_GROUP_DEFAULT);
98+
99+
DBG(120, "Child ResultProcessor Process PID:" << getpid() << " FDPassingSocketFD:" << _FDPassingSocketFD);
69100
DBG(120, "Child ResultProcessor SharedMemAddress:" << SHMAdresses.StaticFSPtr);
70101
DBG(120, "Child ResultProcessor Atomic Address:" << StaticFSLock << " Value:" << *(StaticFSLock));
71102

@@ -120,7 +151,11 @@ pid_t ResultProcessor::forkProcessResultProcessor(ResultProcessorSHMPointer_t SH
120151
}
121152
}
122153

123-
DBG(-1, "Exit Parent ResultProcessor Process.");
154+
DBG(-1, "Parent ResultProcessor closing Unix Domain Socket.");
155+
156+
close(_FDPassingSocketFD);
157+
158+
DBG(-1, "Exit parent ResultProcessor process.");
124159
exit(0);
125160
}
126161
}
@@ -151,7 +186,7 @@ void ResultProcessor::_processStaticFSRequests(uint16_t RequestCount)
151186
getNextAddress(ClientPayloadLength);
152187
DBG(120, "ClientFD:" << ClientFD << " ReqNr:" << ReqNr << " HTTPVersion:" << HTTPVersion << " PayloadLength:" << ClientPayloadLength << " Payload:'" << ClientPayloadString << "'");
153188

154-
ClientFD_t ClientFDShared = Syscall::pidfd_getfd(_ParentPidFD, ClientFD, 0);
189+
ClientFD_t ClientFDShared = _getFDFromParent(ClientFD);
155190

156191
RequestProps_t Request;
157192

@@ -170,7 +205,6 @@ uint16_t ResultProcessor::_processPythonASResults()
170205
{
171206
uint16_t processed = 0;
172207

173-
//for (const auto& Namespace: _Namespaces) {
174208
for (const auto& Namespace: ConfigRef.Namespaces) {
175209
for (const auto &Index: _VHostOffsetsPrecalc.at(Namespace.first)) {
176210
atomic_uint16_t* CanReadAddr = static_cast<atomic_uint16_t*>(getMetaAddress(Index, 0));
@@ -182,7 +216,7 @@ uint16_t ResultProcessor::_processPythonASResults()
182216
RequestProps_t Request;
183217

184218
Request.ClientFD = *(static_cast<ClientFD_t*>(getMetaAddress(Index, 2)));
185-
Request.ClientFDShared = Syscall::pidfd_getfd(_ParentPidFD, Request.ClientFD, 0);
219+
Request.ClientFDShared = _getFDFromParent(Request.ClientFD);
186220
Request.HTTPVersion = *(static_cast<HTTPVersionType_t*>(getMetaAddress(Index, 3)));
187221
Request.PayloadLength = *(static_cast<HTTPPayloadLength_t*>(getMetaAddress(Index, 7)));
188222

src/ResultProcessor.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,10 @@ class ResultProcessor : private SHMStaticFS, public CPU, private ResultOrder, pr
4343
void _processStaticFSRequests(uint16_t);
4444
inline void _parseHTTPBaseProps(string&);
4545
uint16_t _processPythonASResults();
46+
int _getFDFromParent(uint16_t fd);
4647

4748
pid_t _ForkResult;
48-
pidfd_t _ParentPidFD;
49+
int _FDPassingSocketFD;
4950
VHostOffsetsPrecalc_t _VHostOffsetsPrecalc;
5051

5152
};

0 commit comments

Comments
 (0)