Skip to content

Commit

Permalink
Fix #2550, Use resource ID for validation index
Browse files Browse the repository at this point in the history
Use a resourceID value for access into the validation result
structure array.  This allows for consistent lookup, matching,
and free/in-use determination, as well as improved resilience
to race conditions and stale data.
  • Loading branch information
jphickey committed Apr 19, 2024
1 parent 28a5820 commit 1272f6d
Show file tree
Hide file tree
Showing 12 changed files with 1,000 additions and 330 deletions.
8 changes: 8 additions & 0 deletions modules/resourceid/fsw/inc/cfe_core_resourceid_basevalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ enum

/* configuration registry */
CFE_RESOURCEID_CONFIGID_BASE_OFFSET = OS_OBJECT_TYPE_USER + 7,

/* TBL managed resources */
CFE_RESOURCEID_TBL_VALRESULTID_BASE_OFFSET = OS_OBJECT_TYPE_USER + 8,

};

/*
Expand All @@ -92,6 +96,10 @@ enum

/* configuration registry */
CFE_CONFIGID_BASE = CFE_RESOURCEID_MAKE_BASE(CFE_RESOURCEID_CONFIGID_BASE_OFFSET),

/* TBL managed resources */
CFE_TBL_VALRESULTID_BASE = CFE_RESOURCEID_MAKE_BASE(CFE_RESOURCEID_TBL_VALRESULTID_BASE_OFFSET),

};

/** @} */
Expand Down
138 changes: 50 additions & 88 deletions modules/tbl/fsw/src/cfe_tbl_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,128 +839,90 @@ CFE_Status_t CFE_TBL_ReleaseAddresses(uint16 NumTables, const CFE_TBL_Handle_t T
*-----------------------------------------------------------------*/
CFE_Status_t CFE_TBL_Validate(CFE_TBL_Handle_t TblHandle)
{
CFE_TBL_TxnState_t Txn;
int32 Status;
CFE_ES_AppId_t ThisAppId;
CFE_TBL_RegistryRec_t *RegRecPtr;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};
CFE_TBL_TxnState_t Txn;
int32 Status;
CFE_TBL_RegistryRec_t * RegRecPtr;
char AppName[OS_MAX_API_NAME] = {"UNKNOWN"};
CFE_TBL_LoadBuff_t * BuffPtr;
CFE_TBL_ValidationResult_t *ResultPtr;
const char * LogTagStr;

ResultPtr = NULL;
BuffPtr = NULL;
LogTagStr = "(none)";

/* Verify that this application has the right to perform operation */
Status = CFE_TBL_TxnStartFromHandle(&Txn, TblHandle, CFE_TBL_TxnContext_OWNER_APP);

ThisAppId = CFE_TBL_TxnAppId(&Txn);

if (Status == CFE_SUCCESS)
{
/* Get pointers to pertinent records in registry and handles */
RegRecPtr = CFE_TBL_TxnRegRec(&Txn);

CFE_TBL_TxnFinish(&Txn);

CFE_ES_GetAppName(AppName, ThisAppId, sizeof(AppName));

/* Identify the image to be validated, starting with the Inactive Buffer */
if (RegRecPtr->ValidateInactiveIndex != CFE_TBL_NO_VALIDATION_PENDING)
ResultPtr = CFE_TBL_CheckValidationRequest(&RegRecPtr->ValidateInactiveId);
if (ResultPtr != NULL)
{
LogTagStr = "inactive";
BuffPtr = CFE_TBL_GetInactiveBuffer(RegRecPtr);
}
else
{
/* Identify whether the Inactive Buffer is a shared buffer or a dedicated one */
if (RegRecPtr->DoubleBuffered)
ResultPtr = CFE_TBL_CheckValidationRequest(&RegRecPtr->ValidateActiveId);
if (ResultPtr != NULL)
{
/* Call the Application's Validation function for the Inactive Buffer */
Status =
(RegRecPtr->ValidationFuncPtr)(RegRecPtr->Buffers[(1U - RegRecPtr->ActiveBufferIndex)].BufferPtr);

/* Allow buffer to be activated after passing validation */
if (Status == CFE_SUCCESS)
{
RegRecPtr->Buffers[(1U - RegRecPtr->ActiveBufferIndex)].Validated = true;
}
LogTagStr = "active";
BuffPtr = CFE_TBL_GetActiveBuffer(RegRecPtr);
}
else
{
/* Call the Application's Validation function for the appropriate shared buffer */
Status = (RegRecPtr->ValidationFuncPtr)(CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].BufferPtr);
}

/* Allow buffer to be activated after passing validation */
if (Status == CFE_SUCCESS)
{
CFE_TBL_Global.LoadBuffs[RegRecPtr->LoadInProgress].Validated = true;
}
}
CFE_TBL_TxnFinish(&Txn);

if (Status == CFE_SUCCESS)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_VALIDATION_INF_EID, CFE_EVS_EventType_INFORMATION,
CFE_TBL_Global.TableTaskAppId, "%s validation successful for Inactive '%s'",
AppName, RegRecPtr->Name);
}
else
if (ResultPtr != NULL)
{
if (BuffPtr == NULL)
{
CFE_EVS_SendEventWithAppID(CFE_TBL_VALIDATION_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId,
"%s validation failed for Inactive '%s', Status=0x%08X", AppName,
RegRecPtr->Name, (unsigned int)Status);

if (Status > CFE_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: App(%lu) Validation func return code invalid (Stat=0x%08X) for '%s'\n",
__func__, CFE_RESOURCEID_TO_ULONG(CFE_TBL_Global.TableTaskAppId),
(unsigned int)Status, RegRecPtr->Name);
}
/* No buffer, it cannot be valid */
ResultPtr->Result = -1;
}

/* Save the result of the Validation function for the Table Services Task */
CFE_TBL_Global.ValidationResults[RegRecPtr->ValidateInactiveIndex].Result = Status;

/* Once validation is complete, set flags to indicate response is ready */
CFE_TBL_Global.ValidationResults[RegRecPtr->ValidateInactiveIndex].State = CFE_TBL_VALIDATION_PERFORMED;
RegRecPtr->ValidateInactiveIndex = CFE_TBL_NO_VALIDATION_PENDING;

/* Since the validation was successfully performed (although maybe not a successful result) */
/* return a success status */
Status = CFE_SUCCESS;
}
else if (RegRecPtr->ValidateActiveIndex != CFE_TBL_NO_VALIDATION_PENDING)
{
/* Perform validation on the currently active table buffer */
/* Identify whether the Active Buffer is a shared buffer or a dedicated one */
if (RegRecPtr->DoubleBuffered)
else if (RegRecPtr->ValidationFuncPtr == NULL)
{
/* Call the Application's Validation function for the Dedicated Active Buffer */
Status = (RegRecPtr->ValidationFuncPtr)(RegRecPtr->Buffers[RegRecPtr->ActiveBufferIndex].BufferPtr);
/* no validation function, assume its OK */
ResultPtr->Result = 0;
}
else
{
/* Call the Application's Validation function for the static buffer */
Status = (RegRecPtr->ValidationFuncPtr)(RegRecPtr->Buffers[0].BufferPtr);
/* Save the result of the Validation function for the Table Services Task */
ResultPtr->Result = (RegRecPtr->ValidationFuncPtr)(BuffPtr->BufferPtr);
}

if (Status == CFE_SUCCESS)
/* Get the app name for logging */
CFE_ES_GetAppName(AppName, CFE_TBL_TxnAppId(&Txn), sizeof(AppName));

/* Allow buffer to be activated after passing validation */
if (ResultPtr->Result == 0)
{
BuffPtr->Validated = true;
CFE_EVS_SendEventWithAppID(CFE_TBL_VALIDATION_INF_EID, CFE_EVS_EventType_INFORMATION,
CFE_TBL_Global.TableTaskAppId, "%s validation successful for Active '%s'",
AppName, RegRecPtr->Name);
CFE_TBL_Global.TableTaskAppId, "%s validation successful for %s '%s'",
AppName, LogTagStr, RegRecPtr->Name);
}
else
{
CFE_EVS_SendEventWithAppID(CFE_TBL_VALIDATION_ERR_EID, CFE_EVS_EventType_ERROR,
CFE_TBL_Global.TableTaskAppId,
"%s validation failed for Active '%s', Status=0x%08X", AppName,
RegRecPtr->Name, (unsigned int)Status);
"%s validation failed for %s '%s', Status=0x%08X", AppName, RegRecPtr->Name,
LogTagStr, (unsigned int)Status);

if (Status > CFE_SUCCESS)
if (ResultPtr->Result > 0)
{
CFE_ES_WriteToSysLog("%s: App(%lu) Validation func return code invalid (Stat=0x%08X) for '%s'\n",
__func__, CFE_RESOURCEID_TO_ULONG(CFE_TBL_Global.TableTaskAppId),
(unsigned int)Status, RegRecPtr->Name);
(unsigned int)ResultPtr->Result, RegRecPtr->Name);
}
}

/* Save the result of the Validation function for the Table Services Task */
CFE_TBL_Global.ValidationResults[RegRecPtr->ValidateActiveIndex].Result = Status;

/* Once validation is complete, reset the flags */
CFE_TBL_Global.ValidationResults[RegRecPtr->ValidateActiveIndex].State = CFE_TBL_VALIDATION_PERFORMED;
RegRecPtr->ValidateActiveIndex = CFE_TBL_NO_VALIDATION_PENDING;
/* Once validation is complete, set flags to indicate response is ready */
ResultPtr->State = CFE_TBL_VALIDATION_PERFORMED;

/* Since the validation was successfully performed (although maybe not a successful result) */
/* return a success status */
Expand All @@ -973,8 +935,8 @@ CFE_Status_t CFE_TBL_Validate(CFE_TBL_Handle_t TblHandle)
}
else
{
CFE_ES_WriteToSysLog("%s: App(%lu) does not have access to Tbl Handle=%d\n", __func__,
CFE_RESOURCEID_TO_ULONG(ThisAppId), (int)TblHandle);
CFE_ES_WriteToSysLog("%s: App(%lu) does not have access to Tbl Handle=%lu\n", __func__,
CFE_TBL_TxnAppIdAsULong(&Txn), CFE_TBL_TxnHandleAsULong(&Txn));
}

return Status;
Expand Down
Loading

0 comments on commit 1272f6d

Please sign in to comment.