fix(config): stop sourcing files in unmarked configs/ subdirectories
sourceScanFiles sourced every file two levels deep under configs/, and sourcing means executing. A directory used there as ordinary storage therefore turned its contents into a script. storageIndexSet caches an app -> root TSV at configs/storage/app_locations, with no .category marker alongside it. Every line is `<slug><TAB><path>`, which bash reads as a command and its argument. That stayed invisible while no slug matched a real executable — and became a fork bomb the moment the index recorded the app named `libreportal`, because that IS the CLI on PATH: sourcing ran `libreportal /libreportal-containers`, which re-entered the same scan, which sourced the file again, one process pair per level until the host died of OOM. Every CLI invocation on the box detonated it, the task processor's own poll included, so the machine black-screened out of memory minutes after each boot. Files in a SUBDIRECTORY are now sourced only when that directory carries .category — the contract commandReloadConfigs already enforces in the CLI wrapper, and one every real config category (webui, general, security, backup, network) already satisfies. Files directly in configs/ are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8b5e02c760
commit
928e244696
@ -15,12 +15,38 @@ sourceScanFiles()
|
||||
if [ -f "$file" ]; then
|
||||
local filename=$(basename "$file")
|
||||
local should_load=true
|
||||
|
||||
|
||||
# Skip .category files and excluded files
|
||||
if [[ "$file" =~ \.category$ ]] || [[ "$filename" == "app_categories" ]]; then
|
||||
should_load=false
|
||||
fi
|
||||
|
||||
|
||||
# A file in a SUBDIRECTORY is only sourced when that directory is
|
||||
# a declared config category (carries .category) — the same
|
||||
# contract commandReloadConfigs enforces in the CLI wrapper.
|
||||
#
|
||||
# Sourcing means EXECUTING, so an unmarked directory used as
|
||||
# ordinary storage turned its contents into a script. That is not
|
||||
# hypothetical: storageIndexSet caches an app -> root TSV at
|
||||
# configs/storage/app_locations, no .category alongside it. Every
|
||||
# line there is `<slug><TAB><path>`, which bash reads as a command
|
||||
# and its argument. Harmless while no slug matched a real
|
||||
# executable — and a fork bomb the moment the row was for the app
|
||||
# named `libreportal`, because that IS the CLI: sourcing ran
|
||||
# `libreportal /libreportal-containers`, which re-entered this
|
||||
# scan, which sourced the file again, one process pair per level
|
||||
# until the host died of OOM. Every CLI invocation on the box,
|
||||
# including the task processor's own, detonated it.
|
||||
#
|
||||
# Depth-1 files (directly in configs/) keep loading as before —
|
||||
# only the category dirs gained a marker requirement.
|
||||
if [ "$should_load" = true ]; then
|
||||
local parent_dir="${file%/*}"
|
||||
if [[ "$parent_dir" != "${folder_dir%/}" && ! -f "$parent_dir/.category" ]]; then
|
||||
should_load=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$should_load" = true ]; then
|
||||
source "$file"
|
||||
# echo "$load_type NEW FILE $file"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user