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. * @brief Load configuration from EEPROM and validate.
* *
* Performs CRC check and sanity validation and raises the respective DTCs: * On CRC failure: raise DTC_EEPROM_CFG_BAD and fall back to in-RAM defaults (no writes).
* - DTC_EEPROM_CFG_BAD if CRC fails * On CRC OK: run sanity with autocorrect=true and raise DTC_EEPROM_CFG_SANITY with bitmask if needed.
* - DTC_EEPROM_CFG_SANITY with bitmask payload if values are out of bounds
*/ */
void GetConfig_EEPROM() void GetConfig_EEPROM()
{ {
@@ -297,12 +296,20 @@ void GetConfig_EEPROM()
const uint32_t checksum = LubeConfig.checksum; const uint32_t checksum = LubeConfig.checksum;
LubeConfig.checksum = 0; LubeConfig.checksum = 0;
MaintainDTC(DTC_EEPROM_CFG_BAD, const bool badCrc = (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum);
(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; LubeConfig.checksum = checksum;
const uint32_t sanity = ConfigSanityCheck(false); const uint32_t sanity = ConfigSanityCheck(true);
MaintainDTC(DTC_EEPROM_CFG_SANITY, (sanity > 0), sanity); 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, * If the stored start address is out of range, the persistence partition is reset,
* formatted, and DTC_EEPROM_PDSADRESS_BAD is raised. * 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() void GetPersistence_EEPROM()
{ {
if (!EEPROM_Available()) if (!EEPROM_Available())
return; return;
// Read wear-level start address
ee.readBlock(0, (uint8_t *)&globals.eePersistenceAddress, sizeof(globals.eePersistenceAddress)); 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); MovePersistencePage_EEPROM(true);
FormatPersistence_EEPROM(); FormatPersistence_EEPROM();
MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true); MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true);
return;
} }
else
{ // Safe to read the record
ee.readBlock(globals.eePersistenceAddress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); ee.readBlock(addr, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
const uint32_t checksum = PersistenceData.checksum; const uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0; PersistenceData.checksum = 0;
MaintainDTC(DTC_EEPROM_PDS_BAD, const bool badCrc = (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum);
(Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum)); MaintainDTC(DTC_EEPROM_PDS_BAD, badCrc);
PersistenceData.checksum = checksum; if (badCrc)
{
// 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;
} }
/** /**