W internecie można spotkać głosy, że programiści nie wykonują odpowiedzialnych zadań i nie ma żadnych regulacji, których muszą przestrzegać. Bo co złego może się stać, jeśli strona nie będzie działać, albo komputer wywali bluescreena. W końcu świat się od tego nie zawali. Być może jest to prawdą w 99% projektów programistycznych. Jednak tam, gdzie na szali jest ludzkie życie, bardzo restrykcyjne regulacje obowiązują już od dawna. Wiem o czym mówię, ponieważ przez ostatnie dwa lata pracowałem przy systemie sterującym ruchem pociągów.
Windows się tutaj nie sprawdzi
Wyobraźcie sobie, że lecicie samolotem z systemem sterowania opartym na Windowsie. Nagle następuje blue screen i pilot nie może wydawać żadnych poleceń. Niezbyt ciekawa perspektywa, prawda?
Aby do takich sytuacji nie dopuścić istnieją szczegółowe normy dotyczące systemów bezpieczeństwa. Nie może na nich działać zwykły Windows, czy Linux. Jedyne dopuszczalne systemy operacyjne to Hard Real Time Operating Systems (Hard RTOS), gdzie określone zadania muszą wykonywać się w zadanym czasie i być deterministyczne. Przykładem systemu spełniającego te wytyczne jest SafeRTOS.
Popularnym systemom operacyjnym trudno spełnić te wymagania, ponieważ są one projektowane z myślą o zwykłych użytkownikach i wykorzystaniu do pracy oraz rozrywki, a nie do sterowania samolotem. Chociaż społeczność Linuxa oczywiście stara się wyjść naprzeciw oczekiwaniom wobec systemów Hard Real Time, o czym można przeczytać w tym artykule.
Bardzo często w systemach bezpieczeństwa w ogóle nie używa się systemów operacyjnych, tylko aplikacje bare metal. Jest to możliwe, ponieważ oprogramowanie takich systemów zwykle uruchamiane jest na mikrokontrolerach i posiada ograniczone zasoby.
Safety integrity level
Systemy safety critical to takie, których błędne działanie powoduje zagrożenie dla ludzkiego zdrowia i życia. Zalicza się do nich między innymi oprogramowanie medyczne, do elektrowni atomowych, samochodów, pociągów, lotnicze, procesów chemicznych, wojskowe czy kosmiczne. Dla każdej branży istnieją specyficzne normy. Jest również ogólna norma o systemach bezpieczeństwa IEC61508, będąca podstawą do tworzenia konkretnych norm dla danej branży. Dostęp do treści norm niestety jest płatny, dlatego nie mogę przytoczyć linków do konkretnych dokumentów.
Norma IEC61508 definiuje Safety Integrity Level (SIL), po polsku Poziom Nienaruszalności Bezpieczeństwa. Można powiedzieć, że jest to poziom dopuszczalnego ryzyka wystąpienia groźnej usterki. Poziomy SIL są wyznaczane przy użyciu pożądanego prawdopodobieństwa wystąpienia usterki na godzinę (PFH – Probability of failure per hour) . Systemom przyznaje się poziomy SIL od 1 do 4 w zależności od konsekwencji błędnego działania:
- SIL4 – zagrożenie dla życia wielu ludzi.
- SIL3 – zagrożenie dla życia pojedynczej osoby.
- SIL2 – zagrożenie poważnego uszczerbku na zdrowiu.
- SIL1 – zagrożenie drobnego urazu.
Można również spotkać się z poziomem SIL0, który oznacza że system nie wymaga specjalnych środków bezpieczeństwa, ale twórcy podjęli działania opisane w normie w celu redukcji ryzyka usterek.
Aby uzyskać poziom bezpieczeństwa wymagany przez konkretny poziom SIL, podczas rozwoju systemu należy przestrzegać odpowiedniego procesu opisanego w normie. Proces ten omawia takie aspekty jak wymagana dokumentacja, kontrola jakości, procesy zarządzania projektem, analiza ryzyka, a nawet konkretne praktyki inżynierskie, jakich należy używać. Szczegółowe wymagania procesowe dla danej gałęzi przemysłu są opisane w normach dla danej branży, a w nich szczegółowa definicja SIL może się różnić, albo może być zdefiniowana inna klasyfikacja systemów bezpieczeństwa.
Bezpieczeństwo jest analizowane nie dla samego softu, ale dla systemu jako całości, czyli Software i Hardware. Tylko współpraca tych dwóch warstw może dać odpowiedni poziom bezpieczeństwa w skomplikowanych systemach.
Programowanie systemów bezpieczeństwa
Nie wszystkie języki programowania nadają się do aplikacji safety critical. Nie chcielibyście pewnie lecieć samolotem, gdzie system sterowania jest napisany w JavaScripcie albo w Pythonie.
Język powinien być statycznie typowany i wspierający znajdowanie błędów w czasie kompilacji i runtime. Powinien także nie zezwalać na używanie potencjalnie niebezpiecznych konstrukcji. Poza tym powinien spełniać paradygmat programowania strukturalnego mówiący między innymi, że program powinien składać się z bloków posiadających jeden punkt wejścia i jeden punkt wyjścia.
Tak naprawdę chyba żaden język nie spełnia wszystkich wymagań. Dlatego powstały zestawy dodatkowych reguł, których trzeba przestrzegać pisząc systemy bezpieczeństwa w danym języku. Przykładem może być standard MISRA-C próbujący poradzić sobie z niezdefiniowanymi zachowaniami i niebezpiecznymi konstrukcjami w języku C. Istnieje również wersja standardu dla C++. Reguły tego typu powinny być wymuszane przez narzędzia do statycznej analizy kodu. Za najbezpieczniejszy język uznawana jest ADA. ASM i C są również często wykorzystywane ze względu na większą dostępność toolchainów dla mikrokontrolerów.
Poza ograniczeniami dotyczącymi języka programowania istnieją dodatkowe ograniczenia dotyczące pewnych konstrukcji wyższego poziomu. Ograniczają one użycie rekurencji, polimorfizmu, czy dynamicznej alokacji pamięci. Nie można też na przykład doinstalowywać driverów, czy bibliotek w czasie działania programu. Chodzi o to, żeby system działał w sposób powtarzalny i żeby uchronić się przed błędami takimi jak przepełnienie stosu, czy fragmentacja pamięci.
Normy zawierają wykaz praktyk programistycznych jakie należy stosować w celu uzyskania odpowiedniego poziomu SIL. Należą do nich między innymi modułowy design, unit testy, code review, defensive programming, analiza statyczna. Część praktyk dla normy kolejowej 50128 można znaleźć w tym dokumencie.
Proces realizacji projektu
Projekty zwykle są rozwijane w technikach Waterfallowych, ponieważ normy wymuszają istnienie poszczególnych faz rozwoju takich jak analiza wymagań, implementacja, walidacja i utrzymanie. Fazy te są potrzebne aby zidentyfikować ryzyko i w architekturze wydzielić część krytyczną ze względu na bezpieczeństwo. Sposób prowadzenia projektu safety critical również musi zostać zatwierdzony przez urząd certyfikacyjny jako odpowiedni dla wytwarzania oprogramowania o zadanym SIL.
Dokumentacja w takich projektach jest dużo bardziej szczegółowa niż w zwykłych projektach. Musi ona być rozwijana na bieżąco, dla każdej fazy muszą powstać odpowiednie dokumenty. Co więcej, developer musi być w stanie pokazać jak dany zapis w dokumentacji odnosi się do wymagań, kodu produkcyjnego i testów. W ten sposób zgodność kodu z dokumentacją jest wymuszona przez proces. A dyskusja o zgodności rozwiązań z normą może się wtedy odbywać na poziomie dokumentacji, a nie kodu.
Podczas certyfikacji sam kod nie jest tak dokładnie analizowany. Ważniejsze jest sprawdzenie koncepcji przedstawionych w dokumentacji i poprawności procesu jego powstawania. Dobry proces będzie zapewniał weryfikację oraz walidację niezbędne dla osiągnięcia wymaganej jakości, a także szczegółową dokumentację i odpowiednie procedury wprowadzania zmian.
Podsumowanie
Programistów tworzących systemy od których zależy ludzkie zdrowie i życie obowiązują bardzo szczegółowe i restrykcyjne normy. Standardowe projekty informatyczne nie są w stanie przejść certyfikacji, dlatego takie systemy należy od początku prowadzić w sposób określony przez normy. Użycie wielu języków i technik programowania jest odradzane jako potencjalnie niebezpieczne. Skutkiem tak rygorystycznych procedur jest o wiele dłuższy czas powstawania projektu oraz dużo wyższe koszty. Za to otrzymujemy system o znacząco zwiększonym poziomie bezpieczeństwa.
7 listopada 2017 at 10:04
Programując na codzień „normalne” strony internetowe nie mam styczności z systemami, o których piszesz, dlatego artykuł był dla mnie bardzo ciekawy. Fajnie było zobaczyć jak to wygląda. Interesujące było w szczególności to, że sporo praktyk dotyczących tworzenia wysokiej jakości oprogramowania jednak się powtarza i wychodzi na to, że tworząc „normalne” strony internetowe nie jestem aż tak daleko od wysoce bezpiecznych systemów. Przynajmniej pod względem samych praktyk 🙂