From 1e9e65225bd67d4e7c54fb3846dae3ab4c5ea08d Mon Sep 17 00:00:00 2001 From: librelad Date: Wed, 27 May 2026 01:23:55 +0100 Subject: [PATCH] fix(gluetun): wrap rm -f on dockerinstall-owned tempfiles in runFileOp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gluetun_providers.sh writes its working files ($raw, $headers) next to $output_file, which lives at containers_dir/libreportal/frontend/data/apps/generated/gluetun-providers.json — dockerinstall-owned in rootless. The five rm -f calls on those paths were unwrapped, so the manager running the script (e.g. from the task processor) would get Permission denied — same class as the updateConfigOption sed -i bug that was just fixed. $tmp comes from mktemp (/tmp), so the rm -f for it stays unwrapped. Audit context: this was the only remaining raw filesystem op against container-tree paths in any containers/*/*.sh. The rest of the container .sh files are clean — every sed -i / chmod / chown / cp / mv is already routed through runFileOp or runFileWrite, and the per-app install bodies delegate fs work to high-level helpers (dockerConfigSetupToContainer, copyResource, dockerComposeSetupFile) which themselves use the wrappers. Hooks (_migrate_pre/_post, restoreAppRunHook pre/post) are present in the framework but unused by any app today — that's by design (opt-in per-app). If a future app needs federation-key rotation post-migrate, or a hostname rewrite that the generic URL-rewrite layer doesn't cover, those slots are ready. Signed-off-by: librelad --- containers/gluetun/scripts/gluetun_providers.sh | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/containers/gluetun/scripts/gluetun_providers.sh b/containers/gluetun/scripts/gluetun_providers.sh index 9697c34..0ba17a6 100644 --- a/containers/gluetun/scripts/gluetun_providers.sh +++ b/containers/gluetun/scripts/gluetun_providers.sh @@ -36,18 +36,24 @@ appWebuiRefresh_gluetun() { -D "$headers" -o "$raw" \ -w '%{http_code}' "$upstream") || http_code="" + # $raw and $headers live next to $output_file (under containers_dir/ + # libreportal/frontend/data/, dockerinstall-owned in rootless). The + # manager can't `rm` them directly without a Permission denied — same + # class of bug as the updateConfigOption sed-i issue. runFileOp routes + # the rm through the right user. $tmp is from mktemp (/tmp), so + # `rm -f $tmp` stays unwrapped. if [[ "$http_code" == "304" ]]; then - rm -f "$raw" "$headers" + runFileOp rm -f "$raw" "$headers" return 0 fi if [[ "$http_code" != "200" ]]; then isNotice "Upstream fetch failed (${http_code:-no response}); keeping existing snapshot." - rm -f "$raw" "$headers" + runFileOp rm -f "$raw" "$headers" return 0 fi local new_etag new_etag=$(awk 'tolower($1)=="etag:"{print $2}' "$headers" | tr -d '\r') - rm -f "$headers" + runFileOp rm -f "$headers" # servers.json is a top-level object keyed by provider; each provider # entry has a `servers` array whose items have `vpn` (wireguard|openvpn), @@ -67,11 +73,12 @@ appWebuiRefresh_gluetun() { | { providers: . } ' "$raw" > "$tmp" 2>/dev/null; then isNotice "Failed to parse gluetun servers.json; keeping existing provider snapshot." - rm -f "$raw" "$tmp" + runFileOp rm -f "$raw" + rm -f "$tmp" return 0 fi - rm -f "$raw" + runFileOp rm -f "$raw" if [ -s "$tmp" ]; then runFileWrite "$output_file" < "$tmp"; rm -f "$tmp"