Spawn server fixes No 4 (#18127)
add a magic number to all spawn server replies to ensure they are not corrupted
Costa Tsaousis committed
Jul 12, 2024 at 13:54 UTC
078015b98234bfb59607144f91c86e7571a27c6e
1 file changed
+48
-11
src/libnetdata/spawn_server/spawn_server.c
+48
-11
@@ -323,13 +323,17 @@ static int connect_to_spawn_server(const char *path, bool log) {
323
// the child created by the spawn server
324
325
typedef enum __attribute__((packed)) {
326
+ STATUS_REPORT_NONE = 0,
327
STATUS_REPORT_STARTED,
328
STATUS_REPORT_FAILED,
329
STATUS_REPORT_EXITED,
330
STATUS_REPORT_PING,
331
} STATUS_REPORT;
332
333
+#define STATUS_REPORT_MAGIC 0xBADA55EE
334
+
335
struct status_report {
336
+ uint32_t magic;
337
STATUS_REPORT status;
338
union {
339
struct {
@@ -346,17 +350,20 @@ struct status_report {
350
};
351
};
352
349
-static void spawn_server_send_status_ping(int fd) {
353
+static void spawn_server_send_status_ping(int sock) {
354
struct status_report sr = {
355
+ .magic = STATUS_REPORT_MAGIC,
356
.status = STATUS_REPORT_PING,
357
};
358
354
- if(write(fd, &sr, sizeof(sr)) != sizeof(sr))
355
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Cannot send ping status report");
359
+ if(write(sock, &sr, sizeof(sr)) != sizeof(sr))
360
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
361
+ "SPAWN SERVER: Cannot send ping reply.");
362
}
363
364
static void spawn_server_send_status_success(SPAWN_REQUEST *rq) {
365
const struct status_report sr = {
366
+ .magic = STATUS_REPORT_MAGIC,
367
.status = STATUS_REPORT_STARTED,
368
.started = {
369
.pid = getpid(),
@@ -364,11 +371,14 @@ static void spawn_server_send_status_success(SPAWN_REQUEST *rq) {
371
};
372
373
if(write(rq->sock, &sr, sizeof(sr)) != sizeof(sr))
367
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Cannot send success status report");
374
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
375
+ "SPAWN SERVER: Cannot send success status report for request %zu: %s",
376
+ rq->request_id, rq->cmdline);
377
}
378
379
static void spawn_server_send_status_failure(SPAWN_REQUEST *rq) {
380
struct status_report sr = {
381
+ .magic = STATUS_REPORT_MAGIC,
382
.status = STATUS_REPORT_FAILED,
383
.failed = {
384
.err_no = errno,
@@ -376,11 +386,14 @@ static void spawn_server_send_status_failure(SPAWN_REQUEST *rq) {
386
};
387
388
if(write(rq->sock, &sr, sizeof(sr)) != sizeof(sr))
379
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Cannot send failure status report");
389
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
390
+ "SPAWN SERVER: Cannot send failure status report for request %zu: %s",
391
+ rq->request_id, rq->cmdline);
392
}
393
394
static void spawn_server_send_status_exit(SPAWN_REQUEST *rq, int waitpid_status) {
395
struct status_report sr = {
396
+ .magic = STATUS_REPORT_MAGIC,
397
.status = STATUS_REPORT_EXITED,
398
.exited = {
399
.waitpid_status = waitpid_status,
@@ -388,7 +401,9 @@ static void spawn_server_send_status_exit(SPAWN_REQUEST *rq, int waitpid_status)
401
};
402
403
if(write(rq->sock, &sr, sizeof(sr)) != sizeof(sr))
391
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN SERVER: Cannot send exit status report");
404
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
405
+ "SPAWN SERVER: Cannot send exit status (%d) report for request %zu: %s",
406
+ waitpid_status, rq->request_id, rq->cmdline);
407
}
408
409
static void spawn_server_run_child(SPAWN_SERVER *server, SPAWN_REQUEST *rq) {
@@ -1357,8 +1372,15 @@ int spawn_server_exec_wait(SPAWN_SERVER *server __maybe_unused, SPAWN_INSTANCE *
1372
// get the result
1373
struct status_report sr = { 0 };
1374
if(read(instance->client_sock, &sr, sizeof(sr)) != sizeof(sr))
1360
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN PARENT: failed to receive final status report for child %d, request %zu", instance->child_pid, instance->request_id);
1375
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1376
+ "SPAWN PARENT: failed to read final status report for child %d, request %zu",
1377
+ instance->child_pid, instance->request_id);
1378
1379
+ else if(sr.magic != STATUS_REPORT_MAGIC) {
1380
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1381
+ "SPAWN PARENT: invalid final status report for child %d, request %zu (invalid magic %#x in response)",
1382
+ instance->child_pid, instance->request_id, sr.magic);
1383
+ }
1384
else switch(sr.status) {
1385
case STATUS_REPORT_EXITED:
1386
rc = sr.exited.waitpid_status;
@@ -1368,7 +1390,9 @@ int spawn_server_exec_wait(SPAWN_SERVER *server __maybe_unused, SPAWN_INSTANCE *
1390
case STATUS_REPORT_FAILED:
1391
default:
1392
errno = 0;
1371
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN PARENT: invalid status report to exec spawn request %zu for pid %d (status = %u)", instance->request_id, instance->child_pid, sr.status);
1393
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1394
+ "SPAWN PARENT: invalid status report to exec spawn request %zu for pid %d (status = %u)",
1395
+ instance->request_id, instance->child_pid, sr.status);
1396
break;
1397
}
1398
@@ -1431,7 +1455,16 @@ SPAWN_INSTANCE* spawn_server_exec(SPAWN_SERVER *server, int stderr_fd, int custo
1455
1456
struct status_report sr = { 0 };
1457
if(read(instance->client_sock, &sr, sizeof(sr)) != sizeof(sr)) {
1434
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN PARENT: Failed to exec spawn request %zu (cannot get initial status report)", request.request_id);
1458
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1459
+ "SPAWN PARENT: Failed to exec spawn request %zu (cannot get initial status report)",
1460
+ request.request_id);
1461
+ goto cleanup;
1462
+ }
1463
+
1464
+ if(sr.magic != STATUS_REPORT_MAGIC) {
1465
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1466
+ "SPAWN PARENT: Failed to exec spawn request %zu (invalid magic %#x in response)",
1467
+ request.request_id, sr.magic);
1468
goto cleanup;
1469
}
1470
@@ -1442,13 +1475,17 @@ SPAWN_INSTANCE* spawn_server_exec(SPAWN_SERVER *server, int stderr_fd, int custo
1475
1476
case STATUS_REPORT_FAILED:
1477
errno = sr.failed.err_no;
1445
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN PARENT: Failed to exec spawn request %zu (check errno #1)", request.request_id);
1478
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1479
+ "SPAWN PARENT: Failed to exec spawn request %zu (server reports failure, errno is updated)",
1480
+ request.request_id);
1481
errno = 0;
1482
break;
1483
1484
case STATUS_REPORT_EXITED:
1485
errno = ENOEXEC;
1451
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "SPAWN PARENT: Failed to exec spawn request %zu (check errno #2)", request.request_id);
1486
+ nd_log(NDLS_COLLECTORS, NDLP_ERR,
1487
+ "SPAWN PARENT: Failed to exec spawn request %zu (server reports exit, errno is updated)",
1488
+ request.request_id);
1489
errno = 0;
1490
break;
1491