From c78a21de576f4b2d11d5cd2a518df412eb435330 Mon Sep 17 00:00:00 2001 From: TapTap Date: Sun, 13 Sep 2026 10:38:21 +0200 Subject: [PATCH] docs(shared): clarify authorized_root accessor contracts Document on utils_get_authorized_root_path() that the returned pointer is borrowed and invalidated by the next authorized-root setter, that the fd and path are not read atomically (non-reentrant), and that the fd remains caller-owned. Add a matching single-threaded/set-before-threads note at the accessor definitions in utils.c. In server.c, drop the redundant utils_set_authorized_root(-1, NULL) after a failed utils_set_authorized_root(): the setter already fail-closes the state on allocation failure. The following close(root_fd) is unchanged. --- src/server/server.c | 2 +- src/shared/utils.c | 3 +++ src/shared/utils.h | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/server/server.c b/src/server/server.c index 1eb1e8d..9728500 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -231,7 +231,7 @@ static bool configure_authorization(const char* root) { return false; } if (!utils_set_authorized_root(root_fd, resolved)) { - utils_set_authorized_root(-1, NULL); + /* The setter already cleared the fd/path state on allocation failure. */ close(root_fd); return false; } diff --git a/src/shared/utils.c b/src/shared/utils.c index 6ab725a..64a5581 100644 --- a/src/shared/utils.c +++ b/src/shared/utils.c @@ -36,6 +36,9 @@ void utils_set_authorized_root_fd(int fd) { (void)utils_set_authorized_root(fd, NULL); } +/* Accessors for the process-global authorized root. The path pointer is + * borrowed and valid until the next setter call; the root is a single-threaded, + * set-before-worker-threads value (see server.c), so these carry no locking. */ int utils_get_authorized_root_fd(void) { return authorized_root_fd; } diff --git a/src/shared/utils.h b/src/shared/utils.h index 7ac9059..ff83ac0 100644 --- a/src/shared/utils.h +++ b/src/shared/utils.h @@ -131,7 +131,15 @@ void utils_set_authorized_root_fd(int fd); * site consumes the single shared state instead of keeping its own copy. The * fd is caller-owned (see the setters): it is returned verbatim, never dup'd, * and the caller that opened it is responsible for closing it. With no root - * configured the fd accessor returns -1 and the path accessor returns NULL. */ + * configured the fd accessor returns -1 and the path accessor returns NULL. + * + * The pointer returned by utils_get_authorized_root_path() is borrowed into + * process-global state and is invalidated by the next + * utils_set_authorized_root() / utils_set_authorized_root_fd() call. The fd + * and path are stored separately and read independently, so the pair is NOT + * observed atomically together; the accessors are non-reentrant and callers + * must serialize configuration (the server installs the root before any worker + * threads spawn; see utils.c). */ int utils_get_authorized_root_fd(void); const char* utils_get_authorized_root_path(void); /* True when `path` is `root` itself or lies directly beneath it: a lexical