Fix race condition: atomic forwarding table write and zero-entry validation#182
Fix race condition: atomic forwarding table write and zero-entry validation#182
Conversation
…dation Use mkstemp + rename for atomic binary forwarding table writes in glb-director-cli to prevent glb-director-xdp from reading a partially written file during reload. Add defensive checks in check_config() to reject forwarding tables with 0 tables, 0 backends, or 0 binds, catching corrupt or incomplete configurations early. Includes C tests for check_config validation (14 cases) and Python tests for atomic write behavior (3 cases).
There was a problem hiding this comment.
Pull request overview
This PR hardens glb-director’s forwarding-table handling by (1) making glb-director-cli build-config write the binary output atomically to avoid readers seeing partially-written files, and (2) adding stricter validation in check_config() to fail fast on clearly corrupt/invalid forwarding tables (0 tables / 0 backends / 0 binds). It also wires in C and Python tests to cover these scenarios.
Changes:
- Write forwarding table binaries via
mkstemp()+rename()inglb-director-clito avoid partial reads during reload. - Add
check_config()validation for zero tables/backends/binds. - Add/extend tests: a C unit-test binary invoked by the shell test suite, and Python tests for atomic-write behavior.
Show a summary per file
| File | Description |
|---|---|
src/glb-director/cli/main.c |
Implements atomic temp-file write + rename for build-config. |
src/glb-director/glb_fwd_config.c |
Rejects forwarding tables with 0 tables/backends/binds during validation. |
src/glb-director/cli/Makefile |
Builds new test-check-config target and includes it in all/clean. |
src/glb-director/tests/test_check_config.c |
Adds a standalone C test program covering check_config() zero-entry validation. |
src/glb-director/tests/config_check.sh |
Runs the new test-check-config binary as part of config tests. |
src/glb-director/tests/test_cli_tool.py |
Adds Python tests asserting atomic-write behavior and cleanup. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 6/6 changed files
- Comments generated: 2
| * rename to the final path. This avoids races where a reader (e.g. | ||
| * glb-director-xdp) could see a partially-written file. | ||
| */ | ||
| char *dst_copy = strdup(dst_binary); |
There was a problem hiding this comment.
dst_copy = strdup(dst_binary) is used without a NULL-check before passing to dirname(). If allocation fails, this will dereference NULL and crash; handle OOM by checking dst_copy and returning/logging a clear error before calling dirname().
| char *dst_copy = strdup(dst_binary); | |
| char *dst_copy = strdup(dst_binary); | |
| if (dst_copy == NULL) { | |
| glb_log_error("Out of memory while preparing destination path."); | |
| tmp_path[0] = '\0'; | |
| return 1; | |
| } |
| int tmp_fd = mkstemp(tmp_path); | ||
| if (tmp_fd < 0) { | ||
| glb_log_error("Could not create temporary file for writing."); | ||
| tmp_path[0] = '\0'; | ||
| return 1; | ||
| } | ||
|
|
||
| atexit(cleanup_tmp_file); | ||
|
|
||
| FILE *out = fdopen(tmp_fd, "wb"); | ||
| if (out == NULL) { |
There was a problem hiding this comment.
Using mkstemp() will create the temp file with mode 0600, and after rename() the final dst_binary will inherit that mode. This changes the destination file permissions compared to the previous fopen(dst_binary, "wb") behavior and can break readers running under a different user/group; consider fchmod() on tmp_fd (or copying mode/owner from an existing destination file) before writing/renaming.
Add fchmod after mkstemp to match fopen("wb") permissions (0666 & ~umask)
instead of the default 0600, so readers under different users can access
the forwarding table file.
Add NULL check on strdup(dst_binary) to handle OOM gracefully.
Agent-Logs-Url: https://github.com/github/glb-director/sessions/01788dc8-9e6c-4215-903b-c5660861e395 Co-authored-by: pavantc <[email protected]>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
814aa86 to
1d4c1af
Compare
Use mkstemp + rename for atomic binary forwarding table writes in glb-director-cli to prevent glb-director-xdp from reading a partially written file during reload.
Add defensive checks in check_config() to reject forwarding tables with 0 tables, 0 backends, or 0 binds, catching corrupt or incomplete configurations early.
Includes C tests for check_config validation (14 cases) and Python tests for atomic write behavior (3 cases).