Skip to content

Add sandbox confinement to Svc::FileManager - #5852

Open
Moferanoluwa wants to merge 1 commit into
nasa:develfrom
Moferanoluwa:fix/filemanager-sandbox-confinement
Open

Add sandbox confinement to Svc::FileManager#5852
Moferanoluwa wants to merge 1 commit into
nasa:develfrom
Moferanoluwa:fix/filemanager-sandbox-confinement

Conversation

@Moferanoluwa

Copy link
Copy Markdown
Contributor
Related Issue(s) #5849
Has Unit Tests (y/n) y
Documentation Included (y/n) y
Generative AI was used in this contribution (y/n) AI

Change Description

Svc::FileManager was the only file-handling component without optional path confinement. All nine of its command handlers (CreateDirectory, RemoveFile, MoveFile, RemoveDirectory, AppendFile, FileSize, ListDirectory, CalculateCrc, GenerateDp) passed ground-supplied paths straight to Os::FileSystem/Os::File/Os::Directory, and the FileHandling subtopology's sandboxDir knob did not cover it.

  • Added FileManager::configure(sandboxDir), fail-closed like FileUplink/FileDownlink/PrmDb. Since FileManager doesn't go through Os::File uniformly (most handlers call Os::FileSystem statics or Os::Directory directly), it validates paths itself via a new private checkSandbox() helper built on Os::FilePathUtils::resolveFromCwd + checkContainment, rather than wrapping Os::SandboxedFile (which only covers Os::File::open).
  • Every path argument is checked, including both legs of MoveFile/AppendFile (both are checked independently, not short-circuited, so a violation on either side is reported) and the per-entry path ListDirectory constructs while walking a directory (defense in depth against a platform that yields a ./.. entry — POSIX's Os::Directory already filters these, but the check doesn't assume that). Rejections emit a new PathOutsideSandbox warning event. RemoveFile's ignoreErrors flag only waives missing-file errors, not the sandbox check.
  • Extracted Os::FilePathUtils::resolveDirectory() (resolve + ensure trailing /) out of Os::SandboxedFile::configure() so FileManager::configure() doesn't reimplement that logic.
  • FileHandling now configures fileManager's sandbox to FileHandlingConfig::Paths::sandboxDir ("/" by default) alongside its siblings, and Ref reconfigures it to "." like fileUplink/fileDownlink/prmDb.

Rationale

Fixes #5849. A deployment that sets FileHandlingConfig::Paths::sandboxDir (or reconfigures it) to restrict file access could reasonably believe the whole FileHandling subtopology is confined, when FileManager's command set — which can create/remove/move/append/CRC any path, and package arbitrary files into data products — was not.

Testing/Review Recommendations

Added to Svc/FileManager/test/ut: fail-closed-by-default rejection, an escaping absolute path rejected on a single-path command, a path inside the configured sandbox still succeeding, both legs of MoveFile reported independently when both escape, ignoreErrors=true not bypassing the check on RemoveFile, and the three structurally distinct code paths (ListDirectory's async open, GenerateDp's always-OK-response convention, CalculateCrc's direct Os::File use). Also added test_file_manager_sandbox to the Ref integration suite, mirroring the existing test_prm_db_sandbox.

This dev environment can't natively build F' (no Windows platform support in the CMake build), so I set up WSL Ubuntu to verify:

  • Os_FilePathUtils_Test (24/24) and Os_SandboxedFile_Test (11/11) still pass after extracting resolveDirectory().
  • Svc_FileManager_ut_exe (36/36, all pre-existing tests plus the 8 new sandbox tests) passes.
  • The Ref deployment builds and links cleanly end-to-end, which exercises both the FileHandling.fpp configComponents phase change and the RefTopology.cpp wiring (these aren't touched by a component-level fprime-util check, so this was the only way to compile-check them).

I did not run the new test_file_manager_sandbox Ref integration test itself — that needs fprime-gds, which isn't set up in this environment. It follows the same pattern as test_prm_db_sandbox immediately above it in the same file, which does pass in CI.

Future Work

None.

AI Usage (see policy)

  • Tool: Claude Code (Claude Opus)
  • Type: Traced the confinement gap through the sibling components (FileUplink, FileDownlink, PrmDb) and the recent Os::SandboxedFile fail-closed rework (Keep Os::SandboxedFile fail-closed, default subtopology sandboxes to "/", sandbox PrmDb whole-component, restrict Ref to "." #5833), designed and implemented the fix, wrote the unit/integration tests, and verified the build in WSL since this machine can't natively build F'.
  • Scope: FileManager, Os::FilePathUtils/Os::SandboxedFile (extracted a shared helper, no behavior change there), FileHandling subtopology wiring, Ref topology/integration test.
  • Level of modification: I reviewed and take responsibility for every line; verification was via the actual test suite and a full deployment build, not just code reading.

IAMAI

Fixes nasa#5849. FileManager was the only file-handling component
without optional path confinement: every command handler passed its
ground-supplied path straight to Os::FileSystem/Os::File/Os::Directory, and
the FileHandling subtopology's sandboxDir knob did not cover it, so a
deployment relying on that knob could believe FileManager's commands were
confined when they were not.

Added FileManager::configure(sandboxDir), fail-closed like FileUplink,
FileDownlink, and PrmDb (routed through Os::FileSystem/Os::Directory
directly rather than Os::SandboxedFile, since FileManager doesn't go
through Os::File uniformly). Every path argument across all nine command
handlers is validated via a shared checkSandbox() helper (Os::FilePathUtils
resolve + checkContainment) before it reaches the OSAL, including both legs
of MoveFile/AppendFile and the per-entry path ListDirectory constructs
while walking a directory; rejections emit a new PathOutsideSandbox warning.
ignoreErrors on RemoveFile does not waive the check. Extracted a shared
Os::FilePathUtils::resolveDirectory() helper (resolve + trailing slash) so
SandboxedFile and FileManager don't each reimplement it.

FileHandling now configures fileManager to sandboxDir ("/" by default, for
backwards compatibility) alongside its siblings, and Ref reconfigures it to
"." like fileUplink/fileDownlink/prmDb.

Testing: added unit tests covering the fail-closed default, escaping paths,
ignoreErrors not bypassing the check, MoveFile's independent per-leg
reporting, and the distinct ListDirectory/GenerateDp/CalculateCrc code
paths, plus a Ref integration test mirroring test_prm_db_sandbox. Verified
via a full WSL build: Os_FilePathUtils_Test, Os_SandboxedFile_Test, and
Svc_FileManager_ut_exe all pass, and the Ref deployment (which exercises
the FileHandling.fpp phase change and the RefTopology.cpp wiring) builds
and links cleanly. Did not run the new Ref integration test itself
(requires fprime-gds, not available in this environment).

AI-assisted development (Claude Code) — I traced the gap through the
sibling components, designed and implemented the fix and tests myself,
verified the build and unit tests in a WSL environment since this dev
machine can't natively build F', and take responsibility for every line.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Svc::FileManager lacks the optional sandbox confinement its sibling file components have; FileHandling sandboxDir does not cover it

1 participant