Fault Injection for Firmware: Corrupt the Sensor and Confirm It Notices
Corrupt a sensor value, force an error return, flip a bit, drop a packet, delay an interrupt, and confirm the system detects it. This is the MCAS lesson, ISO 26262 makes it highly recommended at ASIL D, and Renode and QEMU let you run the campaign without hardware.
Fault Injection for Firmware: Corrupt the Sensor and Confirm It Notices
The short answer. Deliberately introduce the fault the system is supposed to tolerate and confirm it notices. Corrupt a sensor value, force an error return, flip a bit, drop a packet, delay an interrupt. ISO 26262 makes it highly recommended at ASIL D, and simulation lets it run on every commit instead of on a bench.
The part of firmware least likely to work
Error handling is the code least likely to have executed since it was written.
The happy path runs constantly, in every test, every demo, every hour in the field. The error path runs when something goes wrong, which by design is rare, which means it may never have run at all outside the afternoon somebody wrote it. And it was written under the worst conditions for correctness: at the end of a task, about a situation the author was imagining rather than observing.
That is the code fault injection targets. Not the logic. The handling.
What to inject
Corrupt a sensor value. Out of range. Stuck at a constant, which is the common real failure and the one nobody tests, because a stuck sensor is producing perfectly valid readings. Physically implausible rate of change. And the single bad reading, which is the MCAS case exactly.
Force an error return from every call that can fail. Including, especially, the ones whose return value the current code ignores. Those are findings before you even run anything.
Flip a bit in memory or in a transferred buffer.
Drop a packet, duplicate a packet, deliver packets out of order. Duplication is the one that catches idempotency assumptions nobody wrote down.
Delay an interrupt, or deliver it inside the window the code assumes is uninterrupted. The Therac-25's race condition lived in exactly this class, reachable when an operator edited parameters within roughly an eight second window.
Remove a guarantee the design depends on and see whether anything notices. This is the architectural form and the most underused. The Therac-25 removed hardware interlocks that its reused software assumed were present, and no test at any level would have found that without somebody first noticing the assumption existed.
What the standards require
ISO 26262 Part 6 covers software unit testing, and fault injection testing is a recommended method that becomes highly recommended at ASIL D for software unit and integration testing.
The hardware side shows how seriously the top level takes it. Single Point Fault Metric at or above 99 percent at ASIL D, so only roughly 1 percent residual single point faults are permitted, and it is assessed through fault injection campaigns. Latent Fault Metric at or above 90 percent.
Those are quantitative targets that cannot be met by inspection, which is why the assessment method is injection rather than review.
State the confidence honestly: the structure of these obligations is well established, while the exact table wording is drawn from summaries rather than the primary text, which is paywalled.
Why a standards body mandates breaking things
Because the alternative has a poor record.
The alternative is analysis: reasoning that a fault would be detected, writing that reasoning down, and treating the document as the verification. MCAS is the current reference case. A hazard classification was recorded, it implied a redundancy requirement, the requirement was not met, and nobody asked the aircraft.
Fault injection converts an assumption about detection into an observation of detection. Those are different epistemic acts and only one of them is evidence. That is the whole reason the standard names the method rather than the goal.
Running it without hardware
This is the practical obstacle, and it has a practical answer, because a campaign that needs a bench and a person does not run on every commit, and a campaign that does not run on every commit stops being a control and becomes an event.
Renode simulates MCUs, peripherals and sensors, and has been integrated with AFL++ to fuzz Zephyr and Contiki-NG firmware. So corrupted sensor values and protocol stack fuzzing can run in CI, on simulated hardware, on every change.
QEMU supports emulation-based fuzzing. One caveat worth knowing before you spend a day on it: AddressSanitizer and MemorySanitizer are generally incompatible with QEMU user mode, and QASan is the known workaround.
Where to start
Enumerate the inputs. Every sensor, every packet source, every interrupt, every call that can return an error. The list is finite and usually shorter than people expect, and building it is often the first day's finding on its own, because it surfaces inputs nobody had classified as inputs.
For each one, write the negative control. Drive the bad case, assert that the system detects it. Not that it survives: that it notices. A system that sails through an injected fault without registering it has failed the test, and this is the most common way a fault injection campaign gets misread as a pass.
Start with the safety-relevant path and any single point of failure the architecture depends on. That is the MCAS lesson, and unidentified single points of failure are a named red flag in technical diligence for the same reason.
The general argument is in a test that has never failed is a decoration, the case that motivates it in MCAS, and to work out which failure modes your current tests actually cover, the failure mode coverage tool.
FAQ
What is fault injection testing in firmware? Deliberately corrupting sensor values, forcing error returns, flipping bits, dropping packets and delaying interrupts to confirm the system detects and handles them, rather than reasoning that it would.
Is fault injection required by any standard? ISO 26262 makes it highly recommended at ASIL D for software unit and integration testing, and sets a Single Point Fault Metric at or above 99 percent there, assessed through fault injection campaigns.
How do I run fault injection without hardware? Renode simulates MCUs, peripherals and sensors and has been integrated with AFL++ for Zephyr and Contiki-NG. QEMU supports emulation-based fuzzing, though ASan and MSan are generally incompatible with QEMU user mode.
What faults should I inject first? Anything on a safety-relevant path, and any single point of failure the architecture depends on. Also every call whose error return the current code ignores, which is a finding before you run anything.
What counts as passing? Detection, not survival. A system that continues through an injected fault without noticing it has failed the test, and this is the most common way a campaign is misread as a pass.
Tell us the system, the stakes, and the date that matters. You get a straight technical reply from the person who would lead the work, within 24 hours.
Bring us the program