hardened EEPROM against out of Bounds and garbage in RAM

This commit is contained in:
2025-08-24 13:31:27 +02:00
parent 05f476bae2
commit f735ea7b0d

View File

@@ -283,9 +283,8 @@ void StoreConfig_EEPROM()
/**
* @brief Load configuration from EEPROM and validate.
*
* Performs CRC check and sanity validation and raises the respective DTCs:
* - DTC_EEPROM_CFG_BAD if CRC fails
* - DTC_EEPROM_CFG_SANITY with bitmask payload if values are out of bounds
* On CRC failure: raise DTC_EEPROM_CFG_BAD and fall back to in-RAM defaults (no writes).
* On CRC OK: run sanity with autocorrect=true and raise DTC_EEPROM_CFG_SANITY with bitmask if needed.
*/
void GetConfig_EEPROM()
{
@@ -297,12 +296,20 @@ void GetConfig_EEPROM()
const uint32_t checksum = LubeConfig.checksum;
LubeConfig.checksum = 0;
MaintainDTC(DTC_EEPROM_CFG_BAD,
(Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum));
const bool badCrc = (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum);
MaintainDTC(DTC_EEPROM_CFG_BAD, badCrc);
if (badCrc) {
// Dont keep corrupted data in RAM
LubeConfig = LubeConfig_defaults;
LubeConfig.EEPROM_Version = EEPROM_STRUCTURE_REVISION; // explicit in-RAM version
return;
}
// CRC OK → restore checksum and sanitize (with autocorrect)
LubeConfig.checksum = checksum;
const uint32_t sanity = ConfigSanityCheck(false);
const uint32_t sanity = ConfigSanityCheck(true);
MaintainDTC(DTC_EEPROM_CFG_SANITY, (sanity > 0), sanity);
}
@@ -333,33 +340,48 @@ void StorePersistence_EEPROM()
*
* If the stored start address is out of range, the persistence partition is reset,
* formatted, and DTC_EEPROM_PDSADRESS_BAD is raised.
* Otherwise, the record is read and checked; DTC_EEPROM_PDS_BAD is raised on CRC failure.
* Otherwise, the record is read and checked; on CRC failure DTC_EEPROM_PDS_BAD is raised
* and the in-RAM persistence data is reset to a safe default (no writes performed here).
*/
void GetPersistence_EEPROM()
{
if (!EEPROM_Available())
return;
// Read wear-level start address
ee.readBlock(0, (uint8_t *)&globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress));
if (globals.eePersistenceAddress < startofPersistence || globals.eePersistenceAddress > ee.getDeviceSize())
const uint16_t addr = globals.eePersistenceAddress;
const uint16_t need = sizeof(PersistenceData);
const uint16_t dev = ee.getDeviceSize();
// Strict range check: addr must be within partition and block must fit into device
if (addr < startofPersistence || (uint32_t)addr + (uint32_t)need > (uint32_t)dev)
{
MovePersistencePage_EEPROM(true);
FormatPersistence_EEPROM();
MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true);
return;
}
else
// Safe to read the record
ee.readBlock(addr, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
const uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0;
const bool badCrc = (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum);
MaintainDTC(DTC_EEPROM_PDS_BAD, badCrc);
if (badCrc)
{
ee.readBlock(globals.eePersistenceAddress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
const uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0;
MaintainDTC(DTC_EEPROM_PDS_BAD,
(Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum));
PersistenceData.checksum = checksum;
// Do not keep corrupted data in RAM; leave DTC set, no EEPROM writes here
PersistenceData = {0};
return;
}
// CRC ok -> restore checksum into the struct kept in RAM
PersistenceData.checksum = checksum;
}
/**