Toyota: Konsekwencje błędnego oprogramowania firmowego (firmware) w starszych modelach samochodów

Toyota_ECMsm

W czwartek, 24 października 2013 roku, sąd Oklahoma wydał wyrok uznający Toyotę odpowiedzialną śmierci jednego z pasażerów na skutek niezamierzonego przyspieszenia pojazdu, spowodowanego błędem w oprogramowaniu.
Zasadniczym przedmiotem rozprawy sądowej było oprogramowanie sprzętowe (firmware) modułu sterowania silnikiem ECM (Engine Control Module).
Użyte wbudowane oprogramowanie było kodem niskiego poziomu, tworzonym przy użyciu języka C lub asemblera.
W dzisiejszych czasach nawet stosunkowo proste, aczkolwiek bardzo ważne zadanie, takie jak sterowanie przepustnicą, pewnie będzie wykorzystywać zaawansowany system operacyjny RTOS (Real-Time Operating System) i dziesiątki tysięcy linii kodu.
Przy całym tym wyrafinowaniu standardy i praktyki w zakresie projektowania, kodowania i testowania stają się najważniejsze – szczególnie, gdy funkcja ta ma decydujące znaczenie dla bezpieczeństwa.
Niepowodzenie (awaria) nie wchodzi w grę. Jest to coś, co ma być zawarte i bezpieczne (pewne).
Co się stanie, gdy producent samochodów zdecyduje się improwizować i grać według własnych zasad?
Czy do zignorowania rygorystycznych norm, najlepszych praktyk i kontroli wymaga się takiego projektu oprogramowania (i sprzętu)?
Ludzie tracą życie, reputacja zrujnowana, a miliardy dolarów odszkodowań zostały wypłacone. Tak się dzieje. Oto historia pewnego oprogramowania, które prawdopodobnie nigdy nie powinno powstać.
W przypadku większości z tych badań Electronic Design skonsultował się z Michaelem Barrem, dyrektorem technicznym i współzałożycielem Barr Group, firmy zajmującej się konsultingiem systemów wbudowanych.
Jako główny świadek dla powodów, dogłębna analiza przeprowadzona przez Barra i jego współpracowników przedstawia haniebny przykład projektowania i opracowywania oprogramowania, a także stanowi ostrzeżenie dla wszystkich zaangażowanych w krytyczny dla bezpieczeństwa rozwój, niezależnie od tego, czy chodzi o motoryzację, medycynę, lotnictwo, astronautyka czy gdziekolwiek indziej, gdzie niepowodzenie i awaria nie mogą być tolerowane.
Barr jest doświadczonym programistą, konsultantem, byłym profesorem, redaktorem, blogerem i autorem.
Ostateczne wnioski Barra brzmiały:
# Kod źródłowy elektronicznego układu sterowania przepustnicą Toyoty (ETCS) ma nieuzasadnioną jakość.

# Kod źródłowy Toyoty jest wadliwy i zawiera błędy, w tym błędy, które mogą powodować niezamierzone przyspieszenie (UA – Unintended Acceleration).

# Metryki jakości kodu przewidują obecność dodatkowych błędów (robaków).

# Zabezpieczenia przed awarią Toyoty są wadliwe i niewystarczające (odnosząc się do architektury bezpieczeństwa maja się jak „domek z kart”).

# Nieprawidłowości Toyoty w obszarze ETCS (Electronic Throttle Control System) są przyczyną błędów UA (Unintended Acceleration).

Co najmniej potworne podsumowanie. Spójrzmy na to, co doprowadziło go do tych wniosków.
Sprzęt komputerowy
Chociaż badanie skupiło się prawie wyłącznie na oprogramowaniu, istnieje, co najmniej jeden czynnik sprzętowy HW (Hardware). Firma Toyota twierdziła, że główny procesor w modelu samochodu Camry w 2005 r., był wyposażony w pamięć RAM z wykrywaniem i korektą błędów (EDAC – Error Detecting And Correcting). Tak nie było.
System EDAC lub przynajmniej tryb parzystości pamięci RAM to relatywnie proste i tanie zabezpieczenie dla systemów o krytycznym znaczeniu dla bezpieczeństwa.
Inne przypadki nieprawidłowego działania przepustnicy zostały powiązane z włoskami cyny w czujniku pedału przyspieszenia. Wydaje się, że nie miało to miejsca w tym przypadku.

Oprogramowanie

Oprogramowanie ECM (Engine Control Module) było rdzeniem badania technicznego. Poniżej znajduje się lista najważniejszych ustaleń.
Odbicie lustrzane (gdzie kluczowe dane są zapisywane do zmiennych nadmiarowych) nie zawsze było wykonywane. To zyskuje dodatkowe znaczenie w świetle … przepełnienia stosu.
Firma Toyota twierdziła, że tylko 41% przydzielonego miejsca na stosie było używane. Dochodzenie Barra pokazało, że 94% było bliższych prawdy.
Ponadto w kodzie, na górze, znaleziono „niszczenie stosu”, rekursję naruszającą reguły MISRA-C (Motor Industry Software Reliability Association), a procesor nie zawiera ochrony pamięci w celu ochrony przed przepełnieniem stosu.
Dwa kluczowe elementy nie były odzwierciedlane: krytyczne wewnętrzne struktury danych RTOS i – najważniejsze bajty wszystkich, końcowy rezultat całego tego oprogramowania – globalna zmienna Target Throttle Angle.
Chociaż Toyota przeprowadziła analizę stosu, Barr stwierdził, że producent całkowicie go spartaczył. Toyota przegapiła niektóre z połączeń wykonanych za pomocą wskaźnika, pominęła użycie stosu przez bibliotekę i funkcje montażu (łącznie około 350) oraz pominęła wykorzystanie RTOS podczas przełączania zadań. Nie udało się również wykonać monitorowania stosu w czasie bieżącego wykonywania.
System ETCS (Electronic Throttle Control System) Toyoty używał wersji OSEK (skrót w jęz. niem. Offene Systeme und deren Schnittstellen für die Elektronik in Kraftfahrzeugen), która jest protokołem motoryzacyjnym standardowego RTOS API. Z jakiegoś powodu wersja dostarczona przez producenta procesora nie była zgodna z certyfikatem.
Niezamierzone zamknięcie zadania RTOS zostało poważnie zbadane jako potencjalne źródło błędów UA (unintended acceleration). Ponieważ pojedyncze bity w pamięci kontrolują każde zadanie, uszkodzenie wynikające z błędów HW (Hardware) lub SW (Software) powoduje zawieszenie wymaganych zadań lub uruchamianie niechcianych zadań.
Testy pojazdu potwierdziły, że jedno konkretne martwe zadanie spowodowałoby utratę kontroli przepustnicy, i że kierowca może musieć całkowicie zdjąć stopę z pedału hamulca podczas niezamierzonego przyspieszenia, zanim będzie w stanie zakończyć niepożądane przyspieszenie.
W kodzie znaleziono litanię innych błędów, w tym przepełnienie bufora, niebezpieczne rzutowanie (unsafe casting) i warunki wyścigu między zadaniami.
Tysiące i tysiące

Stwierdzono, że kod Camry systemu ETCS zawiera 11 000 zmiennych globalnych. Barr określił kod jako „spaghetti”. Używając parametru złożoności cyklicznej, 67 funkcji zostało ocenionych, jako niepoprawne, (co oznacza, że uzyskały więcej niż 50).
Funkcja kąta przepustnicy uzyskała więcej niż 100 (niezmienna).
Toyota luźno przestrzegała powszechnie przyjętych zasad kodowania MISRA-C, ale grupa Barra wykryła 80 000 naruszeń przepisów. Wewnętrzne standardy Toyoty wykorzystują tylko 11 zasad MISRA-C, a pięć z nich zostało naruszonych w rzeczywistym kodzie. MISRA-C: 1998, w rzeczywistości, gdy kod został pierwotnie napisany, ma 93 wymagane i 34 zasady doradcze. Toyota zastosowała sześć z nich.
Barr odkrył również nieadekwatne i nierejestrowane inspekcje kodów peer oraz brak systemu śledzenia błędów (bug) w Toyocie.
NASA, która brała udział we wcześniejszym dochodzeniu, omówiła w swoim raporcie pięć trybów awaryjnych wdrożonych w ETCS. Obejmują trzy tryby limp-home, ograniczenie prędkości obrotowej i wreszcie wyłączenie silnika. Wszystkie awarie są obsługiwane przez to samo zadanie. Co zrobić, jeśli to zadanie nie działa lub działa nieprawidłowo?
Watchdog
Wiele systemów wbudowanych używa zegarów układu nadzorczego watchdog do powstrzymania błędnych procesorów; w systemach o krytycznym znaczeniu dla bezpieczeństwa jest to obowiązkowe. Jednak wraz ze wzrostem złożoności systemów, podsystem nadzoru musi odzwierciedlać tę złożoność.
Idealnie w systemie wielozadaniowym, każde aktywne zadanie powinno być zobowiązane do „zameldowanie się” (check in) do organu nadzoru. W firmie Toyota watchdog systemu ETCS był usatysfakcjonowany niczym więcej niż rutynową procedurą przerwania taktowania (ISR – Interrupt Service Routine).
Powolny takt. Jeśli układ ISR nie wyzeruje stanu układu watchdog, system ETCS może nadal działać nieprawidłowo z powodu przeciążenia procesora do 1,5s przed zresetowaniem. Należy jednak pamiętać, że w przypadku większości scenariuszy niepowodzenia zadania, ISR nadal będzie działał bez konieczności resetowania kontrolera.
Stwierdzono również, że większość kodów błędów RTOS wskazujących problemy z zadaniami zostały po prostu zignorowane – stanowcze naruszenie procedury MISRA-C.
Kto śledzi układ nadzorujący?

Płyta oprogramowania ETCS Toyoty ma drugi procesor do monitorowania pierwszego. Procesor monitora to część trzecia, z oprogramowaniem układowym nieznanym dla Toyoty i prawdopodobnie opracowana bez szczegółowej znajomości kodu głównego procesora.
Jest to potencjalnie dobra rzecz, ponieważ byłby naprawdę niezależnym nadzorcą. Ten układ komunikuje się z głównym procesorem przez łącze szeregowe, a także zawiera przetwornik ADC, który digitalizuje pozycję pedału przyspieszenia.
Każdy, kto pracuje z systemami bezpieczeństwa, wie, że pojedynczych punktów awarii należy unikać prawie za wszelką cenę, ale tutaj jest jeden – pojedynczy ADC, który zasila oba procesory swoją informacją o stanie pojazdu.
Ponadto kod odporny na awarie w tym procesorze monitorującym zależy od prawidłowego działania zadania głównego procesora Barr zidentyfikowane dla sądu tylko jako „Zadanie X” (w związku z zasadami ochrony tajemnicy otaczającymi sam kod źródłowy), prawdopodobnie poza zadaniem, które zajmuje się wszystkim od tempomatu do diagnostyki, która nie działa prawidłowo, do podstawowej funkcji przeliczania pozycji pedału na kąt otwarcia przepustnicy.
Zadanie X może być postrzegane, jako kolejny pojedynczy punkt awarii.
Wnioski i zalecenia

Czego można się nauczyć z tej historii oprogramowania, które poszło nie tak?
Oto kilka myśli, inspirowanych doświadczeniem Toyoty:
♦ Wszystko zaczyna się od kultury inżynierskiej. Jeśli musisz walczyć, aby wdrożyć jakość, lub odwrotnie, jeśli inni pozwolą ci ukryć tandetną pracę, jakość nie może się rozwijać. Kultura musi wspierać prawidłową wzajemną weryfikację, udokumentowane egzekwowanie reguł, stosowanie narzędzi i metryk jakości kodu itp.

♦ W złożonych systemach niemożliwe jest przetestowanie wszystkich potencjalnych scenariuszy awarii spowodowanych przez sprzęt i oprogramowanie. Należy dążyć do wdrożenia wszystkich możliwych najlepszych praktyk i wykorzystywać wszystkie dostępne narzędzia, aby stworzyć kod odporny na awarie.

♦ W miarę możliwości stosuj projektowanie oparte na modelach.

♦ Używaj narzędzi z odpowiednimi referencjami, a nie niecertyfikowanym systemem operacyjnym RTOS, jak to tutaj zrobiono.

♦ System musi zostać dokładnie przetestowany przez oddzielny zespół inżynierów. Nigdy nie popełniaj błędu testowania własnego projektu. (To prawda, ogólna strategia testów Toyoty nie została dokładnie opisana.)

♦ Sprzęt podstawowy musi współpracować z oprogramowaniem firmowym (firmware) w celu zapewnienia niezawodności:

       * Należy unikać pojedynczych punktów awarii w HW i SW.
        * Należy wdrożyć techniki architektoniczne, które przyczyniają się do niezawodności, takie jak procesory lockstep, pamięć EDAC, odpowiednio wdrożone układy watchdog, jednostki zarządzania pamięcią MMU (Memory Managment Unit) do implementacji pełnej izolacji i ochrony zadań.
       * Należy zastosować dokładną metodykę procedury FMEA (Failure Modes and Effects Analysis – analiza rodzajów i skutków możliwych błędów), aby scharakteryzować tryby awaryjne i ulepszenia projektowe.
 * Czy angażujesz się w urządzenia o znaczeniu krytycznym dla bezpieczeństwa? Jeśli tak, czy jesteś zadowolony, z jakości procesów i kultury w swojej firmie? Jakie są twoje przemyślenia na temat prac projektowych firmy Toyoty i ustaleń dochodzenia?

Autor: Michael Dunn (Electronic Design)

Komentarze z Facebooka

Komentarze obecnie - OFF.