Fotolia_112387085_kelly marken_XXL_preview

(Bild: Fotolia/Kelly Marken)

Unser alltägliches Leben wird zunehmend von Technologien bestimmt, daher gewinnt auch die Sicherheit von Embedded-Systemen immer mehr an Bedeutung. Dieser Beitrag wirft einen kurzen Blick auf die weitverbreiteten Paradigmen rund um die Safety-orientierte Entwicklung und zeigt, wie sich der Zertifizierungsprozess beschleunigen lässt.

In der Entwicklung von Embedded-Systemen werden in erster Linie die Programmiersprachen C und C++ eingesetzt. Der Hauptgrund für die anhaltend weite Verbreitung dieser Sprachen ist die Tatsache, dass es eine breite Tool-Unterstützung gibt, die nahezu jede Embedded-Architektur abdeckt. Außerdem werden C und C++ bereits so lange genutzt, dass die Entwickler ein tiefgreifendes Verständnis für die Nuancen der Sprachen entwickelt haben. Darüber hinaus helfen viele Tools für statische Analyse dabei, potenzielle Fehler im Code zu lokalisieren und beheben. Nicht zuletzt sind die Sprachen – vor allem C – sehr flexibel, sodass der Entwickler hardwarenah Register auslesen und I/O-Leitungen umschalten oder das Verhalten zwischen Strukturen und Objekten auf höheren Ebenen betrachten kann. All dies erleichtert die tägliche Arbeit eines Entwicklers.

Wie sicher ist C?

Wenn C und C++ sich also so bewährt haben, warum sollte es problematisch sein, sie auch in der Entwicklung von Systemen mit sicherheitskritischen Funktionen einzusetzen? Tatsächlich gibt es einige Stolperfallen, die sich aber umgehen lassen. In der Tabelle C4.5 des internationalen Dachstandards für funktionale Sicherheit (IEC 61508) etwa lautet eine Empfehlung, dass die für ein sicherheitskritisches System gewählte Sprache vollständig und eindeutig definiert sein sollte. Nun gibt es rund 190 verschiedene undefinierte Verhaltensweisen, in denen der Compiler entscheidet, wie die Quelleprogrammierung zu interpretieren ist. Zum Beispiel, wenn es um den Zugang eines Zeigerwertes zu einem Objekt geht, dessen Lebensdauer bereits überschritten ist, oder wenn zwei Angaben zu demselben Objekt oder derselben Funktion nicht-kompatible Typen spezifizieren.

Der Standard besagt auch, dass die Sprache die Nutzung von kleinen und beherrschbaren Softwaremodulen unterstützen sollte. In C und C++ ist das möglich, aber es ist keine Pflicht. Dasselbe trifft auf die Anforderungen der IEC 61508 zu, nach denen der Zugang zu Daten in speziellen Softwaremodulen sowie der Definition variabler Teilbereiche beschränkt sein sollte. Trotzdem sind C und C++ mit dem richtigen Sprachsubset ein höchst empfehlenswerter Standard für alle vier Safety Integrity Levels (SIL) von IEC 61508.

MISRA C/C++ bekämpft Nebenwirkungen

Ein perfekter Ausgangspunkt für ein solches Subset ist MISRA C/C++. Obwohl dies in erster Linie ein Programmierstandard für die Automobilindustrie ist, nutzen ihn auch viele andere Branchen als Basis für einen Codierungsstandard. MISRA ist ein Sprachsubset, das darauf abzielt alle Mehrdeutigkeiten der Programmiersprache zu beseitigen, und ein sicheres und zuverlässiges Verhalten des Codes zu unterstützen.

Zum Beispiel legt die MISRA C 2004 Regel 33 (required) fest: „the right-hand side of an && or || operator shall not contain side effects” (die rechte Seite eines && oder || Operators sollte keine Nebeneffekte beinhalten). Welche Bedeutung diese Vorschrift hat, wird bei Betrachtung der folgenden Code-Zeile deutlich:

if ((x == y) || (*p++ == z))

Die Spezifizierung der C-Sprache hält den Entwickler nicht davon ab, einen solchen Code zu entwerfen. Trotzdem setzt das ein tiefgehendes Verständnis für die Sprachregeln voraus, denn die rechte Seite wird nur evaluiert (und verursacht auch Nebenwirkungen), wenn der Code auf der linken Seite falsch ist. Das bedeutet, dass der Post-Inkrement-Zeiger nur dann ausgeführt wird, wenn die linke Seite falsch ist. Auch wenn diese vielleicht das beabsichtigte Verhalten darstellt, schleichen sich hier ganz leicht Fehler ein, und das bedeutet auch, dass jeder, der den Code prüft oder wartet, diese Nuance der C-Sprache verstehen muss.

Konstrukte dieser Art sind in MISRA verboten, weil sie so fehleranfällig sind. Ein weniger erfahrener Nutzer oder Prüfer könnte annehmen, dass der Zeiger immer erhöht wird, und wegen seines mangelnden Verständnisses, wie der Sprachstandard mit dieser Situation umgeht, falsche Berechnungen vornehmen und somit falsche Daten eingeben, die möglicherweise zu einem Absturz der Anwendung führen können.

Ein weiteres gutes Beispiel ist die MISRA C 2004 Regel 8, die bestimmt, dass der Speicher zum Beispiel zum Zeitpunkt der Kompilierung statisch festgelegt werden muss. Das ist vielleicht eine lästige Aufgabe, aber sie dient der erhöhten Sicherheit, weil sie sicherstellt, dass das System während seiner Laufzeit immer über ausreichend Speicher verfügt und keine Kapazitäten aus dem Heap zieht. Vielmehr ist dies die Aufgabe des Compilers, und so zeigen sich mögliche Probleme mit dem Speichermanagement noch vor der Testphase. Denn wenn ein System nicht mehr ausreichend Speicher zur Verfügung hat, wird es sich entweder sperren oder neu starten, um so den Fehler zu beheben – ein Verhalten, das zum Beispiel bei einem Luftfahrtsystem mitten in einem Flug auf keinen Fall auftreten sollte.

 

Lesen Sie auf der nächsten Seite: Allen Regeln folgen? – Tools für die beschleunigte Zertifizierung

Allen Regeln folgen?

Sicherheit

Bild 1: Das Tool C-STAT von IAR Systems unterstützt eine Prüfung der Regeln beispielsweise von MISRA oder von CERT-C und CERT-C++. IAR Systems

Viele Tools für die statische Analyse bieten MISRA-C-Checks für Quellcodes an. Viele gehen sogar darüber hinaus und bieten weitere Prüfungen an. Zum Beispiel führt das statische Analysetool C-STAT von IAR Systems Prüfungen der Regeln der Common Weakness Enumeration (CWE) sowie CERT-C und CERT-C++ aus (Bild 1). Diese stellen allerdings nur Richtlinien dar, sie sollten also nicht blind befolgt werden. Vielmehr wäre es ratsam zu überprüfen, was die einzelnen Regeln besagen und ob sie für das vorliegende Projekt geeignet sind, zum Beispiel ob die Speicherallokation dynamisch über den Heap erfolgen darf. Außerdem sollten diese Regeln am besten zu Projektbeginn berücksichtigt und nicht erst am Projektende abgeprüft werden. Im Extremfall werden hier möglicherweise Tausende von Regelverletzungen angezeigt – was den frustrierten Entwickler nur dazu verleiten wird, diese Regelchecks generell zu deaktivieren.

Muss eine statische Analyse durchgeführt werden, nachdem der Code erstellt worden ist (beispielsweise in Legacy-Projekten), sollte zunächst festgelegt werden, welche die „einfachsten“ Regeln sind und den Code auf entsprechende Verstöße überprüfen. Als „einfach“ gelten Regeln, für die sich leicht und sicher Veränderungen am Code vornehmen lassen, wenn ein Verstoß vorliegt – das minimiert den Aufwand bei den erforderlichen erneuten Tests. Je mehr Regeln im Legacy-Code implementiert werden, desto robuster wird die Anwendung. Und auch wenn nicht alle Regeln abgeprüft werden können, gilt trotzdem die alte Regel: Wenig ist besser als nichts!

Sicherheit

Bild 2: Laufzeitanalyse-Tools wie C-RUN von IAR Systems helfen dabei, Fehler bei der Ausführung des Codes zu finden. IAR Systems

Das Gegenstück zur statischen Analyse ist die Laufzeitanalyse. Manche Verhaltensweisen sind vollständig dynamisch und treten erst während der Laufzeit auf. Beispielsweise wenn ein Wert von einem Analog-Digital-Converter ausgelesen und für die Berechnung eines Array-Index genutzt wird, der dann einen Out-of-Bounds-Zugriff des Arrays erzeugt, der nicht statisch erfasst werden kann. Datenzugriffe außerhalb der vorgesehenen Bereiche führen zu unbestimmten Ergebnissen, denn es wird quasi ein Zufallswert ausgelesen, der dazu führt, dass die Anwendung falsche Ergebnisse liefert oder wegen eines fehlerhaften Zeigers „ins Kraut schießt“. Diese Art von potenziellen Fehlern beim Bound-Checking sind in der Embedded-Software weit verbreitet, weshalb Analysetools wie das Laufzeitanalysetool C-RUN von IAR Systems (Bild 2) so hilfreich sind. Sie helfen auch dabei, den Heapspeicher des Codes zu prüfen und andere Datenmanipulationen oder arithmetische Fehler bei der Codeausführung zu lokalisieren.

Entscheidend ist, dass sowohl die statische als auch Laufzeitanalyse des Codes dabei hilft, Fehler noch während der Entwicklung zu finden, also noch bevor sie in den formalen Build einfließen. Fehler, die in diesem Stadium der Entwicklung entdeckt und behoben werden, sind damit quasi niemals entstanden.

Wird aber ein Fehler in die Build-Phase übernommen, beeinträchtigt er die „Release Metrics“ des Projektes, wie Mean Time to Failure (MTTF) oder Mean Time Between Failures (MTBF). Dies verlängert den Test- und Debugging-Zyklus im Projekt, was wiederum zu erhöhten Entwicklungskosten und auch demotivierten Entwicklungsteams führt. Mit dem Einsatz eines Codeanalysetools lässt sich aber nicht nur ein langwieriger Debugging-Prozess verhindern. Vielmehr lässt es die Softwareentwicklung des Unternehmens für einen Reviewer bei der Zertifizierung für funktionale Sicherheit insgesamt auch sehr viel ausgereifter aussehen, wenn der Code offensichtlich eine niedrige Fehlerrate hat. Durch die Nutzung dieser Tools und Prozesse lässt sich also auch viel schneller eine Zertifizierung für funktionale Sicherheit erzielen.

Tools für die beschleunigte Zertifizierung

Um die Zertifizierung noch weiter zu beschleunigen, ist es ratsam Tools zu nutzen, die bereits eine eigene Zertifizierung für funktionale Sicherheit nachweisen können. Beim Einsatz eines nicht zertifizierten Tools ist es erforderlich, sehr strengere Anwendungstests durchzuführen, um nachzuweisen, dass es keine nachhaltigen Fehlerquellen in der Toolchain gibt. Das ist zwar grundsätzlich möglich, bedeutet aber einen Zusatzaufwand, weil dies bedeutet, dass die Tools für jedes einzelne Projekt wieder zertifiziert werden müssen. Das kann gut und gerne bis zu fünf Mitarbeiter für bis zu sechs Monate beschäftigen, was einen hohen finanziellen Aufwand und einen Verlust in der Produktivität bedeutet. Wird eine Toolchain eingesetzt, die diese Zertifizierung bereits vorweisen kann – wie die Functional-Safety-Version der IAR Embedded Workbench mit einer zertifizierten kompletten Build-Chain – wird sich der Zertifizierer bei seiner Prüfung auf die Anwendung konzentrieren.

Eck-DATEN

Mit vorqualifizierten Entwicklungs- und Analysetools lässt sich der Zertifizierungsprozess für funktionale Sicherheit erheblich beschleunigen. Grundsätzlich kommen dabei Werkzeuge sowohl für die statische Analyse als auch für die Laufzeitanalyse. Speziell für den Bereich Automotive hat IAR Systems erst kürzlich eine neue Functional-Safety-Version ihrer Toolchain vorgestellt: die IAR Embedded Workbench für die RH850 Mikrocontrollerfamilie von Renesas.

Shawn A. Prestridge

(Bild: IAR Systems)
Senior Field Applications Engineer bei IAR Systems

(ku)

Sie möchten gerne weiterlesen?

Unternehmen

IAR Systeme GmbH

Werner-Eckert-Str. 9
81829 München
Germany