Skip to content

fm: handle all CFE_TBL_GetAddress failure codes (not just NEVER_LOADED)#143

Open
nurdymuny wants to merge 7 commits into
nasa:mainfrom
nurdymuny:scj-hardening-tbl-getaddress-errors
Open

fm: handle all CFE_TBL_GetAddress failure codes (not just NEVER_LOADED)#143
nurdymuny wants to merge 7 commits into
nasa:mainfrom
nurdymuny:scj-hardening-tbl-getaddress-errors

Conversation

@nurdymuny

Copy link
Copy Markdown

Summary

Three call sites in FM check only Status == CFE_TBL_ERR_NEVER_LOADED after CFE_TBL_GetAddress() and dereference FM_AppData.MonitorTablePtr in the else branch. Per cfe_tbl.h, the pointer is undefined on any of the other four documented failure codes — CFE_TBL_ERR_INVALID_HANDLE, CFE_TBL_ERR_NO_ACCESS, CFE_ES_ERR_RESOURCEID_NOT_VALID, CFE_TBL_BAD_ARGUMENT — so those paths reach an undefined-pointer deref.

Affected sites:

File Function Behaviour on non-NEVER_LOADED error
fsw/src/fm_cmds.c FM_MonitorFilesystemSpaceCmd (line 855) reads FM_AppData.MonitorTablePtr->Entries
fsw/src/fm_cmds.c FM_SetTableStateCmd (line 967) reads FM_AppData.MonitorTablePtr->Entries[Index].Type and writes .Enabled
fsw/src/fm_table_utils.c FM_AcquireTablePointers (line 206) leaves stale pointer for later callers

This is the same defense-in-depth shape as nasa/MM#116 (DataSize switch with no default case) — a switch / if that covers some but not all of the failure modes of an upstream API.

Change

At all three sites, invert the predicate: only CFE_SUCCESS and CFE_TBL_INFO_UPDATED are documented to set the pointer; everything else NULLs it (and for the two command handlers, also flips CommandResult false and emits the existing *_TBL_ERR_EID error event so the ground operator sees the failure).

- if (Status == CFE_TBL_ERR_NEVER_LOADED)
+ if (Status != CFE_SUCCESS && Status != CFE_TBL_INFO_UPDATED)

Provenance

Surfaced by scj-hunt + Gigi ATTEND on a fresh ingest of FM v1.2.0 into the cfs_apps_fm_v01 fiber bundle. FM_SetTableStateCmd was the rank-1 hit at risk_score 8.8; drilling its structural twins surfaced the matching pattern in the other two sites. scj-hunt is open source at nurdymuny/shadow-clone-jutsu.

Test plan

  • Build under existing CI (no new symbols, no new headers)
  • Mock-fault CFE_TBL_GetAddress with CFE_TBL_ERR_INVALID_HANDLE, observe FM_SET_TABLE_STATE_TBL_ERR_EID / FM_GET_FREE_SPACE_TBL_ERR_EID emitted instead of the prior undefined-pointer deref. Happy to add a unit test for this if reviewers want.

🤖 Generated with Claude Code

jphickey and others added 7 commits May 13, 2026 09:10
Reset MISSION_REV to 0xFF and build number to 1.
…use-updated-static-analysis-workflow

Part cFS/workflows#129, Use Updated Static Analysis Workflow
…fm-table-utils

Fix nasa#139, Suppressed ignored return value warning for CFE_TBL_Load() in FM_TableInit()
Per `cfe_tbl.h`, `CFE_TBL_GetAddress` leaves the table pointer
*undefined* on any non-success return.  The documented return set is:

  - CFE_SUCCESS                       --  pointer set
  - CFE_TBL_INFO_UPDATED              --  pointer set (info code)
  - CFE_TBL_ERR_NEVER_LOADED          --  pointer undefined
  - CFE_TBL_ERR_INVALID_HANDLE        --  pointer undefined
  - CFE_TBL_ERR_NO_ACCESS             --  pointer undefined
  - CFE_ES_ERR_RESOURCEID_NOT_VALID   --  pointer undefined
  - CFE_TBL_BAD_ARGUMENT              --  pointer undefined

Three call sites in FM check only `Status == CFE_TBL_ERR_NEVER_LOADED`
and dereference `FM_AppData.MonitorTablePtr` in the `else` branch.
On any of the other four failure codes (e.g. a table handle that
became invalid after a registration churn, or an access-denied caused
by an ownership change) the dereference reads an undefined pointer.

  - fm_cmds.c          FM_MonitorFilesystemSpaceCmd  ( line ~865 )
  - fm_cmds.c          FM_SetTableStateCmd            ( line ~977 )
  - fm_table_utils.c   FM_AcquireTablePointers        ( line ~216 )

Invert the check at all three sites: the only safe states are
`CFE_SUCCESS` and `CFE_TBL_INFO_UPDATED`; everything else NULLs the
pointer (and for the two command handlers also sets `CommandResult`
false and emits the existing `*_TBL_ERR_EID` error event so the
ground operator sees the failure).

Same defense-in-depth shape as nasa/MM#116 (DataSize switch with no
default case).

Surfaced by scj-hunt + Gigi ATTEND on a fresh ingest of FM v1.2.0
into the `cfs_apps_fm_v01` fiber bundle.  `FM_SetTableStateCmd` was
the rank-1 hit at risk_score 8.8; drilling its structural twins via
the ATTEND query surfaced the matching pattern in the other two
sites.

No new tests added -- the trigger path requires injecting a
non-NEVER_LOADED error from `CFE_TBL_GetAddress`, which would need
either a mock or a test bench that can fault the handle.  Happy to
add one if reviewers want.
@nurdymuny

Copy link
Copy Markdown
Author

FYI to reviewers: while sweeping the other cFS apps for the same shape, I found that nasa/CF::CF_CheckTables (cf_app.c:48) addresses the identical concern with an inline comment block explaining the multi-success-code issue and uses

if (status < CFE_SUCCESS) { /* error */ }

(negative-only check) on the basis that cFE convention is "alt-success codes are positive, errors are negative".

If you'd prefer that idiom over the explicit allow-list in this PR (Status != CFE_SUCCESS && Status != CFE_TBL_INFO_UPDATED), I'm happy to switch. CF's approach is shorter and more future-proof against new info codes; the explicit allow-list is more conservative about what it accepts.

Sister PR with the same root cause: nasa/SC#170.

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.

5 participants