Skip to content

Commit 64a5b5f

Browse files
pizhenweiproost
authored andcommitted
RDMA: Prevent IO for child process (valkey-io#1244)
RDMA MR (memory region) is not forkable, the VMA (virtual memory area) of a MR gets empty in a child process. Prevent IO for child process to avoid server crash. In the check for whether read and write is allowed in an RDMA connection, a check that if we're in a child process is added. If we are, the function returns an error, which will cause the RDMA client to be disconnected. Suggested-by: Viktor Söderqvist <[email protected]> Signed-off-by: zhenwei pi <[email protected]>
1 parent 9a11e1a commit 64a5b5f

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

src/rdma.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,34 @@ static void serverRdmaError(char *err, const char *fmt, ...) {
143143
va_end(ap);
144144
}
145145

146+
static inline int connRdmaAllowCommand(void) {
147+
/* RDMA MR is not accessible in a child process, avoid segment fault due to
148+
* invalid MR access, close it rather than server random crash */
149+
if (server.in_fork_child != CHILD_TYPE_NONE) {
150+
return C_ERR;
151+
}
152+
153+
return C_OK;
154+
}
155+
156+
static inline int connRdmaAllowRW(connection *conn) {
157+
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
158+
return C_ERR;
159+
}
160+
161+
return connRdmaAllowCommand();
162+
}
163+
146164
static int rdmaPostRecv(RdmaContext *ctx, struct rdma_cm_id *cm_id, ValkeyRdmaCmd *cmd) {
147165
struct ibv_sge sge;
148166
size_t length = sizeof(ValkeyRdmaCmd);
149167
struct ibv_recv_wr recv_wr, *bad_wr;
150168
int ret;
151169

170+
if (connRdmaAllowCommand()) {
171+
return C_ERR;
172+
}
173+
152174
sge.addr = (uint64_t)cmd;
153175
sge.length = length;
154176
sge.lkey = ctx->cmd_mr->lkey;
@@ -1214,6 +1236,10 @@ static size_t connRdmaSend(connection *conn, const void *data, size_t data_len)
12141236
char *remote_addr = ctx->tx_addr + ctx->tx.offset;
12151237
int ret;
12161238

1239+
if (connRdmaAllowCommand()) {
1240+
return C_ERR;
1241+
}
1242+
12171243
memcpy(addr, data, data_len);
12181244

12191245
sge.addr = (uint64_t)addr;
@@ -1247,7 +1273,7 @@ static int connRdmaWrite(connection *conn, const void *data, size_t data_len) {
12471273
RdmaContext *ctx = cm_id->context;
12481274
uint32_t towrite;
12491275

1250-
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
1276+
if (connRdmaAllowRW(conn)) {
12511277
return C_ERR;
12521278
}
12531279

@@ -1290,7 +1316,7 @@ static int connRdmaRead(connection *conn, void *buf, size_t buf_len) {
12901316
struct rdma_cm_id *cm_id = rdma_conn->cm_id;
12911317
RdmaContext *ctx = cm_id->context;
12921318

1293-
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
1319+
if (connRdmaAllowRW(conn)) {
12941320
return C_ERR;
12951321
}
12961322

@@ -1312,7 +1338,7 @@ static ssize_t connRdmaSyncWrite(connection *conn, char *ptr, ssize_t size, long
13121338
long long start = mstime();
13131339
uint32_t towrite;
13141340

1315-
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
1341+
if (connRdmaAllowRW(conn)) {
13161342
return C_ERR;
13171343
}
13181344

@@ -1355,7 +1381,7 @@ static ssize_t connRdmaSyncRead(connection *conn, char *ptr, ssize_t size, long
13551381
long long start = mstime();
13561382
uint32_t toread;
13571383

1358-
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
1384+
if (connRdmaAllowRW(conn)) {
13591385
return C_ERR;
13601386
}
13611387

@@ -1390,7 +1416,7 @@ static ssize_t connRdmaSyncReadLine(connection *conn, char *ptr, ssize_t size, l
13901416
char *c;
13911417
char nl = 0;
13921418

1393-
if (conn->state == CONN_STATE_ERROR || conn->state == CONN_STATE_CLOSED) {
1419+
if (connRdmaAllowRW(conn)) {
13941420
return C_ERR;
13951421
}
13961422

0 commit comments

Comments
 (0)