Zastosowanie symulacji bŇĎdów do oceny i

Transkrypt

Zastosowanie symulacji bŇĎdów do oceny i
POLITECHNIKA WARSZAWSKA
Wydział Elektroniki
i Technik Informacyjnych
ROZPRAWA DOKTORSKA
mgr inż. Sławomir Chyłek
Zastosowanie symulacji bł˛edów do oceny i optymalizacji
niezawodności systemów operacyjnych
Promotor
prof. dr hab. inż. Janusz Sosnowski
Warszawa 2014
Podzi˛ekowania
Dzi˛ekuj˛e profesorowi Januszowi Sosnowskiemu za opiek˛e przez cały okres studiów
doktoranckich oraz nieoceniona˛ pomoc podczas tworzenia niniejszej rozprawy.
Dzi˛ekuj˛e Żonie Emilii, za wspieranie mnie oraz wyrzeczenia, które umożliwiły mi napisanie
niniejszej pracy.
Dzi˛ekuj˛e Koleżankom i Kolegom z Wydziału za wsparcie i pomoc podczas pracy nad
doktoratem.
Streszczenie
Symulacja bł˛edów jest jedna˛ z głównych technik ewaluacji niezawodności oprogramowania.
Niniejsza rozprawa poświ˛econa jest adaptacji symulacji bł˛edów w emulatorach systemów
komputerowych,
co umożliwiło badanie niezawodności oprogramowania systemów
operacyjnych oraz tworzenie nowych mechanizmów wykrywania i obsługi bł˛edów.
W rozprawie zaprezentowana została metodyka testowania oprogramowania z
zastosowaniem emulatora systemu komputerowego. Przedstawione zostały cechy emulacji
szczególnie użyteczne przy badaniu niezawodności oraz opisano oryginalne rozszerzenia
procesu emulacji o funkcje symulacji bł˛edów i nieinwazyjnego śledzenia wykonania.
Omówiony został aspekt masowego wykonania eksperymentów oraz analizowania dzienników
wykonania b˛edacych
˛
ich artefaktami.
Implementacja opisanej metodyki posłużyła do
opracowania oryginalnych metod przeprowadzania eksperymentów porównujacych
˛
różne
architektury procesorów, systemy operacyjne, a także pozwoliła przeprowadzić badania
ukierunkowane na ewaluacj˛e wrażliwości systemu operacyjnego na bł˛edy wyst˛epujace
˛
w urzadzeniach
˛
systemu komputerowego oraz poszczególnych typach danych systemu
operacyjnego: kod, stos, dane alokowane, dane statyczne oraz dane tylko do odczytu. W
rozprawie opisano przeprowadzone eksperymenty wraz z wynikami i płynacymi
˛
z nich
wnioskami.
Przeprowadzone badania pozwoliły na określenie krytycznych komponentów systemu
operacyjnego. Uwzgl˛edniajac
˛ ograniczenia oprogramowania wykonywanego w przestrzeni
jadra,
˛
zaproponowano oryginalny algorytm obsługi przerwań umożliwiajacy
˛ detekcj˛e i obsług˛e
lokalnych bł˛edów, a jego skuteczność została zweryfikowana opracowana˛ metodyka˛ testowania.
Zdefiniowano problem odtwarzalności wraz z algorytmem brudnych zasobów stanowiacym
˛
jedno z jego rozwiazań.
˛
Dodatkowo zaprezentowano mechanizm ochrony wskaźników powrotu
z funkcji przechowywanych na stosie.
Słowa kluczowe:
wstrzykiwanie bł˛edów, emulacja, niezawodność oprogramowania,
testowanie oprogramowania, systemy operacyjne, problem odtwarzalności, detekcja bł˛edów,
wrażliwość na bł˛edy, lokalizacja bł˛edów, tolerowanie bł˛edów.
5
Abstract
Adaptation of fault injection technique in assessment and reliability optimization of operating
systems
Fault injection is one of the most commonly used techniques for software reliability
evaluation. This thesis is focused on the subject of integration of fault injection technique into
computer system emulation software. The approach enabled research on reliability of operating
system’s software and development of novel fault detection and error handling mechanisms.
The thesis proposes methodology for testing software with utilization of computer software
emulation. Emulation features especially advantageous in reliability evaluation are presented in
detail followed by description of original extensions to emulation process: fault injection and
nonintrusive execution tracing. The aspects of parallel experiment execution and analysis of
experiments’ execution logs was discussed. Implementation of the proposed methodology was
utilized to develop original experimental methods for processors’ architectures and operating
systems comparison. Dedicated research was focused on evaluation of operating system’s
susceptibility to faults in case of faults occurring in computer system’s devices or different
types of operating system’s data: code, stack space, dynamically allocated data, static data and
read-only data. The thesis includes descriptions of conducted experiments followed by results
and conclusions.
Performed research enabled identification of most critical components of operating system.
While taking into account limitations of code executed in kernel mode a novel algorithm
for detecting and handling faults in interrupt procedures was proposed. Its effectiveness was
verified with presented testing methodology. The recovery problem was defined along with the
dirty resources algorithm as one of its solution. In addition, a method for protecting functions’
return address stored on stack was proposed.
Keywords:
fault injection, emulation, software reliability, software testing, operating
systems, recovery problem, software fault detection, fault sensitivity, software debugging, error
tolerance.
Spis treści
1. Wprowadzenie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
1.1.
Motywacja do powstania pracy
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
1.2.
Kierunek badań . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
1.3.
Teza i cel rozprawy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
1.4.
Układ pracy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
2. Analiza wpływu bł˛edów na działanie systemu komputerowego . . . . . . . . . . . . . . .
17
2.1.
Model systemu komputerowego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
2.1.1.
Model zasobów sprz˛etowych . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
2.1.2.
Model oprogramowania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
Modele bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
2.2.1.
Źródła bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
2.2.2.
Charakterystyka modeli bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . .
27
2.2.3.
Bł˛edy jednostek przetwarzajacych
˛
. . . . . . . . . . . . . . . . . . . . . . . .
28
2.2.4.
Bł˛edy pami˛eci operacyjnej . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
2.2.5.
Bł˛edy urzadzeń
˛
zewn˛etrznych . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
2.3.
Mechanizmy zwi˛ekszania niezawodności . . . . . . . . . . . . . . . . . . . . . . . . .
31
2.4.
Symulacja bł˛edów w badaniu niezawodności systemów komputerowych . . . . . . . . .
33
2.5.
Analiza efektów bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
2.5.1.
Scenariusz wystapienia
˛
bł˛edu . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
2.5.2.
Symulowanie bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
3. Metodyka symulacji bł˛edów w emulowanym środowisku . . . . . . . . . . . . . . . . . .
43
2.2.
2.6.
3.1.
Motywacja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
3.2.
Emulacja systemów komputerowych . . . . . . . . . . . . . . . . . . . . . . . . . . .
44
3.3.
Zastosowanie emulacji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
3.4.
Środowisko zautomatyzowanych testów . . . . . . . . . . . . . . . . . . . . . . . . . .
51
3.4.1.
Wybór emulatora systemu komputerowego . . . . . . . . . . . . . . . . . . . .
52
3.4.2.
Dokładność emulacji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
3.4.3.
Nieinwazyjne śledzenie wykonania . . . . . . . . . . . . . . . . . . . . . . . .
54
3.4.4.
Wydajność emulacji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
3.4.5.
Metodyka badań . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
3.4.6.
Architektura QEFI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
7
3.4.7.
Charakterystyka bł˛edów symulowanych w QEFI . . . . . . . . . . . . . . . . .
67
3.4.8.
Zastosowanie metodyki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
4. Badania eksperymentalne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
3.5.
4.1.
Plan przeprowadzonych eksperymentów . . . . . . . . . . . . . . . . . . . . . . . . . .
71
4.2.
Profilowanie wrażliwości na bł˛edy badanej architektury sprz˛etowej . . . . . . . . . . .
74
4.3.
Porównanie wrażliwości na bł˛edy różnych architektur sprz˛etowych . . . . . . . . . . .
85
4.4.
Porównanie wrażliwości różnych systemów operacyjnych . . . . . . . . . . . . . . . .
90
4.5.
Eksperymenty ukierunkowane na jadro
˛ systemu operacyjnego . . . . . . . . . . . . . .
95
4.5.1.
Bł˛edy urzadzeń
˛
wejścia/wyjścia . . . . . . . . . . . . . . . . . . . . . . . . . .
96
4.5.2.
Zaburzanie kodu, danych statycznych i danych tylko do odczytu systemu
operacyjnego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.5.3.
Zastosowanie profilowania do zaburzania kodu, stosu oraz danych alokowanych
systemu operacyjnego . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.6.
Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5. Mechanizmy wykrywania i obsługi bł˛edów . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.1.
Mechanizmy zwi˛ekszajace
˛ niezawodność w systemie operacyjnym . . . . . . . . . . . 117
5.2.
Ogólne założenia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.3.
Identyfikacja krytycznych komponentów . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.4.
Założenia dotyczace
˛ projektowanych mechanizmów zwi˛ekszania niezawodności . . . . 121
5.5.
Zapewnienie spójności kodu wykonywalnego . . . . . . . . . . . . . . . . . . . . . . . 122
5.6.
Procedury naprawcze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.6.1.
Metoda obsługi przerwań procesora dla kodu systemu operacyjnego . . . . . . 125
5.6.2.
Algorytm brudnych zasobów . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.6.3.
Ochrona stosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
5.6.4.
Mechanizmy ochrony danych . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
5.7.
Zastosowanie QEFI do optymalizacji niezawodności . . . . . . . . . . . . . . . . . . . 143
5.8.
Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
6. Podsumowanie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
6.1.
Spostrzeżenia i wnioski . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
6.2.
Zastosowania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
6.3.
Kierunki dalszych badań . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Bibliografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
A. Dodatek – specyfikacja opracowanego oprogramowania . . . . . . . . . . . . . . . . . . . 161
A.1. QEFI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
A.1.1. QEMU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
A.1.2. Nadzorca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
8
A.1.3. Ekstraktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
A.1.4. Eksperyment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
A.1.5. Analizator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
A.2. Zmiany w jadrze
˛
systemu GNU/Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
9
1. Wprowadzenie
Wraz z upowszechnieniem si˛e komputerów rośnie znaczenie niezawodnego funkcjonowania
urzadzeń
˛
cyfrowych.
Oczekiwania te zwiazane
˛
sa˛ z coraz wyższymi wymaganiami
użytkowników w stosunku do dost˛epności i jakości usług, a także z krytyczna˛ natura˛
zadań powierzonych systemom komputerowym – np. sterowanie układami pojazdów, czy
urzadzeń
˛
medycznych. O wadze tego problemu świadczy wiele faktów jak awaria chmury
obliczeniowej Amazon EC2 w 2012 roku1 powodujaca
˛ straty finansowe wielu portali
internetowych, czy opracowany w 2013 roku raport Amerykańskiej Agencji ds. Żywności
i Leków (FDA), ujawniajacy
˛ w Stanach Zjednoczonych w latach 2006-2011 wzrost liczby
incydentów zagrażajacych
˛
bezpieczeństwu pacjentów w zwiazku
˛
z usterkami medycznego
sprz˛etu komputerowego z 153 do 319 (patrz [6]).
Awarie te wystapiły
˛
pomimo nakładów pracy poświ˛econych na zwi˛ekszanie niezawodności
tych produktów, natomiast wiele awarii komputerów pozostaje nieodnotowanych lub raporty sa˛
niewystarczajace
˛ do prawidłowego określenia przyczyny problemu (patrz [113]). Dotyczy to w
szczególności awarii konsumenckich stacji roboczych, telefonów komórkowych, czy terminali
POS2 . Ostatnie badania (patrz [84, 94]) potwierdzaja˛ wag˛e problemu wyst˛epowania awarii
zarówno w systemach serwerowych jak i konsumenckich stacjach roboczych. Rodzi to potrzeb˛e
opracowywania nowych mechanizmów zwi˛ekszania niezawodności, które moga˛ być stosowane
w systemach typu COTS3 .
1.1. Motywacja do powstania pracy
Mechanizmy podnoszace
˛
niezawodność sa˛ wykorzystywane w specjalistycznych
rozwiazaniach,
˛
majacych
˛
na celu zwi˛ekszenie bezpieczeństwa ludzkiego życia lub
minimalizacj˛e finansowych.
W krytycznych zastosowaniach systemów komputerowych
wi˛eksza niezawodność osiagana
˛
jest poprzez ugruntowane metody realizowane sprz˛etowo lub
programowo – np. redundancja, punkty kontrolne (checkpoint), czy n-version programming
(patrz 2.3). Jednak wiele z tych technik nie jest wykorzystywanych w komponentach COTS
ze wzgl˛edu na wi˛eksze koszty projektowania lub produkcji – przykładowo w komputerach
przeznaczonych na rynek konsumencki standardowo nie sa˛ montowane dyski twarde
1
2
3
http://money.cnn.com/2011/04/21/technology/amazon_server_outage/index.htm
Ang. Point of Service.
Ang. Customer Of The Shelf.
11
wykorzystujace
˛ technologi˛e RAID4 , znaczaco
˛ zmniejszajace
˛ prawdopodobieństwo utraty
danych, a przygotowywanie kilku wersji oprogramowania, ocenianych później pod wzgl˛edem
wrażliwości na bł˛edy, jest wykorzystywane tylko w specjalistycznych dziedzinach. Wiele
systemów komputerowych oferowanych konsumentom pozbawionych jest ochrony przed
efektami awarii, a sa˛ także zbudowane z tańszych komponentów bardziej podatnych na usterki
(patrz [84]).
Sprz˛etowe metody zwi˛ekszania niezawodności sa˛ rozwiazaniami
˛
drogimi w produkcji ze
wzgl˛edu na koszt dodatkowych układów montowanych w każdym z produkowanych urzadzeń.
˛
Z tego wzgl˛edu szczególnie interesujace
˛ sa˛ programowe metody zwi˛ekszania niezawodności,
które moga˛ być dodane do oprogramowania urzadzenia
˛
bez dodatkowych kosztów i to nie tylko
w fazie produkcji, ale również podczas eksploatacji urzadzenia.
˛
Technika˛ wykorzystywana˛ w obszarze badań nad niezawodnościa˛ oprogramowania jest
SWIFI5 (patrz [8]).
Polega ona na wprowadzaniu bł˛edów do systemu komputerowego
metoda˛ programowa˛ w celu ewaluacji jego działania w obliczu zaburzeń.
Instytut
Informatyki Politechniki Warszawskiej posiada bogate doświadczenie z wykorzystaniem
techniki SWIFI (m.in. [37, 38, 42, 96, 97] ). Badania prowadzone w Instytucie pozwoliły na
opracowanie wielu narz˛edzi wstrzykiwania bł˛edów, ocen˛e podatności na bł˛edy różnych typów
oprogramowania, zaproponowanie rozwiazań
˛
programowych zwi˛ekszajacych
˛
niezawodność, a
także zaawansowana˛ analiz˛e dzienników działania systemów komputerowych.
Według autora, na podstawie analizy prac prowadzonych w Instytucie Informatyki oraz
literatury, istotna˛ dziedzina˛ wymagajac
˛ a˛ badań jest niezawodność oprogramowania systemów
operacyjnych. Twierdzenie to jest uzasadnione nast˛epujaco:
˛
— Obserwowana
jest
ekspansja
systemów
operacyjnych
znanych
z
zastosowań
biurowych/serwerowych do nowych dziedzin [10, 114]. Przykładami takich scenariuszy jest
wykorzystanie jadra
˛
systemu operacyjnego GNU/Linux w robotyce, platformie Android,
czy systemów z rodziny Windows NT w platformie Windows Phone. Oznacza to, że od
tych systemów oczekiwane jest niezawodne funkcjonowanie zarówno w kontrolowanych
warunkach farm serwerów jak i urzadzeniach
˛
przenośnych.
— Potwierdzone sa˛ przypadki wyst˛epowania przekłamań powodujacych
˛
awari˛e systemów
operacyjnych (patrz [84]) w konsumenckich stacjach roboczych.
— Wiele przedstawionych w literaturze mechanizmów zwi˛ekszania niezawodności aplikacji
wykorzystuje usługi dostarczane przez systemy operacyjne, jednak niewiele jest
opisanych mechanizmów zwi˛ekszania niezawodności samego oprogramowania systemów
operacyjnych.
4
5
Ang. Redundant Array of Independent Disks.
Ang. Software Implemented Fault Injection
12
Zainteresowanie
autora
zagadnieniem
niezawodności
systemów
operacyjnych
dodatkowo zostało wzmocnione udziałem w projekcie realizowanym dla Centrum
Badawczo-Rozwojowego Samsung Electronics Polska w Warszawie przez Instytut Informatyki
Politechniki Warszawskiej6 .
W literaturze można znaleźć niewiele publikacji skupiajacych
˛
si˛e na badaniu niezawodności
systemu operacyjnego.
Według autora fakt ten wynika z nast˛epujacych
˛
problemów
technicznych:
— opracowywane narz˛edzia SWIFI dla oprogramowania aplikacji najcz˛eściej polegaja˛ na
usługach systemu operacyjnego, co uniemożliwia ich zastosowanie w jadrze
˛
systemu
operacyjnego,
— opracowywane narz˛edzia symulacji bł˛edów w systemie operacyjnym wymagaja˛
modyfikacji źródeł jadra
˛
systemu operacyjnego – powoduje to de facto badanie
niezawodności innego oprogramowania, niż oprogramowanie docelowe (pozbawionego
kodu symulujacego
˛
bł˛edy),
— ograniczona
skalowalność
przedstawionych
rozwiazań
˛
–
do
przeprowadzania
eksperymentów cz˛esto dedykowany jest osobny system komputerowy; ch˛eć zwi˛ekszenia
liczby przeprowadzanych testów wia˛że si˛e z kosztem instalacji i konfiguracji dodatkowych
dedykowanych systemów komputerowych.
Niemniej
badanie
niezawodności
jadra
˛
systemu
operacyjnego
i
projektowanie
mechanizmów zwi˛ekszajacych
˛
niezawodność działajacych
˛
po stronie jadra
˛
systemu
operacyjnego wia˛że si˛e z potencjalnymi korzyściami:
— systemy operacyjne sa˛ stosowane w wi˛ekszości współczesnych urzadzeń,
˛
co pozwala
zwi˛ekszyć ich niezawodność niezależnie od ich specyficznych zastosowań,
— możliwość informowania aplikacji o potencjalnych problemach wykrytych przez system
operacyjny,
— zwi˛ekszenie dost˛epności oraz możliwości diagnostyki systemu komputerowego,
— opracowanie mechanizmów zwi˛ekszania niezawodności, wykorzystujacych
˛
kooperacj˛e
aplikacji i systemu operacyjnego; podejście takie jest alternatywa˛ dla mechanizmów,
gdzie zarówno program o zwi˛ekszonej niezawodności, jak i program realizujacy
˛ usługi
zwi˛ekszania niezawodności (np. program dokonujacy
˛ operacji wznowienia działania
po awarii na podstawie wcześniej zapisanych wyników cz˛eściowych) sa˛ aplikacjami
użytkownika działajacymi
˛
w systemie operacyjnym.
Motywacja˛ do powstania rozprawy jest ulepszenie realizacji metod SWIFI do
badania niezawodności systemów operacyjnych, w zwiazku
˛
z wymienionymi problemami
6
Projekt Adapting fault injection techniques to improve Samsung mobile products współfinansowany
przez Polska˛ Agencj˛e Rozwoju Przedsi˛ebiorczości w ramach działania 1.4 Wsparcie projektów celowych osi
priorytetowej 1 Badania i rozwój nowoczesnych technologii oraz działania 4.1 Wsparcie wdrożeń wyników prac
B+R osi priorytetowej 4 Inwestycje w innowacyjne przedsi˛ewzi˛ecia.
13
technicznymi, wyst˛epujacymi
˛
w obecnych rozwiazaniach
˛
oraz opracowywanie na tej podstawie
nowych mechanizmów zwi˛ekszajacych
˛
niezawodność. W ten sposób autor pragnie wnieść
wkład w proces integracji mechanizmów niezawodności w opracowywanie produktów
wysokiej jakości.
1.2. Kierunek badań
Rozważania opisane w rozprawie bazuja˛ na koncepcji zastosowania emulatora systemu
komputerowego do przeprowadzania eksperymentów badania niezawodności. Zastosowanie
takiego podejścia pozwala rozwiazać
˛
wymienione powyżej problemy techniczne oraz posiada
dodatkowe atuty:
możliwe jest zwi˛ekszenie spektrum modeli symulowanych bł˛edów
wzgl˛edem rozwiazań
˛
znanych z literatury (np. o modele bł˛edów konkretnych urzadzeń),
˛
a
także porównywanie mi˛edzy soba˛ różnych architektur systemów komputerowych i różnych
implementacji systemów operacyjnych.
Dzi˛eki temu możliwe jest uzupełnienie stanu
wiedzy o nowe fakty nieopisane w literaturze. Opracowanie środowiska symulacji bł˛edów,
wykorzystujacego
˛
emulator, wymagało dogł˛ebnego poznania szczegółów implementacji
zarówno różnych technik emulacji, jak i systemów operacyjnych.
Badania przeprowadzone w przygotowanym przez autora środowisku pozwoliły na
szczegółowa˛ analiz˛e scenariuszy wystapienia
˛
bł˛edów w systemie operacyjnym.
Na tej
podstawie autor opracował metody zwi˛ekszania niezawodności implementowane po stronie
jadra
˛ systemu operacyjnego, przy czym przyj˛ete zostało założenie integracji opracowywanych
mechanizmów z istniejacym
˛
oprogramowaniem.
Opracowane mechanizmy bazuja˛ na
wzbogaceniu procedur obsługi przerwań zaimplementowanych w systemie operacyjnym o
dodatkowe kroki umożliwiajace
˛ kontynuowanie pracy systemu.
1.3. Teza i cel rozprawy
Teza˛ pracy jest stwierdzenie:
Integracja technik symulacji bł˛edów z emulacja˛ systemu komputerowego umożliwia
dokładniejsza˛ ocen˛e wrażliwości na bł˛edy oprogramowania systemu operacyjnego oraz
weryfikacj˛e skuteczności mechanizmów zwi˛ekszania niezawodności.
Celem rozprawy jest:
Opracowanie metodyki, algorytmów oraz narz˛edzi służacych
˛
ocenie niezawodności
systemów komputerowych typu COTS oraz zaproponowanie nowych typów mechanizmów
14
zwi˛ekszania niezawodności implementowanych po stronie jadra
˛
systemu operacyjnego, wraz z
ocena˛ ich efektywności.
Cel rozprawy osiagni˛
˛ eto poprzez:
— opracowanie autorskich rozszerzeń oprogramowania emulatora o funkcje:
— symulacji bł˛edów,
— nieinwazyjnego śledzenia wykonania,
— zaproponowanie oryginalnej metodyki i scenariuszy przeprowadzania eksperymentów z
wykorzystaniem emulatora oraz miar służacych
˛
ocenie wrażliwości systemu na bł˛edy,
— opracowanie algorytmów i oprogramowania QEFI realizujacego
˛
zaproponowana˛ metodyk˛e,
— przeprowadzenie serii eksperymentów z wykorzystaniem opracowanych narz˛edzi:
— porównanie wrażliwości na bł˛edy różnych architektur sprz˛etowych,
— porównanie wrażliwości na bł˛edy różnych systemów operacyjnych,
— zbadanie efektów bł˛edów wyst˛epujacych
˛
w różnych urzadzeniach,
˛
— zbadanie wrażliwości na bł˛edy kodu, danych statycznych, danych tylko do odczytu,
danych alokowanych oraz stosu systemu operacyjnego,
— zaproponowanie metody zwi˛ekszania niezawodności w przypadku przekłamań w kodzie
systemu operacyjnego i jej weryfikacja z zastosowaniem opracowanej metodyki,
— opracowanie eksperymentalnej metody ochrony stosu, wykorzystujacej
˛
współprac˛e
aplikacji oraz jadra
˛ systemu operacyjnego.
Dodatkowo na podstawie obserwacji efektów bł˛edów w kodzie systemu operacyjnego
zdefiniowany został problem odtwarzalności oraz opracowano algorytm brudnych zasobów.
1.4. Układ pracy
Praca składa si˛e z sześciu rozdziałów, bibliografii oraz dodatku zawierajacego
˛
informacje
o opracowanym oprogramowaniu. Rozdział pierwszy stanowi wprowadzenie do tematyki
rozprawy oraz zdefiniowanie tezy i celu rozprawy.
Rozdział drugi przedstawia tło badań nad niezawodnościa˛ z wykorzystaniem SWIFI oraz
znane z literatury mechanizmy zwi˛ekszania niezawodności. Opisane sa˛ modele badanych
bł˛edów oraz zdefiniowane sa˛ miary opisujace
˛ wpływ symulowanych bł˛edów na system
komputerowy, wykorzystane w dalszej cz˛eści rozprawy.
Rozdział trzeci zawiera opis opracowanej metodyki przeprowadzania eksperymentów
symulacji bł˛edów z wykorzystaniem emulacji systemu komputerowego.
W rozdziale
opisane jest opracowane przez autora narz˛edzie QEFI, służace
˛
symulacji bł˛edów w
emulowanym systemie komputerowym, profilowaniu działania systemu oraz analizie efektów
15
wprowadzanych bł˛edów.
Przedstawiona jest architektura QEFI, uzasadnione sa˛ decyzje
projektowe oraz opisane sa˛ algorytmy, służace
˛ realizacji opracowanej metodyki.
Rozdział czwarty przedstawia praktyczne wykorzystanie metodyki w serii eksperymentów
opartych o opracowane przez autora scenariusze testów.
Przedstawiono porównanie
wrażliwości na bł˛edy różnych architektur ISA procesorów (patrz 4.3) oraz porównanie różnych
systemów operacyjnych (patrz 4.4). Opracowana została seria badań nad wrażliwościa˛ na bł˛edy
systemu operacyjnego GNU/Linux – zbadano efekty bł˛edów wyst˛epujacych
˛
w urzadzeniach
˛
systemu komputerowego (patrz 4.5.1) oraz różnych typach danych: kod, stos, dane alokowane,
dane statyczne oraz dane tylko do odczytu (patrz 4.5.2, 4.5.3). W opisie eksperymentów
wprowadzania bł˛edów w przestrzeń kodu, stosu oraz danych alokowanych, przedstawiono
wykorzystanie mechanizmów profilowania zintegrowanych z QEFI.
W rozdziale piatym
˛
opisano opracowane mechanizmy zwi˛ekszania niezawodności – metod˛e
obsługi przerwań, algorytm brudnych zasobów oraz metod˛e ochrony stosu. Mechanizmy te
pozwalaja˛ uniknać
˛ wystapienia
˛
sytuacji wyjatkowej
˛
podczas wykonania oprogramowania i
moga˛ być łatwo zintegrowane z systemem operacyjnym GNU/Linux z użyciem mechanizmu
kprobes. Skuteczność metody obsługi przerwań została zweryfikowana z użyciem QEFI.
Przy opracowaniu algorytmu brudnych zasobów zdefiniowany został problem odtwarzalności –
tzn. przywrócenia prawidłowego stanu wykonania programu po wykonaniu serii zaburzonych
instrukcji. Skuteczność algorytmu brudnych zasobów została oszacowana poprzez symulacj˛e.
Natomiast metoda ochrony stosu prezentuje technik˛e kooperacji aplikacji oraz systemu
operacyjnego przy zwi˛ekszaniu niezawodności. Dodatkowo przeprowadzona została dyskusja
nad mechanizmami ochrony danych w systemie operacyjnym
Rozdział szósty stanowi podsumowanie przeprowadzonych badań.
wnioski i spostrzeżenia z przeprowadzonych badań.
Rozdział zawiera
Przedstawione sa˛ zastosowania
zaproponowanych rozwiazań
˛
oraz dalsze kierunki badań.
Dodatek zawiera wykaz funkcji opracowanego oprogramowania QEFI wraz z informacja˛ o
zmianach w oprogramowaniu QEMU oraz jadrze
˛
systemu GNU/Linux.
16
2. Analiza wpływu bł˛edów na działanie systemu
komputerowego
Projektowanie mechanizmów zwi˛ekszania niezawodności systemów komputerowych
wymaga analizy problemów wyst˛epujacych
˛
podczas eksploatacji. Na podstawie tych danych
tworzone sa˛ modele bł˛edów, które wykorzystywane sa˛ przy ewaluacji skuteczności technik
obsługi sytuacji wyjatkowych.
˛
W rozdziale przedstawiony jest model systemu komputerowego, stanowiacy
˛ podstaw˛e
dalszych rozważań.
Nast˛epnie scharakteryzowane sa˛ źródła bł˛edów eksploatacyjnych w
systemach cyfrowych, podstawowe techniki badania i zwi˛ekszania niezawodności oraz modele
bł˛edów opisujace
˛ efekty zaburzeń w warstwie logicznej. Ostatnia cz˛eść rozdziału poświ˛econa
jest miarom niezawodności – wprowadzone miary wykorzystane sa˛ do oceny kondycji systemu
komputerowego w rozdziałach 4 oraz 5.
2.1. Model systemu komputerowego
Celem systemów komputerowych jest udost˛epnianie określonych funkcji. Sposób ich
realizacji zapisany jest w postaci oprogramowania.
Oprogramowanie operuje na danych
wejściowych i w wyniku wykonania zaimplementowanych algorytmów wytwarza dane
wyjściowe.
Za wykonanie oprogramowania oraz dostarczenie danych do i z systemu
komputerowego odpowiedzialne sa˛ zasoby sprz˛etowe. Powyższa charakterystyka pozwala na
zdefiniowanie systemu komputerowego:
Definicja 2.1.1. System komputerowy jest to SK ≡ H × S × D, gdzie H – zasoby sprz˛etowe,
S – oprogramowanie, D – dane.
Zasoby sprz˛etowe składaja˛ si˛e z wielu urzadzeń
˛
o skomplikowanej wewn˛etrznej strukturze.
Dzi˛eki sieci połaczeń
˛
oraz opracowanym interfejsom komunikacji możliwe jest współdziałanie
urzadzeń
˛
w celu realizacji określonych zadań. W sekcji 2.1.1 przedstawiony jest model tych
urzadzeń,
˛
opracowany na potrzeby niniejszej rozprawy.
Oprogramowanie systemu komputerowego jest niezmienne podczas eksploatacji systemu
(z wyłaczeniem
˛
czynności konfiguracyjnych), natomiast dane sa˛ zmienne i wykorzystywane
na bieżaco
˛ przy realizacji określonych funkcji. Oprogramowanie można podzielić według
17
miejsca wykonania (np. procesory ogólnego przeznaczenia1 , procesory specjalistyczne2 , układy
wbudowane3 ) oraz poziomu abstrakcji – stos oprogramowania rozciaga
˛ si˛e od oprogramowania
bezpośrednio obsługujacego
˛
urzadzenia
˛
elektroniczne do aplikacji użytkownika realizujacych
˛
określone funkcje.
W sekcji 2.1.2 szczegółowo przestawiono opracowany model
oprogramowania.
2.1.1. Model zasobów sprz˛etowych
W systemach komputerowych podstawowymi komponentami sa˛ procesory, pami˛eć oraz
urzadzenia
˛
wejścia/wyjścia. Urzadzenia
˛
te współpracuja˛ ze soba˛ za pośrednictwem interfejsów
umożliwiajacych
˛
wymian˛e danych.
Procesor
Procesor jest to układ cyfrowy realizujacy
˛ sekwencyjne wykonanie instrukcji pobieranych z
pami˛eci. Zbiór instrukcji procesora określany jest jako ISA4 . Operacje zakodowane przez
instrukcje można podzielić według nast˛epujacych
˛
kategorii: ładowanie danych do pami˛eci,
manipulowanie danymi (wykonywanie obliczeń), zapisywanie danych w pami˛eci, instrukcje
sterujace
˛ (instrukcje skoku i warunkowe) oraz instrukcje specjalne (np. instrukcje opróżnienia
pami˛eci podr˛ecznej). Procesor dysponuje rejestrami – sa˛ to komórki pami˛eci wykorzystywane
do przechowywania pośrednich wyników obliczeń oraz stanu procesora. Można wyróżnić
rejestry danych, adresowe, ogólnego przeznaczenia, zmiennoprzecinkowe, wektorowe oraz
specjalne (patrz [56]). Procesor wyposażony jest również w mechanizm obsługi przerwań,
pozwalajacy
˛ na wstrzymanie aktualnie wykonywanego kodu i wykonanie przez procesor kodu
procedury obsługi przerwania. Przerwania moga˛ być zgłaszane przez: urzadzenia
˛
zewn˛etrzne
(np. sygnalizowane jest w ten sposób nadejście nowych danych), zegary (wykorzystywane przy
implementacji systemów z podziałem czasu), procesor (sa˛ to wyjatki
˛ procesora wywołane
wykonaniem przez program niedozwolonej operacji) lub wykonanie specjalnej instrukcji
przerwania programowego.
Przedstawiony model procesora jest modelem logicznym.
Współczesne procesory
w celu przyśpieszenia wykonania dysponuja˛ dodatkowymi układami realizujacymi
˛
specjalizowane zadania: potok wykonania, układ przewidywania skoków, superskalarne
jednostki
wykonawcze
oraz
zwielokrotnienie
rejestrów.
Elementy
mikroarchitektur˛e procesora (patrz [51]) i służa˛ przyśpieszeniu jego pracy.
te
stanowia˛
Integralna˛
cz˛eść procesora stanowi również pami˛eć podr˛eczna. Jest to mechanizm buforowania danych
i instrukcji przechowywanych w pami˛eci operacyjnej w pami˛eci o krótszym czasie dost˛epu.
1
Współcześnie konstruowane sa˛ systemy wieloprocesorowe, gdzie system komputerowy wyposażony jest
kilka fizycznych procesorów, a każdy z nich pełni funkcj˛e jednego lub wi˛ecej procesorów logicznych.
2
Np. Układy graficzne GPU (Ang. Graphics Processing Unit).
3
Np. kontrolery RAID.
4
Ang. Instruction Set Architecture.
18
Rozwiazanie
˛
to zostało wprowadzone z uwagi na duży koszt wytworzenia pojemnej pami˛eci
o krótkim czasie dost˛epu.
lokalności odwołań.
Wykorzystane zostało tu zjawisko czasowej i przestrzennej
Pami˛eci podr˛eczne organizowane sa˛ w hierarchiczne struktury –
najcz˛eściej wykorzystywane sa˛ dwa lub trzy poziomy pami˛eci podr˛ecznej, gdzie każdy kolejny
poziom charakteryzuje si˛e wi˛eksza˛ pojemnościa˛ oraz dłuższym czasem dost˛epu. Dost˛ep do
wymienionych układów procesora jest niemożliwy z poziomu wykonywanych programów
(wyjatkiem
˛
jest specjalna instrukcja procesora wymuszajaca
˛ unieważnienie zawartości danych
w pami˛eci podr˛ecznej).
Warto zaznaczyć, że we współczesnych procesorach stosuje si˛e wi˛ecej, niż jeden rdzeń
wykonania, co pozwala na zwi˛ekszenie wydajności systemu. Rdzenie te posiadaja˛ wspólna˛
pami˛eć podr˛eczna˛ i połaczone
˛
sa˛ jedna˛ szyna˛ danych do reszty systemu. Dodatkowo każdy z
rdzeni może być wyposażony w technologi˛e hyper threading, która powoduje, że pojedynczy
rdzeń jest widoczny dla systemu operacyjnego jako dwie wirtualne jednostki wykonawcze.
Technologia ta polega na zwielokrotnieniu niektórych zasobów procesora w taki sposób,
że możliwe jest przechowywanie dwóch kontekstów wykonania. W przypadku, gdy jedna
jednostka wykonania zostaje wstrzymana (np. podczas oczekiwania na dane pobierane z
pami˛eci) rdzeń przełacza
˛
si˛e na kontekst drugiej jednostki wykonania, umożliwiajac
˛ w ten
sposób realizacj˛e równolegle dwóch zadań.
Pami˛eć
Pami˛eć realizuje funkcj˛e przechowywania danych. Można wyróżnić pami˛eć ROM5 oraz RAM6 .
Pami˛eci ROM służa˛ przechowywaniu danych tylko do odczytu – sa˛ to np. procedury startowe
systemu komputerowego. Natomiast pami˛eć RAM jest pami˛ecia˛ ogólnego przeznaczenia
umożliwiajac
˛ a˛ zapis oraz odczyt danych.
Pami˛eć RAM sa˛ nazywane również pami˛ecia˛
operacyjna˛ w odróżnieniu od innych, specjalizowanych typów pami˛eci (np. pami˛eć podr˛eczna
procesora).
Istotnym układem wykorzystywanym w obsłudze pami˛eci jest MMU7 – jest to urzadzenie
˛
odpowiedzialne za mechanizm pami˛eci wirtualnej, tworzacy
˛ dla każdego z programów
wykonywanych przez procesor osobna˛ przestrzeń adresowa.˛ Obecnie układ MMU stanowi
integralna˛ cz˛eść procesora. Urzadzenie
˛
to w ścisłej współpracy z systemem operacyjnym dzieli
pami˛eć na strony i zarzadza
˛
ich stanem (m.in. wolna, załadowana, w pliku wymiany) oraz
prawami dost˛epu (strona zawiera wykonywalny kod, dane, dane tylko do odczytu).
Urzadzenia
˛
wejścia/wyjścia
Systemy komputerowe wyposażane sa˛ w dodatkowe urzadzenia
˛
realizujace
˛
funkcje
komunikacyjne, multimedialne, wskazujace
˛ oraz pami˛eci masowej. Poszczególne urzadzenia
˛
5
6
7
Ang. Read Only Memory.
Ang. Random Access Memory.
Ang. Memory Management Unit.
19
systemu komputerowego wymieniaja˛ dane z procesorem oraz pami˛ecia˛ z zastosowaniem
magistral.
Współpraca procesora oraz urzadzeń
˛
wejścia/wyjścia realizowana jest przez
przerwania oraz mechanizm Memory mapped I/O, czyli przypisanie cz˛eści przestrzeni
adresowej dost˛epnej dla procesora bezpośrednio do rejestrów urzadzeń
˛
zamiast do pami˛eci
operacyjnej.
2.1.2. Model oprogramowania
Oprogramowanie
systemu
komputerowego
określonych przez twórców algorytmów.
służy
przetwarzaniu
danych
według
Jest ono zapisane w postaci zestawu instrukcji
wykonywanych przez procesor – zbiór instrukcji nazywany jest również kodem programu. W
celu realizacji swoich zadań oprogramowanie wykorzystuje pami˛eć. Można wyróżnić kilka
typów pami˛eci ze wzgl˛edu na przechowywane dane: stos programowy, pami˛eć statyczna,˛
pami˛eć tylko do odczytu oraz pami˛eć alokowana.˛
Stos programowy służy jako pami˛eć przechowujaca
˛ dane tymczasowe obliczeń, gdy jest ich
zbyt wiele, aby zostały zapisane w rejestrach procesora. Dodatkowo wykorzystywany jest on
w programowaniu wysokopoziomowym, pozwalajac
˛ na hierarchiczne wywołania procedur.
Pami˛eć statyczna sa˛ to obszary pami˛eci stałego rozmiaru dost˛epne na każdym etapie
obliczeń pod tym samym adresem. W pami˛eci tego typu przechowywane sa˛ dane globalne
– sa˛ to dane dost˛epne na każdym etapie wykonania programu.
Pami˛eć tylko do odczytu zawiera niezmienne podczas obliczeń dane. Mi˛edzy innymi jest to
kod programu, zakodowane obrazy wyświetlane użytkownikowi na ekranie, czy stałe napisowe,
b˛edace
˛ szablonami komunikatów wypisywanych podczas interakcji z programem.
Pami˛eć alokowana jest przydzielana w trakcie obliczeń według potrzeb wykonywanego
algorytmu.
Charakteryzuje si˛e zmiennym rozmiarem oraz tym, że jest przyznawana
przez mechanizmy alokacji pami˛eci systemu operacyjnego spośród dost˛epnej w danej
chwili puli wolnej pami˛eci.
Istnieje wiele algorytmów alokacji pami˛eci, które różnia˛
si˛e czasami alokacji oraz stopniem fragmentacji pami˛eci8 .
Opracowane sa˛ również
zaawansowane techniki zarzadzania
˛
pami˛ecia,˛ pozwalajace
˛ na automatyczne zwalnianie
niewykorzystywanej pami˛eci (garbage collection), jednak nie sa˛ one wykorzystywane w
każdym rodzaju oprogramowania ze wzgl˛edu na niedeterministyczny charakter działania.
Dynamika alokacji oraz lokalność odwołań jest ściśle zwiazana
˛
z realizowanymi algorytmami
oraz wykorzystywanymi strukturami danych.
Przykładowo alokacja danych na potrzeby
9
listowej struktury danych jest wykorzystana przy każdym dodawaniu nowego elementu, a
także przeszukiwanie kolejno w˛ezłów listy powoduje dost˛ep do wielu miejsc w pami˛eci (każdy
8
Fragmentacja powstaje w przypadku dzielenia przez algorytm alokacji pami˛eci na bloki o stałym rozmiarze.
Kiedy blok jest wykorzystywany na alokacj˛e pami˛eci o mniejszym rozmiarze, niż rozmiar bloku – w ten sposób
niewykorzystana cz˛eść pami˛eci staje si˛e niedost˛epna.
9
Opis listowej struktury danych dla j˛ezyka C++: http://www.cplusplus.com/reference/list/list/
20
w˛ezeł jest alokowany osobno i miejsce jego położenia w pami˛eci jest zależne od algorytmu
alokacji). Natomiast zastosowanie wektorowej struktury danych10 pozwala na redukcj˛e liczby
alokacji oraz przeglad
˛ kolejnych elementów struktury danych, charakteryzuje si˛e liniowym
dost˛epem do kolejnych adresów pami˛eci (niemniej zysk ten obarczony jest wi˛eksza˛ złożonościa˛
obliczeniowa˛ przy usuwaniu elementów z wektora, w zwiazku
˛
z koniecznościa˛ przeniesienia
elementów znajdujacych
˛
si˛e za usuwanym elementem w nowa˛ lokalizacj˛e11 ).
Oprogramowanie
systemu
komputerowego
można
podzielić
na
trzy
rodzaje:
oprogramowanie wbudowane (firmware), system operacyjny oraz aplikacje użytkownika.
Firmware jest oprogramowaniem dedykowanym dla poszczególnych urzadzeń
˛
i jest
wykonywany przez układy elektroniczne stanowiace
˛ integralna˛ cz˛eść tych urzadzeń.
˛
Natomiast
oprogramowanie systemu operacyjnego i aplikacji użytkownika wykonywane jest przez
procesor systemu komputerowego.
Istnieja˛ także metody pozwalajace
˛ na wykonywanie
specjalnie zaprojektowanych programów na procesorach specjalizowanych karty graficznej w
celu osiagni˛
˛ ecia wi˛ekszej wydajności12 , jednak oprogramowanie tego typu nie jest rozważane
w niniejszej rozprawie. Poniżej przedstawiona jest charakterystyka wymienionych typów
oprogramowania zawierajaca
˛ opis struktury, funkcji oraz wzajemnych interakcji pomi˛edzy
modułami programowymi.
Oprogramowanie wbudowane
Oprogramowanie wbudowane w komputerach typu COTS wyst˛epuje w wielu urzadzeniach
˛
– np. kartach graficznych, kontrolerach RAID, dyskach twardych, czy płytach głównych.
Oprogramowanie to charakteryzuje si˛e wysokim stopniem specjalizacji – jego głównym
celem jest zapewnienie poprawnej pracy obsługiwanych urzadzeń.
˛
Przykładowo zadaniem
oprogramowania wbudowanego w dyski twarde jest realizacja strategii odczytu danych z
wyprzedzeniem do pami˛eci podr˛ecznej oraz opóźnionego zapisu13 .
Wspólna˛ cecha˛ oprogramowania wbudowanego jest to, iż rzadko jest modyfikowane w
produkcyjnym cyklu życia urzadzenia.
˛
Jeżeli aktualizacja jest konieczna, to operacja ta wymaga
przeprowadzenia dedykowanej procedury dla każdego typu sprz˛etu.
Oprogramowanie wbudowane wykonywane jest niezależnie od głównego procesora
systemu komputerowego przez układy elektroniczne poszczególnych urzadzeń
˛
(np. dysku
twardego, adaptera sieciowego). Komunikacja natomiast z zewn˛etrznymi układami odbywa si˛e
10
Opis wektorowej struktury danych dla j˛ezyka C++: http://www.cplusplus.com/reference/vector/vector/
Niemniej
dzi˛eki
lokalności
danych
składowanych
w
wektorze
czas
usuni˛ecia
losowo
wybranego
elementu
z
listy
może
być
mniejszy,
niż
w
przypadku
listy:
http://www.baptiste-wicht.com/2012/12/cpp-benchmark-vector-list-deque/
12
Np. technologia CUDA umożliwia wykonanie oprogramowania na procesorze GPU –
http://www.nvidia.com/object/cuda_home_new.html.
13
Funkcja ta polega na grupowaniu i zmianie kolejności żadań
˛
zapisania danych na dysk w celu optymalizacji
operacji wykonywanych przez głowic˛e dysku twardego.
11
21
przez układy sprz˛etowe np. magistrale lub bezpośrednie przyłaczenie
˛
do przestrzeni adresowej
procesora (Memory mapped I/O).
System operacyjny
System operacyjny jest oprogramowaniem pośredniczacym
˛
mi˛edzy zasobami sprz˛etowymi oraz
oprogramowaniem użytkownika – posiada pełen dost˛ep do zasobów sprz˛etowych i udost˛epnia
je aplikacjom użytkownika za pośrednictwem ujednoliconych interfejsów programistycznych
(patrz [103]). Poniżej jako system operacyjny rozważane jest przede wszystkim jadro
˛ systemu
operacyjnego. Aplikacje narz˛edziowe dostarczane wraz z systemem operacyjnym nie różnia˛ si˛e
sposobem komunikacji z jadrem
˛
od pozostałych aplikacji użytkownika.
System operacyjny wyposażony jest w szereg mechanizmów tworzacych
˛
środowisko
wykonania aplikacji użytkownika.
Podstawowym mechanizmem zaimplementowanym
we współczesnych systemach operacyjnych jest mechanizm procesów.
Proces jest to
instancja wykonania programu wraz z przypisanymi do niej zasobami. System operacyjny
odpowiedzialny jest za załadowanie kodu programu dla każdego procesu, a nast˛epnie przydziela
zasoby takie jak czas procesora, pami˛eć, dost˛ep do pami˛eci masowej lub innych urzadzeń.
˛
Procesy sa˛ zorganizowane w struktur˛e drzewiasta,˛ gdzie każdy proces jest rodzicem dla
uruchomionych przez siebie procesów (dzieci), a korzeniem drzewa jest specjalny proces
uruchamiany przez system operacyjny.
W ramach procesu może być uruchomionych
wiele watków
˛
– podstawowa jednostka wykonywania, dysponujaca
˛ własnym zestawem
rejestrów oraz stosem programowym współdzielaca
˛ pami˛eć z pozostałymi watkami
˛
w ramach
procesu. Zastosowanie watków
˛
oraz procesów pozwala na przetwarzanie równoległe, co
dzi˛eki zastosowaniu procesorów wielordzeniowych pozwala na równoczesne wykonanie kilku
programów, zwi˛ekszajac
˛ w ten sposób wydajność systemu.
Pozostałe usługi realizowane przez system operacyjny to:
zarzadzanie
˛
procesami
(np. wstrzymywanie/wznawianie wykonania), przydział czasu procesora poszczególnym
procesom, synchronizacja i komunikacja mi˛edzyprocesowa, mechanizm sygnałów, zarzadzanie
˛
pami˛ecia,˛ obsługa urzadzeń
˛
peryferyjnych, realizacja połaczeń
˛
sieciowych, obsługa systemu
plików. Całość usług dostarczanych przez system operacyjny stanowi środowisko wykonania
dla aplikacji użytkownika.
Aplikacje użytkownika komunikuja˛ si˛e z systemem operacyjnym za pośrednictwem
wywołań systemowych.
Procedura obsługi żadań
˛
aplikacji użytkownika składa si˛e z
nast˛epujacych
˛
kroków (kursywa˛ zapisane sa˛ kroki wykonywane przez oprogramowanie
systemu operacyjnego):
1. odłożenie na stos programowy parametrów wywołania systemowego,
2. wykonanie dedykowanej instrukcji przerwania programowego,
3. procesor przechodzi z trybu użytkownika do trybu systemu operacyjnego,
4. odczytanie parametrów wywołania systemowego,
22
5. obsługa wywołania,
6. zastapienie
˛
parametrów wywołania systemowego wynikiem wywołania,
7. powrót do trybu użytkownika i wznowienie wykonania.
Oprócz wspomnianych przerwań wywołań systemowych system operacyjny obsługuje
również przerwania sprz˛etowe oraz przerwania wywołane sytuacjami wyjatkowymi.
˛
Przerwania sprz˛etowe służa˛ do obsługi sygnałów pochodzacych
˛
z urzadzeń
˛
zewn˛etrznych
lub magistrali danych – np. klawiatura systemowa, kontroler DMA14 . Obsługa przerwania
sprz˛etowego najcz˛eściej oznacza odebranie danych z urzadzenia
˛
zewn˛etrznego i przekazanie
ich do oczekujacego
˛
na nie procesu. Sytuacje wyjatkowe
˛
zgłaszane sa˛ przez procesor w
przypadku naruszenia zasad bezpieczeństwa lub wykonania nieprawidłowych operacji. Cz˛eść
sytuacji wyjatkowych
˛
jest krytyczna i nie pozwala na dalsze wykonanie kodu – np. wyjatek
˛
dzielenia przez zero lub próba zapisu do pami˛eci tylko do odczytu. Przykłady przerwań,
które system operacyjny może obsłużyć, to pułapka debug (służy do wstrzymania wykonania
procesu i przekazania sterowania do oprogramowania debuggera w celach diagnostycznych),
czy bład
˛ stronicowania15 (ang. page fault). Przy zarzadzaniu
˛
pami˛ecia˛ procesor współpracuje
z układem MMU opisanym w 2.1.1.
W przypadku udanej obsługi sytuacji wyjatkowej
˛
wykonywanie kodu jest wznawiane od instrukcji, która wywołała przerwanie. Jeżeli obsługa nie
jest możliwa, system operacyjny awaryjnie kończy działanie bł˛ednego programu. Gdy źródłem
bł˛edu jest kod systemu operacyjnego implementowane sa˛ różne strategie działania: np. systemy
operacyjne z rodziny Windows wyświetlaja˛ niebieski ekran z informacjami diagnostycznymi
bł˛edu i wymagany jest restart systemu komputerowego, natomiast systemy z rodziny Linux
wypisuja˛ informacje diagnostyczne na wszystkich dost˛epnych konsolach i kończa˛ działanie
watku,
˛
na rzecz którego wykonywany był kod zgłaszajacy
˛ żadanie
˛
– restart systemu nie
jest wymagany, jednak system komputerowy może działać niestabilnie lub nie odpowiadać
na żadania.
˛
Procedura obsługi sytuacji wyjatkowej
˛
w systemie operacyjnym, w przypadku
niepowodzenia przy jej obsłudze, zbiera możliwie najwi˛ecej danych o kontekście wystapienia
˛
wyjatku
˛
i wypisuje je na ekran. Dane te moga˛ zawierać m.in. typ zgłoszonego wyjatku,
˛
zawartość rejestrów procesora, załadowane moduły systemu operacyjnego, dane procesu, czy
stos wywołań funkcji (ang. stack-trace).
System operacyjny może być rozszerzany o dodatkowe funkcje poprzez ładowane w
trakcie działania systemu moduły.
Moduły moga˛ być wykorzystane do rozszerzenia
zbioru wywołań systemowych, implementacji nowych mechanizmów w jadrze
˛
systemu
operacyjnego (np. nowego system plików), jednak najcz˛estszym wykorzystaniem jest
dostarczenie dla systemu operacyjnego sterowników – sa˛ to specjalne programy stanowiace
˛
14
Ang. Direct Memory Access
Jest to cz˛eść mechanizmu pami˛eci wirtualnej, sygnalizujaca
˛ dost˛ep do pami˛eci wirtualnej niedost˛epnej w
danej chwili w pami˛eci fizycznej, a obsługa polega na załadowaniu przez system żadanej
˛
strony pami˛eci z pliku
wymiany.
15
23
łacznik
˛
mi˛edzy systemem operacyjnym, a konkretnym urzadzeniem.
˛
Zadaniem sterowników
jest implementacja określonego interfejsu zdefiniowanego w systemie operacyjnym dla danego
typu urzadzenia,
˛
jednocześnie oprogramowujac
˛ specyficzny dla danego typu urzadzenia
˛
protokół wymiany danych, który może być różny dla urzadzeń
˛
dostarczanych przez różnych
producentów.
Istnieje kilka koncepcji konstrukcji systemu operacyjnego.
Podstawowe z nich to
architektura jadra
˛
monolitycznego oraz mikrojadra.
˛
W ramach architektury monolitycznej
sterowniki oraz wszystkie usługi sa˛ integralna˛ cz˛eścia˛ jadra
˛
systemu operacyjnego.
W
przypadku mikrojadra
˛
kod wykonywany w przestrzeni jadra
˛
systemu operacyjnego jest
ograniczony do minimum – sterowniki oraz inne usługi implementowane sa˛ jako aplikacje
wykonywane w przestrzeni użytkownika, komunikujace
˛ si˛e z jadrem
˛
z użyciem komunikatów.
Istotnym zagadnieniem sa˛ mechanizmy alokowania pami˛eci w systemach operacyjnych.
Istnieje wiele mechanizmów wyspecjalizowanych do obsługi różnych żadań.
˛
Można wyróżnić
dwa główne mechanizmy alokowania pami˛eci – alokowanie na potrzeby współpracy ze
sprz˛etem oraz alokowanie na potrzeby obliczeń.
Mechanizm alokacji pami˛eci do wykorzystania ze sprz˛etem musi spełniać nast˛epujace
˛
wymagania:
1. szybkość – watek
˛ wywołujacy
˛ alokacj˛e nie może być uśpiony w oczekiwaniu na alokacj˛e,
2. przydzielona pami˛eć musi być ciagła
˛ w sensie adresów fizycznych.
Wymaganie 1. jest zwiazane
˛
z koniecznościa˛ sprawnej obsługi urzadzeń
˛
– alokacje cz˛esto
sa˛ wywoływane w procedurach obsługi przerwań generowanych przez urzadzenia
˛
w celu
przygotowania pami˛eci na dane przychodzace
˛ od urzadzeń.
˛
Powolna alokacja w tym
scenariuszu może spowodować problemy wydajnościowe. Natomiast wymaganie 2. wynika z
zastosowania techniki DMA16 , która pozwala na przesyłanie danych bezpośrednio z urzadzenia
˛
(np. dysku twardego) do pami˛eci RAM – wykorzystanie pojedynczego, ciagłego
˛
bloku
pami˛eci fizycznej pozwala na unikni˛ecie wielokrotnego programowania kontrolera DMA.
Implementacje tego mechanizmu alokacji zazwyczaj narzucaja˛ alokowanie bloków pami˛eci o
stałym rozmiarze, co może powodować fragmentacj˛e pami˛eci.
Alokacja na potrzeby obliczeń nie podlega takim restrykcjom jak alokacja pami˛eci dla
sprz˛etu.
Może wykorzystywać wolniejsze algorytmy alokacji, które gwarantuja˛ mniejsza˛
fragmentacj˛e. Ten mechanizm alokacji stosowany jest do przydzielania pami˛eci np. dla kodu,
stosu i danych procesów użytkownika.
Oprócz wymienionych głównych mechanizmów alokacji istnieja˛ również inne
specjalistyczne mechanizmy.
16
Przykładowo sa˛ to mechanizmy zoptymalizowane pod
Ang. Direct Memory Access.
24
katem
˛
przechowywania danych tymczasowych (cache), czy pozwalajace
˛ na wykorzystanie
rozszerzonych przestrzeni adresowych17 .
Aplikacje użytkownika
Aplikacje użytkownika sa˛ to procesy uruchomione w systemie operacyjnym.
Realizuja˛
one główne zadania powierzone systemom komputerowym: np. środowisko stacji roboczej,
serwer WWW, czy serwer baz danych.
Aplikacje te wykorzystuja˛ do swojego działania
środowisko stworzone przez system operacyjny: systemy plików, mechanizmy alokacji
pami˛eci, komunikacj˛e mi˛edzyprocesowa,˛ interfejsy do urzadzeń
˛
sieciowych, mechanizm
bibliotek współdzielonych.
Systemy plików pozwalaja˛ na zapis oraz odczyt plików na urzadzeniach
˛
takich jak dyski
twarde, czy pami˛eci flash. Dzi˛eki abstrakcji systemu operacyjnego aplikacja użytkownika
wykorzystuje jeden interfejs programistyczny niezależnie od typu urzadzenia
˛
przechowujacego
˛
dane.
Mechanizm alokacji pami˛eci pozwala na wykorzystanie przez procesor dowolnej ilości
pami˛eci z przestrzeni adresowej w celu realizacji swoich zadań. System operacyjny udost˛epnia
pami˛eć z wykorzystaniem mechanizmu pami˛eci wirtualnej, co pozwala na wykorzystanie przez
procesy wi˛ekszej ilości pami˛eci, niż jest dost˛epna w systemie komputerowym.
Komunikacja mi˛edzyprocesowa pozwala na wymian˛e danych mi˛edzy procesami (potoki,
wiadomości, pami˛eć współdzielona), synchronizacj˛e (semafor, mutex) oraz przesyłanie
sygnałów. Dzi˛eki tym mechanizmom możliwe jest koordynowanie pracy wielu procesów.
Interfejsy sieciowe pozwalaja˛ na oprogramowanie komunikacji z innymi systemami
komputerowymi. Służa˛ zarówno do udost˛epniania usług jak i korzystania z usług innych
systemów komputerowych.
Ze wzgl˛edu na duży stopień skomplikowania oprogramowania opracowana została
możliwość modularyzacji kodu w postaci bibliotek.
Biblioteki moga˛ być powiazane
˛
z
programem statycznie lub dynamicznie. Statyczne biblioteki sa˛ podczas kompilacji dołaczane
˛
do kompilowanego programu użytkownika. Natomiast biblioteki dynamiczne pozwalaja˛ na
ładowanie bibliotek w trakcie działania programu – podczas kompilacji wykorzystywana
jest jedynie informacja o interfejsie programistycznym biblioteki, na podstawie której w
kodzie skompilowanego programu tworzone sa˛ niezwiazane
˛
symbole stanowiace
˛ punkty
wywołań biblioteki. Ładowanie bibliotek w trakcie działania programu wymaga wsparcia
ze strony systemu operacyjnego.
W systemach operacyjnych z rodziny Unix biblioteki
dynamiczne nazywane sa˛ dynamic shared object, natomiast w systemach z rodziny Windows
dynamic-link library. Zadaniem systemu jest odnalezienie żadanej
˛
biblioteki i załadowanie
17
Rozszerzona przestrzeń adresowa umożliwia wykorzystanie wi˛ecej niż 4GB pami˛eci na
architekturach wykorzystujacych
˛
32-bitowe słowo adresowe.
Implementacja firmy Microsoft polega
na udost˛epnienia przesuwnego okna dost˛epu do pami˛eci.
Szczegóły można znaleźć na stronie
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366527(v=vs.85).aspx
25
kodu wykonywalnego do przestrzeni adresowej procesów18 i powiazanie
˛
symboli z kodem
załadowanej biblioteki. Kod biblioteki jest współdzielony – tzn. ładowany jest tylko raz
w jedno miejsce pami˛eci i udost˛epniany klienckim procesom z zastosowaniem pami˛eci
wirtualnej. Każdy z procesów posiada natomiast swoja˛ instancj˛e danych wykorzystywanych
przez bibliotek˛e.
Aplikacje te moga˛ realizować różne zadania, jednak wszystkie korzystaja˛ z systemu
operacyjnego, jako jedynej drogi komunikacji z urzadzeniami
˛
oraz mi˛edzy soba.˛
2.2. Modele bł˛edów
Systemy komputerowe sa˛ oparte o układy cyfrowe, a ich działanie może być zaburzone
wskutek różnorodnych procesów fizycznych. Powoduje to sytuacje, kiedy system przestaje
prawidłowo wykonywać powierzone mu zadania. Efekty zaburzeń moga˛ rozciagać
˛
si˛e od
trwałej niezdolności systemu do pracy, poprzez tymczasowe generowanie nieprawidłowych
wyników, do maskowania takich sytuacji.
wyst˛epujacych
˛
w systemie jest bład.
˛
Podstawowym modelem nieprawidłowości
W niniejszym podrozdziale scharakteryzowane sa˛
źródła bł˛edów, ich modele oraz wpływ na funkcjonowanie poszczególnych układów systemu
komputerowego.
2.2.1. Źródła bł˛edów
Bł˛edy w systemach cyfrowych wynikaja˛ z budowy nowoczesnych układów oraz warunków
ich eksploatacji. Przeprowadzone niedawno badania firmy Google [94] wykazały, że w 32%
serwerów tej firmy w ciagu
˛ roku wykryto co najmniej jeden bład
˛ przekłamania pami˛eci.
W [16, 27, 28] przedstawiono prognoz˛e zwi˛ekszenia liczby tego typu bł˛edów wraz ze
stopniem upakowania układów scalonych. Dodatkowo systemy cyfrowe sa˛ eksploatowane
w wielu różnych środowiskach, które mog˛e mieć niekorzystny wpływ na ich działanie –
zaburzenia w działaniu moga˛ być spowodowane przez promieniowanie kosmiczne, czastki
˛
alfa,
impulsy elektromagnetyczne, temperatur˛e, czy degradacj˛e układów wynikajac
˛ a˛ ze starzenia si˛e
materiałów użytych do ich wytworzenia.
W [59] przedstawiono wpływ wzrostu temperatury na cz˛estotliwość bł˛edów w prostych
układach składajacych
˛
si˛e z przerzutników wykonanych w technologii 40 nm. Zbadano, że
przy temperaturze 80 ◦ C cz˛estotliwość wyst˛epowania bł˛edów może wzrosnać
˛ dwukrotnie,
a przy temperaturze 120 ◦ C trzykrotnie przy eksponowaniu układu na promieniowanie
neutronowe.
Dodatkowo w badaniach prowadzonych w Instytucie Telekomunikacji
Politechniki Warszawskiej (patrz [68]) obserwowano znaczacy
˛ wzrost przekłamań w wynikach
18
Kod biblioteki jest specjalnie przygotowany pod katem
˛
możliwości załadowania pod różne adresy pami˛eci
– jest to tzw. kod relokowalny.
26
generowanych przez układ szyfrujacy
˛ przy symulowaniu bł˛edów zegara nawet przy niewielkich
zmianach temperatury pracy układu.
W [94] przedstawiono analiz˛e wykazujac
˛ a,˛ że w modułach pami˛eci RAM po 24 miesiacach
˛
użytkowania cz˛estotliwość wyst˛epowania przekłamań pami˛eci rośnie od 1,7 do 3,5 raza w
zależności od konkretnego produktu. Badania te również potwierdzaja˛ korelacj˛e cz˛estotliwości
wyst˛epowania bł˛edów wraz ze wzrostem temperatury.
Przytoczone badania świadcza˛ o wadze problemu wyst˛epowania bł˛edów.
Niemniej
wiele konfiguracji systemów komputerowych nie jest badanych pod katem
˛
wyznaczenia
charakterystyki wrażliwości na bł˛edy w różnych warunkach eksploatacji.
2.2.2. Charakterystyka modeli bł˛edów
Modele bł˛edów moga˛ być rozważane na różnych poziomach abstrakcji: fizycznym,
logicznym oraz aplikacyjnym.
Najniższym poziomem jest fizyczny model układu.
Rozpatrywane sa˛ w nim elementy elektroniczne pod katem
˛
podatności na wymienione w 2.2.1
niekorzystne oddziaływania. W szczególności badany jest mechanizm przełożenia si˛e tych
oddziaływań na nieprawidłowa˛ prac˛e układu: np. fizyczne uszkodzenie układu elektronicznego,
zwarcia lub rozwarcia ścieżek, czy zwi˛ekszenie pradów
˛
upływowych.
Istotnym zagadnieniem jest wyznaczanie (najcz˛eściej eksperymentalne [8, 59]) propagacji
nieprawidłowości na poziomie fizycznym na modele bł˛edów logicznych. Bł˛edy logiczne
rozumiane sa˛ jako nieprawidłowy stan rozpatrywanego układu. Przykładami takich modeli jest
sklejenie z 0/1 (stuck-at-0/stuck-at-1), bł˛edy sprz˛eżeń, czy bit-flip. Warto zaznaczyć, że bł˛edy
fizyczne moga˛ nie być łatwo modelowane jako bł˛edy warstwy logicznej (np. przekształcenie
układu kombinacyjnego w sekwencyjny).
Bł˛edy warstwy logicznej natomiast propaguja˛ si˛e na bł˛edy aplikacyjne, czyli inny przebieg
wykonania aplikacji w stosunku do przebiegu niezaburzonego. Przykładowo bł˛edy logiczne
przekłamań bitów w kodzie instrukcji procesora moga˛ powodować bł˛edy aplikacyjne zmian w
argumentach instrukcji lub zamienić instrukcj˛e na inna˛ – w przypadku architektur o zmiennej
długości instrukcji może to spowodować wr˛ecz lawinowe przekłamanie kolejnych instrukcji
w zwiazku
˛
z odczytywaniem instrukcji spod nieprawidłowych adresów. Natomiast bł˛edy w
strukturach danych moga˛ uszkodzić dane właściwe lub dane adresowe – skutki takich bł˛edów
sa˛ ściśle zwiazane
˛
z typem struktury danych oraz właściwościami przechowywanych danych.
Bł˛edy aplikacyjne objawiaja˛ si˛e generowaniem nieprawidłowych wyników, niedost˛epnościa˛
usług, awariami (wykonanie przez program nieprawidłowej operacji kończacej
˛
w trybie
awaryjnym jego działanie) lub sa˛ one maskowane podczas wykonania oprogramowania. Warto
zaznaczyć, że niektóre typy danych sa˛ w naturalny sposób odporne na bł˛edy – np. bład
˛ w pliku
dźwi˛ekowym może spowodować niesłyszalne dla słuchaczy przekłamania.
27
Bł˛edy można scharakteryzować również według czasu utrzymywania si˛e w systemie: bł˛edy
trwałe, bł˛edy przemijajace
˛ oraz bł˛edy migoczace
˛ (patrz [96]).
Bł˛edy trwałe sa˛ wynikiem uszkodzeń układów cyfrowych.
Układy te działaja˛
nieprawidłowo z powodu np. zwarcia lub przepalenia cz˛eści wewn˛etrznych połaczeń,
˛
wi˛ec
ich naprawienie jest niemożliwe.
Jedna˛ z metod redukcji efektów takich bł˛edów jest
redundancja układowa, umożliwiajaca
˛ przej˛ecie funkcji niedziałajacego
˛
układu przez zapasowe
komponenty.
Bł˛edy przemijajace
˛
powstaja˛ w wyniku chwilowego zaburzenia pracy systemu –
np. tymczasowe obce pola elektromagnetyczne, zakłócenia zasilania, promieniowanie
kosmiczne. Charakteryzuja˛ si˛e tym, że układ nie jest uszkodzony, a jedynie jednorazowo
zmienia si˛e jego wewn˛etrzny stan. Ponowne uruchomienie systemu pozwala w tej sytuacji
przywrócić prawidłowe działanie.
Bł˛edy migoczace
˛ sa˛ to bł˛edy powodujace
˛ tymczasowe nieprawidłowe działanie układu, tak
jak w przypadku bł˛edów trwałych, niemniej możliwy jest powrót do prawidłowego działania
układu po samoczynnym ustapieniu
˛
bł˛edu migoczacego.
˛
Detekcja bł˛edów tego typu jest
możliwa wyłacznie
˛
w okresie aktywności bł˛edu. Utrudnia to diagnostyk˛e układu z uwagi
na konieczność okresowego przeprowadzania testów, aby możliwe było zaobserwowanie
nieprawidłowego działania układu.
2.2.3. Bł˛edy jednostek przetwarzajacych
˛
Nowoczesne procesory sa˛ układami cyfrowymi o dużym stopniu upakowania.
W
strukturach procesora znajduje si˛e wiele jednostek o dedykowanych funkcjach: dekoder
instrukcji, potoki wykonania, układ przewidywania skoków, pami˛eć podr˛eczna, jednostki
arytmetyczne i zmiennoprzecinkowe. Wiele z tych jednostek jest niedost˛epnych w modelu
programistycznym procesora.
Opracowywanie modeli bł˛edów logicznych procesora jest
zadaniem trudnym. Badania przeprowadzone w [43, 65] wykazuja,˛ że bł˛edy przekłamań bitów
w ukrytych rejestrach (poziom architektury) moga˛ powodować bł˛edy innego typu na poziomie
logicznym funkcjonowania procesora. Przykładowo uszkodzenie jednego z rejestrów może
objawić si˛e na poziomie logicznym uszkodzeniem kilku rejestrów ze wzgl˛edu na wykorzystanie
registers renaming (patrz [51]). Niemniej możliwe jest rozpatrywanie cz˛eści układów procesora
jako układów pami˛eci – w szczególności dotyczy to rejestrów, pami˛eci podr˛ecznej, układu
MMU oraz układu przewidywania skoków. Dzi˛eki temu możliwe jest zastosowanie modeli
bł˛edów opisanych w 2.2.4.
Interesujacym
˛
zagadnieniem sa˛ przekłamania w pami˛eci podr˛ecznej stanowiacej
˛ integralna˛
cz˛eść procesora ze wzgl˛edu na jej redundantny charakter wzgl˛edem pami˛eci operacyjnej.
Wystapienie
˛
bł˛edów zarówno po stronie pami˛eci operacyjnej i podr˛ecznej może zostać w
sposób naturalny zamaskowane:
28
— przekłamanie w pami˛eci podr˛ecznej jest zamaskowane, jeżeli: dane te nie zostały odczytane
i zostana˛ usuni˛ete z pami˛eci podr˛ecznej bez zapisywania do pami˛eci głównej (dane te nie
były oznaczone w pami˛eci cache jako dirty),
— przekłamanie w pami˛eci głównej jest zamaskowane, gdy prawidłowa kopia danych
znajdowała si˛e w pami˛eci podr˛ecznej (kopia ta może być wykorzystana przy obliczeniach)
i została nadpisana nowa˛ wartościa,˛ co oznacza nadpisanie zaburzonych danych w pami˛eci
głównej.
2.2.4. Bł˛edy pami˛eci operacyjnej
Bł˛edy pami˛eci moga˛ być spowodowane bł˛edami komórek pami˛eci lub układów
adresujacych.
˛
Przykładowe bł˛edy jednostek adresujacych
˛
to: wybór bł˛ednej komórki pami˛eci,
nieudany wybór zadanej komórki pami˛eci, wybór jednej z komórek pami˛eci przez wi˛ecej niż
jeden adres, jednoczesny wybór kilku komórek pami˛eci przez jeden adres, a wynik jest funkcja˛
wartości wybranych komórek.
Natomiast podstawowe modele bł˛edów komórek pami˛eci to (na podstawie [96]): bł˛edy
sklejeń z 0/1 – komórka pami˛eci zawsze ma t˛e sama˛ wartość; bład
˛ typu bit-flip – negacja
wartości przechowywanej w komórce pami˛eci; bład
˛ ulotności – zapami˛etana informacja w
komórce jest tracona na skutek pradów
˛
upływowych; bł˛edy tranzycji – niemożność zmiany
stanu z 1 na 0 lub z 0 na 1; bł˛edy sprz˛eżeń – wartość przechowywana w komórce lub jej
zdolność do zmiany wartości jest zależna od przechowywanych w innych komórkach.
Osobna˛ kategoria˛ bł˛edów sa˛ bł˛edy charakterystyczne dla poszczególnych technologii
wytwarzania pami˛eci (patrz [57]): opóźnienie czasu dost˛epu; opóźnienie wzmacniacza odczytu
– na wyjściu pojawia si˛e stan poprzednich bitów; opóźnienie zapisu – po dokonaniu zapisu
kolejna operacja jest dokonywana na tej samej komórce pami˛eci pomimo zmiany adresu; bład
˛
niezrównoważenia – bł˛edna kwalifikacja wartości odczytywanej komórki, jeżeli wi˛ekszość
komórek na tej samej linii adresowej ma stan odmienny od odczytywanej komórki.
Popularna˛ metoda˛ wykrywania i ewentualnego zapobiegania bł˛edom pami˛eci w cyklu
życia systemu jest stosowanie kodów korekcyjnych – sa˛ to pami˛eci ECC19 RAM (patrz
[64]).
Technika ta polega na rozszerzeniu pami˛eci o dodatkowe komórki, w których
sa˛ przechowywane dodatkowe dane kodu korekcyjnego, pozwalajace
˛ na poprawienie i
wykrywanie bł˛edów.
Liczba wykrywanych i poprawianych bł˛edów pami˛eci różni si˛e w
zależności od zastosowanego kodu. Weryfikacja i ewentualna korekta zawartości komórek
pami˛eci odbywa si˛e przy odczycie. Niektóre implementacje tej techniki periodycznie skanuja˛
cała˛ przestrzeń adresowa˛ pami˛eci w celu wyeliminowania efektu kumulacji bł˛edów (tzw. error
scrubbing).
19
Ang. Error-correcting code.
29
Pami˛eci ECC pozwalaja˛ skutecznie zwi˛ekszyć niezawodność systemów komputerowych
– pozwalaja˛ na korekcj˛e bł˛edów przemijajacych
˛
oraz wykrycie bł˛edów trwałych.
W
[94] przedstawiono szczegółowe badanie nad cz˛estotliwościa˛ zgłaszania pojedynczych
bł˛edów pami˛eci maskowanych przez ECC oraz podwójnych bł˛edów pami˛eci w środowisku
produkcyjnym. Bł˛edy podwójne powodowały eliminacj˛e modułu pami˛eci z dalszych badań
i zastapienie
˛
go nowym modułem.
W ciagu
˛ roku w 32,2% maszyn obj˛etych badaniem
zaobserwowano przynajmniej jeden bład
˛ pojedynczy (8,2% obj˛etych badaniem modułów
pami˛eci) oraz w 1,29% maszyn wykryto bład
˛ podwójny (0,22% modułów pami˛eci). Przy dużej
liczbie maszyn produkcyjnych koszt wymiany wadliwych modułów pami˛eci stanowi istotny
koszt utrzymania.
2.2.5. Bł˛edy urzadze
˛ ń zewn˛etrznych
Modele bł˛edów urzadzeń
˛
zewn˛etrznych stanowia˛ szeroka˛ dziedzin˛e badań, które sa˛
systematycznie pogł˛ebiane.
Każde z urzadzeń
˛
dysponuje swoim odr˛ebnym profilem
najcz˛eściej zgłaszanych bł˛edów.
Bł˛edy urzadzeń
˛
zewn˛etrznych moga˛ być zwiazane
˛
zarówno z przekłamaniami danych lub nieprawidłowym zachowaniem przy komunikacji z
systemem operacyjnym. Warto zaznaczyć, że bł˛edy moga˛ wystapić
˛
zarówno w urzadzeniu
˛
zewn˛etrznym, jak i kontrolerze stanowiacym
˛
integralna˛ cz˛eść systemu komputerowego.
Przykładami zaburzania danych moga˛ być przekłamania jak w przypadku bł˛edów pami˛eci
(typu bit-flip lub sklejeń z 0/1).
Natomiast bł˛edy behawioralne moga˛ być modelowane
jako niezgłaszane/nadmiarowe przerwania, zachowanie niezgodne z protokołem współpracy
z urzadzeniem
˛
(np. brak odpowiedzi na wysyłane komendy).
Bł˛edy danych w szczególności dotycza˛ urzadzeń
˛
przechowywania danych oraz urzadzeń
˛
komunikacyjnych.
Urzadzenia
˛
przechowywania danych to dyski twarde, pami˛eci USB,
czy pami˛eci Compact Flash. Przykładowo dyski twarde wykorzystuja˛ talerze z nośnikiem
magnetycznym, na którym zapisywane sa˛ informacje. Urzadzenia
˛
te zapisuja˛ dane na nośniku z
zastosowaniem kodów korekcyjnych, pomimo to bł˛edy nienaprawialne wyst˛epuja.˛ W badaniu
opisanym w [106] w przeciagu
˛ 12 miesi˛ecy 0,04% spośród 387 840 głowic dysków twardych
natrafiło na bł˛edy nienaprawialne. W krytycznych zastosowaniach wykorzystuje si˛e macierze
dyskowe typu RAID.
Bł˛edy danych w urzadzeniach
˛
komunikacyjnych najcz˛eściej zwiazane
˛
sa˛ z bł˛edami kanału
przesyłu informacji. W przypadku sieci komputerowych duża˛ rol˛e odgrywa zastosowany
protokół komunikacji – UDP20 lub TCP21 . Protokół UDP nie zakłada żadnej kontroli
spójności danych, natomiast TCP posiada takie mechanizmy wbudowane.
W Instytucie
Informatyki Politechniki Warszawskiej prowadzono badania nad tymi mechanizmami i w [38]
20
21
Ang. User Datagram Protocol.
Ang. Transmission Control Protocol.
30
przedstawiono zależność opóźnienia transmisji TCP od liczby bł˛edów w kanale transmisyjnym.
Warto zaznaczyć, że pomimo zastosowania kodów korekcyjnych w TCP wcia˛ż istnieje
możliwość przekłamania danych i prowadzone sa˛ badania nad poprawa˛ tego mechanizmu (patrz
[60]).
Oprócz bł˛edów danych przechowywanych lub przesyłanych przez urzadzenie
˛
moga˛
wystapić
˛
także bł˛edy protokołu współpracy urzadzenia
˛
z systemem operacyjnym.
Bł˛edy
te moga˛ być modelowane jako nadmiarowe przerwania (patrz [8]), bł˛edy danych protokołu
(np. bł˛edy w ramkach protokołu SATA22 ) lub w przypadku urzadzeń
˛
korzystajacych
˛
z DMA
zapisywanie danych pod inny adres niż przeznaczony do wykorzystania przez urzadzenie.
˛
2.3. Mechanizmy zwi˛ekszania niezawodności
Mechanizmy zwi˛ekszania niezawodności spełniaja˛ nast˛epujace
˛
funkcje:
maskowanie oraz tolerowanie bł˛edów.
systemie.
detekcja,
Detekcja jest to wykrycie istnienia bł˛edu w
Maskowanie jest to zdolność do usuni˛ecia efektu bł˛edu zanim b˛edzie miał
on wpływ na działanie systemu.
Natomiast tolerowanie bł˛edów jest to mechanizm
umożliwiajacy
˛ prawidłowa˛ prac˛e systemu pomimo wyst˛epowania bł˛edów. Można wyróżnić
kilka podstawowych technik zwi˛ekszania niezawodności: redundancja masowa, redundancja
cz˛eściowa, redundancja informacji, asercje, mechanizmy typu watchdog, izolacja oraz
mechanizmy typu checkpoint.
Wymienione techniki moga˛ realizować jedna˛ lub wi˛ecej
funkcji niezawodności. Techniki zwi˛ekszania niezawodności moga˛ być implementowane jako
mechanizmy sprz˛etowe, programowe lub programowo-sprz˛etowe.
Redundancja masowa jest to technika polegajaca
˛ na wykorzystaniu wielu modułów w
celu realizacji tego samego zadania lub wielokrotnym wykonaniu zadania przez jeden moduł,
w przypadku założenia wyst˛epowania bł˛edów przemijajacych.
˛
Wyniki działania wszystkich
modułów moga˛ brać udział w głosowaniu (redundancja bierna) – opracowanych jest wiele
algorytmów przeprowadzania głosowania (patrz [96]).
Alternatywnym rozwiazaniem
˛
jest
zastosowanie detektora bł˛edów, który testuje wyniki działania modułów i w przypadku
wykrycia bł˛edu dokonuje rekonfiguracji układu np. poprzez wyłaczenie
˛
zasilania wadliwych
modułów (redundancja aktywna).
Przykładem redundancji masowej realizowanej w
oprogramowaniu jest N-version programming (patrz [88]). Opis badań majacych
˛
na celu
zastosowania tego typu rozwiazań
˛
w systemach operacyjnych można znaleźć w [79, 111].
Istotna˛ wada˛ rozwiazań
˛
tego typu jest duży narzut na koszty tworzenia tego typu rozwiazań.
˛
Redundancja cz˛eściowa różni si˛e od redundancji masowej ograniczonym zakresem
replikacji tylko do cz˛eści zasobów – przykładowo jest to zastosowanie w systemie
komputerowym macierzy dyskowych RAID lub wyposażenie dysków twardych w zapasowe
22
Ang. Serial Advanced Technology Attachment.
31
cylindry na etapie produkcji. Istotne jest również wprowadzenie mechanizmów detekcji i
rekonfiguracji systemu. Macierze RAID pozwalaja˛ na maskowanie bł˛edów w trakcie pracy
systemu, natomiast zapasowe cylindry dysku twardego moga˛ być aktywowane jako zamiennik
uszkodzonego cylindra (niemniej liczba zapasowych cylindrów jest ograniczona i w przypadku
długiej pracy systemu taka zamiana może już nie być możliwa).
Redundancja informacji polega na wzbogacaniu danych o dodatkowe informacje
pozwalajace
˛ na dokonanie korekcji ewentualnych bł˛edów. Technika ta jest w szczególności
wykorzystywana przy przesyłaniu informacji przez kanał z zakłóceniami, co pozwala
zniwelować negatywne efekty. Niemniej techniki te moga˛ być również wykorzystane do
zabezpieczania danych (np. RAID 3, 4, 5, 6 lub pami˛eci RAM ECC). Technika ta należy do
rodziny technik forward recovery.
Umieszczanie asercji w oprogramowaniu służy sygnalizacji naruszeń niezmienników
działania oprogramowania. Umożliwia to wykrycie nieprawidłowego stanu systemu i podj˛ecie
działań naprawczych. Zagadnienie umieszczania asercji w kodzie i oceny ich skuteczności jest
przedmiotem badań prowadzonych w Instytucie Informatyki Politechniki Warszawskiej (patrz
[82, 83]).
Mechanizmy typu watchdog polegaja˛ na tworzeniu systemów monitorujacych
˛
działanie
systemu podstawowego.
Monitorowanie zazwyczaj odbywa si˛e poprzez wygenerowanie
żadania
˛
i sprawdzenie odpowiedzi monitorowanego systemu z pewnym wzorcem –
nieprawidłowości sa˛ wykrywane poprzez stwierdzenie braku odpowiedzi lub jej rozbieżności
wzgl˛edem wzorca.
Warto zaznaczyć, że mechanizmy typu watchdog moga˛ być
implementowane zarówno sprz˛etowo, jak i programowo (patrz [30]).
Izolacja w zwi˛ekszaniu niezawodności służy odseparowaniu poszczególnych modułów
oprogramowania lub sprz˛etu. Celem jest możliwość odłaczenia
˛
nieprawidłowo działajacego
˛
modułu, tak aby działanie systemu było niezakłócone podczas dalszej eksploatacji.
Przykładowo system operacyjny realizuje t˛e koncepcj˛e poprzez mechanizm procesów, gdzie
awaria jednego nie ma wpływu na działanie pozostałych (szerzej w 5.1).
Nieprawidłowości wykryte przy użyciu asercji lub mechanizmów watchdog wymagaja˛
podj˛ecia akcji naprawczych majacych
˛
na celu usuni˛ecie zaburzeń i ewentualna˛ diagnostyk˛e.
Najprostsza˛ metoda˛ post˛epowania w przypadku wykrycia nieprawidłowości jest wymuszenie
ponownego uruchomienia systemu komputerowego.
Rozwiazanie
˛
to jednak jest
niedopuszczalne w niektórych sytuacjach z uwagi na utrat˛e cz˛eści wyników i niedost˛epność
systemu w czasie ponownego uruchamiania. Bardziej zaawansowana˛ technika˛ jest odtwarzanie
systemu z kopii historycznej – jest to technika checkpointing. Technika ta jest przedmiotem
wielu badań opisanych w [29, 72, 87, 109]. Ciekawym zastosowaniem tej techniki jest migracja
– tzn. kopia historyczna jest odtwarzana na innym systemie komputerowym, ponieważ system
32
pierwotny uległ trwałemu uszkodzeniu (patrz [81, 86]). Checkpointing należy do rodziny
technik backward recovery.
Warto zaznaczyć, że podejmowane sa˛ próby tworzenia bibliotek programowych,
umożliwiajacych
˛
wzbogacenie istniejacego
˛
oprogramowania o funkcje zwi˛ekszajace
˛
niezawodność (patrz [39, 76]).
Opracowanie tego typu rozwiazań
˛
jest pozwoliłoby na
szerokie wykorzystanie mechanizmów, które dost˛epne sa˛ wyłacznie
˛
w specjalistycznych
systemach.
2.4. Symulacja bł˛edów w badaniu niezawodności systemów
komputerowych
Podstawa˛ badań niezawodności systemów komputerowych jest analiza produkcyjnych
systemów. Wykonywana jest ona na podstawie raportów o awariach. W [69, 70, 71, 94, 97, 113]
przedstawione sa˛ przykładowe projekty majace
˛ na celu zbieranie tego typu danych. Jest
to najbardziej wartościowe źródło wiedzy ze wzgl˛edu na możliwość zbierania informacji
o działaniu systemu w warunkach jego rzeczywistego użytkowania. Istotnym problemem
opisanym w [113] jest trudność w interpretacji zebranych w ten sposób danych – wynika to z
faktu, że raporty o bł˛edach oprogramowania moga˛ być wywołane zarówno bł˛edami programów,
bł˛edami konfiguracyjnymi, a także usterkami sprz˛etu.
W celu umożliwienia szczegółowych badań nad efektami bł˛edów opracowane
zostały techniki wstrzykiwania bł˛edów umożliwiajace
˛ prowadzenie badań w warunkach
laboratoryjnych.
Sa˛ to mi˛edzy innymi metody takie jak celowe eksponowanie układów
cyfrowych na niekorzystne warunki – pole elektromagnetyczne, promieniowanie czastek
˛
alfa, naświetlanie laserem, modyfikowanie ścieżek drukowanych układu, czy też akceleracja
procesów starzenia si˛e układów poprzez podwyższona˛ temperatur˛e (patrz [8, 59, 92]). Badania
tego typu sa˛ wartościowym narz˛edziem weryfikacji odporności układów przed użyciem ich
w produkcji, niemniej obarczone sa˛ one pewnymi ograniczeniami: duży koszt aparatury
koniecznej do przeprowadzania tego typu eksperymentów, mała kontrola nad procesem
wstrzykiwania bł˛edów oraz potencjalne ryzyko trwałego uszkodzenia testowanych układów.
W zwiazku
˛
z opisanymi trudnościami popularność zdobyły techniki programowego
wstrzykiwania bł˛edów – SWIFI. Techniki te rozwijane sa˛ od kilkudziesi˛eciu lat [8, 19,
75], jednak wcia˛ż pozwalaja˛ na uzyskiwanie nowych, wartościowych rezultatów. Instytut
Informatyki Politechniki Warszawskiej posiada bogate doświadczenie w tej dziedzinie nauki
(m.in. [40, 41, 42, 96]).
W [8] przedstawiono studium nad porównaniem technik fizycznego wstrzykiwania
bł˛edów oraz SWIFI. Autorzy przedstawiaja˛ przypadki, gdy zastosowanie obu metod skutkuje
podobnymi efektami, oraz takie gdzie rezultaty si˛e różnia.˛
33
Rozbieżności pojawiały si˛e
przede wszystkim w zwiazku
˛
z ograniczeniem modeli bł˛edów wstrzykiwanych metoda˛
SWIFI – w jednym z eksperymentów fizycznego zaburzania zaobserwowano zgłaszanie przez
sprz˛et niemaskowanych przerwań, które nie były obserwowane przy bł˛edach symulowanych
metoda˛ SWIFI. Oznacza to komplementarność technik fizycznych oraz SWIFI. Zaletami
technik fizycznych jest odwzorowanie rzeczywistych bł˛edów, natomiast SWIFI pozwala
na przeprowadzanie eksperymentów z wi˛eksza˛ sterowalnościa,˛ obserwowalnościa˛ oraz
możliwościa˛ powtarzania przebiegu eksperymentu – niemniej modele SWIFI powinny być
uzupełniane o nowe modele bł˛edów i zaburzane komponenty w celu pokrycia możliwie
szerokiego spektrum przypadków testowych. O popularności metod SWIFI może świadczyć
pojawianie si˛e prac zmierzajacych
˛
do ujednolicenia metod opisu profili wstrzykiwania (patrz
[9, 55]) rozumianych jako sposób odtworzenia charakterystyki bł˛edów rzeczywistych urzadzeń
˛
przez narz˛edzia SWIFI. Dodatkowo opracowywane sa˛ uniwersalne formaty konfiguracji
eksperymentów (patrz [31, 36]), które maja˛ na celu uniezależnić definicj˛e eksperymentu
od konkretnej platformy SWIFI umożliwiajac
˛ uruchamianie tych samych eksperymentów na
różnych platformach w celu weryfikacji uzyskiwanych rezultatów.
Rozpatrujac
˛ metody typu SWIFI należy zaznaczyć, że metody te sa˛ ukierunkowane na
wstrzykiwanie bł˛edów według zdefiniowanych modeli w ściśle określona˛ przestrzeń testowania.
Oznacza to wi˛eksza˛ kontrol˛e nad procesem wstrzykiwania bł˛edów w porównaniu z metodami
wykorzystujacymi
˛
fizyczne zaburzanie działania układów, niemniej zdefiniowana przestrzeń
testowania jest zazwyczaj ograniczona i charakterystyczna dla każdego z opracowanych
narz˛edzi. W celu ilustracji tego zagadnienia opisane zostały przykłady różnych narz˛edzi typu
SWIFI.
Podstawowa˛ rodzina˛ narz˛edzi typu SWIFI sa˛ narz˛edzia operujace
˛ na modelach testowanych
urzadzeń.
˛
Modele te moga˛ być opracowane m.in. w j˛ezykach takich jak VHDL23 , czy Matlab.
Opis narz˛edzi tego typu można znaleźć w pracach [43, 47, 63, 90, 95, 102, 104, 105, 110].
Wspólna˛ cecha˛ tych rozwiazań
˛
jest modelowanie układów i oprogramowania wbudowanego o
ściśle określonych funkcjach. Rozwiazania
˛
te sa˛ rzadko stosowane do badania niezawodności
komponentów COTS z uwagi na duży stopień ich skomplikowania, co znaczaco
˛ spowalnia
proces przeprowadzania eksperymentów.
Osobna˛ rodzina˛ narz˛edzi SWIFI sa˛ narz˛edzia ukierunkowane na konkretna˛ platform˛e
sprz˛etowa˛ lub programowa.˛ Do nich można zaliczyć oprogramowanie FITS opracowane w
Instytucie Informatyki Politechniki Warszawskiej (patrz [40, 41, 42]). Proces wstrzykiwania
bł˛edów zaimplementowany w tym rozwiazaniu
˛
polega na wykorzystaniu mechanizmów
debuggowania dost˛epnych w systemach operacyjnych (np. Windows API24 , ptrace25 ) do
kontroli i zaburzania wykonania testowanego oprogramowania.
23
24
25
J˛ezyk opisu układów cyfrowych.
http://msdn.microsoft.com/en-us/library/ms809754.aspx
http://linux.die.net/man/2/ptrace
34
W [112] przedstawione zostało porównanie trzech metod modelowania bł˛edów w
SWIFI: modyfikacja wartości parametrów wywołań procedur, zamiana wartości zwracanych
przez procedury oraz przekłamania pojedynczych bitów w dowolnych miejscach pami˛eci.
Przekłamania parametrów wywołań procedur imituja˛ propagacj˛e bł˛edów wygenerowanych
w rejestrach urzadzeń
˛
do programów.
bł˛edy programistyczne.
Zaburzanie wartości zwracanych symuluje
Natomiast zaburzanie pami˛eci stanowi model nieprawidłowości
wyst˛epujacych
˛
w pami˛eci RAM. Badania te ilustruja˛ różne podejścia do wstrzykiwania bł˛edów
i autorzy wskazuja˛ na najwi˛eksza˛ skuteczność (w sensie liczebności typów zgłaszanych awarii)
metody zaburzania losowych komórek pami˛eci.
W [115] opisany został eksperyment wykorzystujacy
˛
przekłamania na poziomie
pojedynczych bitów do zaburzania różnych typów danych składowanych w pami˛eci w celu
porównania ich wrażliwości na bł˛edy. Wyniki uzyskane przez autorów wskazuja,˛ że dane
alokowane dynamicznie sa˛ wielokrotnie bardziej wrażliwe na zaburzenia, niż dane statyczne.
Zagadnieniem wartym uwagi jest stosowanie SWIFI do ewaluacji niezawodności systemów
operacyjnych, ponieważ nie jest możliwe wykorzystanie mechanizmów debuggowania i
konieczne jest opracowywanie rozwiazań
˛
innego typu. Wiele koncepcji testowania systemów
operacyjnych wia˛że si˛e z testowaniem sterowników obsługiwanych urzadzeń
˛
(patrz 2.1.2).
Np. w [33] przedstawiono rozwiazanie
˛
wprowadzajace
˛ bł˛edy do sterowników DMA, a w
[38, 58] opisano metody zaburzania danych pochodzacych
˛
z sieci. Rozwiazania
˛
skupiajace
˛
si˛e na zaburzaniu parametrów wywołań procedur wykonywanych w przestrzeni jadra
˛ systemu
operacyjnego opracowano w [5, 38, 61, 62]. Jednakże niewiele jest opracowań pozwalajacych
˛
całościowo badać systemy operacyjne. W [34] zaprezentowane jest nast˛epujace
˛ podejście: do
symulowania bł˛edów wykorzystywany jest moduł systemu operacyjnego, natomiast kontrola
eksperymentu powierzona jest osobnej maszynie, która rejestruje wynik symulacji bł˛edu na
maszynie realizujacej
˛ eksperyment. Podejście to ma szereg wad: konieczne jest opracowanie
modułu symulujacego
˛
bł˛edy zależnego od testowanego systemu komputerowego, wymagany
jest dodatkowy system komputerowy wykorzystywany jako nadzorca (wia˛że si˛e to z kosztami
i utrudnia skalowalność) oraz ograniczone sa˛ możliwości badania efektów awarii. W [78]
przedstawiono rozwiazanie
˛
niewymagajace
˛ implementacji dedykowanego modułu systemu
operacyjnego symulujacego
˛
bł˛edy – praca opisuje badanie systemu wbudowanego opartego
o FPGA26 działajacego
˛
pod kontrola˛ systemu GNU/Linux i wyposażonego w możliwość
symulowania bł˛edów poprzez modyfikacj˛e konfiguracji układu FPGA. W przypadku ch˛eci
równoległego przeprowadzania eksperymentów rozwiazanie
˛
to również wymaga nakładu
kosztów na dodatkowe jednostki układów przeprowadzajacych
˛
testy. Wymienione problemy
sa˛ cz˛eściowo rozwiazane
˛
przez dwa projekty opisane w [18] oraz [93].
26
Ang. Field Programmable Gate Array.
35
W [18]
wykorzystany został emulator systemu operacyjnego User Mode Linux27 , gdzie odpowiednio
zmodyfikowane jadro
˛
systemu operacyjnego uruchamiane jest jako proces użytkownika, a
wstrzykiwanie bł˛edów odbywa si˛e poprzez interfejs ptrace. Wada˛ takiego rozwiazania
˛
jest
konieczność modyfikowania testowanego oprogramowania (źródeł jadra
˛ systemu operacyjnego)
w celu uruchomienia na platformie testowej oraz możliwość testowania wyłacznie
˛
jednego
systemu operacyjnego na jednej z dwóch obsługiwanych architektur sprz˛etowych: x86 i
AMD64. Natomiast w [93] opisano prób˛e stworzenia w pełni deterministycznego emulatora
systemu komputerowego, wzbogacajac
˛ go o możliwość integracji z modułami sprz˛etowymi
modelowanymi w j˛ezyku VHDL. Proces wstrzykiwania bł˛edów polega na zaburzaniu pracy
wspomnianych modułów sprz˛etowych i obserwowaniu zachowania systemu operacyjnego
uruchomionego w emulowanym środowisku. Rozwiazanie
˛
to jest bardzo obiecujace,
˛ jednak
ogranicza si˛e tylko do testowania układów.
Reasumujac,
˛ narz˛edzia typu SWIFI sa˛ uznana˛ w środowisku naukowym metoda˛
ewaluacji niezawodności oprogramowania, jednak konieczne jest ciagłe
˛ rozwijanie scenariuszy
testowych oraz metod analizy wyników.
Według autora, na podstawie przeanalizowanej
literatury, istotnym brakiem we współczesnych narz˛edziach SWIFI sa˛ ograniczone możliwości
ewaluacji niezawodności oprogramowania systemu operacyjnego. Oprogramowanie systemu
operacyjnego jest krytyczne dla prawidłowego działania systemu komputerowego, a jego
ewaluacja jest wielopłaszczyznowa: m.in. wrażliwość na bł˛edy pami˛eci, wrażliwość na
bł˛edy urzadzeń,
˛
stabilność systemu, czy porównanie cech kodu tego samego systemu
operacyjnego skompilowanego na różne platformy sprz˛etowe.
Opracowana na potrzeby
niniejszej rozprawy metodyka symulacji bł˛edów wsparta przez opracowany przez autora system
QEFI (patrz rozdział 3) stanowi prób˛e stworzenia narz˛edzia typu SWIFI umożliwiajacego
˛
ewaluacj˛e oprogramowania systemu operacyjnego poprzez zastosowanie emulacji systemu
komputerowego.
2.5. Analiza efektów bł˛edów
Wystapienie
˛
bł˛edu w systemie może powodować różnego typu nast˛epstwa – od maskowania
bł˛edu do awarii. Opracowywanie skutecznych technik obsługi bł˛edów wymaga szczegółowej
analizy cyklu życia bł˛edu w systemie. Poniżej przedstawiona jest charakterystyka zdarzeń
opisujacych
˛
wystapienie
˛
bł˛edu oraz poj˛ecia i miary zwiazane
˛
z symulacja˛ bł˛edów, które
pozwalaja˛ na dogł˛ebna˛ analiz˛e wpływu bł˛edów na działanie systemu.
27
http://user-mode-linux.sourceforge.net/
36
2.5.1. Scenariusz wystapienia
˛
bł˛edu
Analiza efektów bł˛edów w systemie komputerowym wymaga opisania zdarzeń, które maja˛
miejsce w sytuacji wystapienia
˛
bł˛edu. Poniżej zamieszczone sa˛ definicje rozpatrywanych
zdarzeń:
— wystapienie
˛
bł˛edu na poziomie fizycznym – jest to moment, kiedy działanie układu zostało
zaburzone i nie realizuje on funkcji zgodnie ze swoja˛ specyfikacja,˛
— wystapienie
˛
bł˛edu na poziomie logicznym – jest to sytuacja, kiedy zaburzenie na poziomie
fizycznym zmienia stan logiczny układu (np. zmiana wartości bitów),
— aktywacja bł˛edu – jest to chwila, gdy dane zmodyfikowane na skutek bł˛edu logicznego
zostały wykorzystane w procesie wykonania oprogramowania,
— maskowanie – sytuacja, gdy aktywacja bł˛edu nie wpłyn˛eła na działanie systemu
komputerowego,
— manifestacja – wyst˛epuje, gdy zaistniała w systemie nieprawidłowość wywołuje
obserwowalne odst˛epstwo od pracy systemu (np. generowanie nieprawidłowych wyników,
nieudany wynik sprawdzenia asercji, zniekształcone komunikaty systemu),
— awaria – jest to zdarzenie b˛edace
˛ manifestacja˛ bł˛edu oznaczajace
˛ wystapienie
˛
sytuacji
wyjatkowej
˛
uniemożliwiajacej
˛ kontynuacj˛e wykonania oprogramowania,
— detekcja bł˛edu – wyst˛epuje, gdy zaistniała w systemie nieprawidłowość zostaje
zamanifestowana i zidentyfikowana jako bład
˛ sprz˛etowy.
Odst˛ep mi˛edzy wystapieniem
˛
bł˛edu na poziomie fizycznym a jego aktywacja˛ nazywany jest
utajeniem bł˛edu. Natomiast interwał mi˛edzy wystapieniem
˛
bł˛edu, a manifestacja˛ jest określany
opóźnieniem manifestacji bł˛edu. W przypadku powyższych zdarzeń odst˛epy pomi˛edzy nimi
moga˛ być mierzone zarówno czasem rzeczywistym jak i czasem logicznym (np. liczba wykonań
instrukcji, czy liczba taktów zegara procesora).
Istotnym zagadnieniem zwiazanym
˛
z aktywacja˛ bł˛edów jest aktywność zasobów. Zasób,
czyli przykładowo komórka pami˛eci RAM, jest aktywny, jeżeli przechowuje dane, które
b˛eda˛ wykorzystane w przebiegu programu do uzyskania wyniku. Oznacza to, że zasób jest
nieaktywny w przedziałach czasu pomi˛edzy ostatnim odczytem zasobu, a zapisem nowymi
wartościami28 . Nie wszystkie bł˛edy maja˛ wpływ na obliczenia. Mamy do czynienia z takim
scenariuszem, gdy bład
˛ przemijajacy
˛ wystapił
˛ w okresie nieaktywności zasobu. Chociaż
możliwe sa˛ również przypadki, kiedy bład
˛ aktywowany nie miał wpływu na obliczenia.
28
Pod warunkiem, że nowa wartość b˛edzie odczytana. W przypadku, gdy kolejna˛ operacja˛ na zasobie jest
zapis, to czas nieaktywności zasobu wydłuża si˛e do tej operacji.
37
2.5.2. Symulowanie bł˛edów
W technice symulacji bł˛edów możliwe jest dokładne określenie skutków wstrzykiwania
bł˛edów.
Poniżej przedstawione sa˛ miary pozwalajace
˛ określić zarówno cechy efektów
wstrzykiwania pojedynczych bł˛edów, jak i zbiorczych eksperymentów.
Bł˛edy moga˛ być symulowane w różnych komponentach systemu komputerowego, a także
w różnych momentach.
Definicja 2.5.1. Zaburzana przestrzeń jest to charakterystyczny dla danego typu bł˛edu zbiór
zasobów i momentów symulacji bł˛edu.
Przykładowo dla bł˛edów pami˛eci zaburzana˛ przestrzenia˛ sa˛ komórki pami˛eci w czasie pracy
systemu komputerowego. Warto zaznaczyć, że wprowadzanie bł˛edów w pewnych podzbiorach
zaburzanej przestrzeni nie b˛edzie miało wpływu na działanie systemu komputerowego. W
przypadku bł˛edów bit-flip pami˛eci celowe jest tylko zaburzanie zasobów aktywnych w danym
momencie wstrzykni˛ecia, ponieważ w nieaktywnej komórce pami˛eci zostanie zapisana nowa
wartość maskujac
˛ w ten sposób wystapienie
˛
bł˛edu.
Natomiast sytuacja jest odmienna
w przypadku bł˛edów stuck-at-0/stuck-at-1, kiedy symulacja bł˛edu w nieaktywnej komórce
pami˛eci utrzymuje si˛e po zapisie nowej wartości.
Oprogramowanie systemu operacyjnego powinno być w stanie obsługiwać bł˛edy, które
pochodza˛ z urzadzeń
˛
systemu komputerowego (komponentów obsługiwanych przez system
operacyjny, np. sprz˛etu stanowiacego
˛
integralna˛ cz˛eść systemu komputerowego oraz urzadzeń
˛
zewn˛etrznych) jak i bł˛edów w komponentach wykorzystywanych przez system operacyjny
do działania – kodu oraz danych. Skutkuje to podziałem na dwa rodzaje symulowanych
bł˛edów: bł˛edy zewn˛etrzne oraz bł˛edy wewn˛etrzne. Przykładem bł˛edu zewn˛etrznego jest
nieprawidłowo działajacy
˛ kontroler USB generujacy
˛ losowe pakiety.
Natomiast bł˛edem
wewn˛etrznym może być przekłamanie typu bit-flip w obszarze pami˛eci RAM przechowujacej
˛
kod systemu operacyjnego.
Opóźnienie awarii jest miara˛ zwiazan
˛ a˛ z opóźnieniem manifestacji bł˛edu w przypadku, gdy
bład
˛ skutkuje awaria.˛
Definicja 2.5.2. Opóźnienie awarii stanowi liczb˛e instrukcji kodu programu wykonanych przez
jednostk˛e przetwarzajac
˛ a˛ od wykonania pierwszej instrukcji aktywujacej
˛ bład
˛ do wykonania
instrukcji wywołujacej
˛ awari˛e.
Manifestacja bł˛edu dla celów niniejszej rozprawy została podzielona na kategorie
uwzgl˛edniajace
˛
czy
system
komputerowy
wygenerował
powierzone
mu
zadanie
(np. prawidłowo przetworzony został pewien plik) oraz czy system operacyjny zgłosił
komunikaty sygnalizujace
˛ nieprawidłowości w działaniu systemu:
38
— PU – prawidłowy wynik realizowanego zadania; bład
˛ spowodował odst˛epstwo w
pracy aplikacji użytkownika (np. deformacja wypisywanych przez aplikacj˛e użytkownika
komunikatów); jest to niekrytyczny przypadek manifestacji bł˛edu,
— PS – prawidłowy wynik realizowanego zadania; system operacyjny zgłosił komunikat o
wystapieniu
˛
nieprawidłowości w systemie (np. awaria procesu niemajacego
˛
wpływu na
proces realizacji zadania – przykładowo procesu defragmentacji dysku); jest to niekrytyczny
przypadek manifestacji bł˛edu z punktu widzenia realizacji zadania, niemniej praca systemu
operacyjnego została zaburzona,
— NU – nieprawidłowy wynik realizowanego zadania lub brak wyniku; brak komunikatu
zgłoszonego przez system operacyjny; jest to krytyczny scenariusz, ponieważ bład
˛
spowodował bł˛edne działanie aplikacji użytkownika, uniemożliwił dostarczenie wyniku lub
wr˛ecz spowodował zawieszenie si˛e systemu operacyjnego,
— NS – nieprawidłowy wynik realizowanego zadania lub brak wyniku; system operacyjny
zgłosił komunikat o odst˛epstwie od prawidłowej pracy systemu; jest to krytyczny scenariusz
z uwagi na brak prawidłowego wyniku, jednak dostarcza on wi˛ecej informacji o przyczynie
nieprawidłowości, niż kategoria NU .
Przykłady wymienionych typów manifestacji wraz z opisem przedstawione sa˛ w 4.2.
Dodatkowo możliwe jest rozróżnienie, czy w przypadku manifestacji bł˛edu system
komputerowy pozostał dost˛epny i czy użytkownik mógł obserwować manifestacj˛e bł˛edu.
System komputerowy uznawany jest za dost˛epny, kiedy możliwa jest interakcja z systemem.
Dost˛epność systemu została podzielona na nast˛epujace
˛ kategorie:
— DU – system dost˛epny, odst˛epstwa od prawidłowej pracy systemu sa˛ zwiazane
˛
z
komunikatami zgłaszanymi przez aplikacje użytkownika,
— DS
– system dost˛epny,
system operacyjny zgłosił komunikat o wystapieniu
˛
nieprawidłowości,
— N DU – system niedost˛epny, brak informacji o wykryciu bł˛edu aplikacyjnego przez system
operacyjny,
— N DS – system niedost˛epny, system operacyjny zgłosił komunikat o wystapieniu
˛
nieprawidłowości przed utrata˛ możliwości interakcji.
Dla zbiorczej oceny efektów symulowanych bł˛edów wprowadzone zostały nast˛epujace
˛
współczynniki:
— współczynnik wrażliwości na bł˛edy Fs =
M
,
W
— współczynnik naturalnej odporności na bł˛edy I = 1 −
— współczynnik detekcji bł˛edów Fd =
Wd
,
Wa
— współczynnik naprawy bł˛edów określony Fr =
gdzie:
— M – liczba bł˛edów zamanifestowanych,
39
R
,
Wd
M
,
Wa
— W – liczba bł˛edów symulowanych w systemie,
— Wa – liczba bł˛edów aktywowanych w systemie,
— Wd – liczba bł˛edów wykrytych w systemie,
— R – liczba bł˛edów, dla których przeprowadzono procedur˛e naprawcza˛ i uzyskano
prawidłowy wynik realizowanego zadania.
Współczynniki te dotycza˛ eksperymentu składajacego
˛
si˛e z wielu pojedynczych testów
symulowania bł˛edu.
Wyznaczenie dokładnej wartości każdego ze współczynników
wymagałoby zupełnego pokrycia zaburzanej przestrzeni (np. zaburzanie wszystkich adresów
pami˛eci RAM), niemniej możliwe jest oszacowanie ich wartości poprzez odpowiednio liczna˛ i
reprezentatywna˛ prób˛e wstrzykni˛etych bł˛edów (szerzej opisane w 4.2).
Współczynnik wrażliwości na bł˛edy określa podatność systemu na bł˛edy. Współczynnik
naturalnej odporności na bł˛edy wyznacza zdolność systemu do maskowania bł˛edów –
określa on liczb˛e bł˛edów, które nie zostały zamanifestowane, pomimo że były aktywowane.
Współczynnik detekcji bł˛edów określa zdolność systemu do wykrywania bł˛edów sprz˛etowych.
Przykładowo, jeżeli system wykrył bład
˛ w danych tylko do odczytu poprzez wyliczenie sumy
kontrolnej i wypisał zwiazany
˛
z tym komunikat, to jest to detekcja bł˛edu, natomiast jeżeli
bład
˛ spowodował awari˛e, to jest to jedynie manifestacja bł˛edu, ponieważ nie jest możliwe
określenie, czy awaria jest skutkiem bł˛edu pracy systemu, czy bł˛edu programistycznego.
Współczynnik naprawy bł˛edów wyraża zdolność systemu do przeprowadzenia skutecznych
procedur naprawczych w przypadku detekcji bł˛edu sprz˛etowego.
2.6. Podsumowanie
W rozdziale przedstawiony został model rozważanego systemu komputerowego jako
sprz˛etu oraz oprogramowania. Opisana została również dziedzina badania niezawodności
systemów komputerowych. Scharakteryzowane zostały źródła bł˛edów oraz znane z literatury
mechanizmy zwi˛ekszania niezawodności wraz z technikami pozwalajacymi
˛
ocenić ich
skuteczność.
Przedstawiona w ostatniej cz˛eści rozdziału analiza pozwala określić podstawowe zadania
mechanizmów zwi˛ekszania niezawodności. Głównym zadaniem jest maksymalizacja detekcji
bł˛edów w systemie. Dzi˛eki temu możliwe jest stwierdzenie, że system może potencjalnie
działać nieprawidłowo w zwiazku
˛
z bł˛edami sprz˛etowymi – niezależnie od tego, czy
bład
˛ zostanie aktywowany.
Informacja o tych bł˛edach stanowi również cenne źródło
wiedzy o kondycji systemu komputerowego, ponieważ bł˛edy maja˛ charakter nawracajacy
˛
(czyli wystapienie
˛
bł˛edu zwi˛eksza szanse na ponowne wystapienie
˛
bł˛edu w tym samym
urzadzeniu
˛
– patrz [84]). Kolejnym zadaniem zwi˛ekszania niezawodności jest maksymalizacja
tolerancji bł˛edów, czyli możliwości podj˛ecia procedur naprawczych niwelujacych
˛
efekty
40
bł˛edu. Optymalizacja detekcji i tolerancji bł˛edów pozwala na osiagni˛
˛ ecie wyższych poziomów
niezawodności określonych za pomoca˛ współczynników przedstawionych w 2.5.2.
41
3. Metodyka symulacji bł˛edów w emulowanym
środowisku
W rozdziale przedstawiono wykorzystanie emulacji systemu komputerowego do analizy
niezawodności oprogramowania.
Poczatek
˛
rozdziału uzasadnia obrany kierunek badań.
Nast˛epnie przedstawiony jest opis obecnego stanu technologii w dziedzinie emulacji systemów
komputerowych oraz prezentacja cech emulatorów, które sa˛ szczególnie istotne z perspektywy
badania niezawodności oprogramowania. Ostania cz˛eść rozdziału zawiera opis stworzonej
na potrzeby niniejszej rozprawy oryginalnej metodyki przeprowadzania eksperymentów oraz
opracowanych algorytmów symulacji bł˛edów.
3.1. Motywacja
Podj˛ecie zagadnienia zastosowania emulacji w analizie niezawodności oprogramowania
zwiazane
˛
jest z próba˛ poszerzenia horyzontu badań w stosunku do narz˛edzi, które
ukierunkowane sa˛ na kod pojedynczych aplikacji (patrz 2.4).
Wada˛ takich narz˛edzi jest
skupienie si˛e na pojedynczym programie w oderwaniu od środowiska wykonania. Według
autora potrzeba zbadania całego środowiska operacyjnego oprogramowania jest istotnym
zagadnieniem niedostatecznie opisanym w literaturze.
Dzi˛eki zwi˛ekszeniu w ostatnich latach wydajności emulacji systemów komputerowych
stało si˛e możliwe wykorzystanie tego typu oprogramowania do badań nad niezawodnościa.˛
Podstawowa˛ technika˛ wykorzystywana˛ w dziedzinie ewaluacji niezawodności jest
wstrzykiwanie bł˛edów (patrz 2.4).
Wzbogacenie emulatorów systemów komputerowych
o funkcje symulacji bł˛edów b˛edacych
˛
modelami rzeczywistych zaburzeń pracy systemu
pozwoli na stworzenie narz˛edzi pozwalajacych
˛
na wszechstronna˛ ewaluacj˛e niezawodności
oprogramowania.
Zastosowanie emulatorów usprawnia prowadzenie eksperymentów poprzez brak
konieczności instrumentacji testowanego oprogramowania oraz pełna˛ kontrol˛e nad procesem
emulacji, gdzie możliwe jest efektywne śledzenie zmian w środowisku. Dodatkowo otwieraja˛
si˛e nowe obszary badań takie jak: ewaluacja oprogramowania systemów operacyjnych, badanie
efektów usterek urzadzeń,
˛
porównywanie właściwości różnych architektur sprz˛etowych,
43
czy opracowywanie nowych mechanizmów zwi˛ekszania niezawodności wykorzystujacych
˛
współprac˛e aplikacji i systemu operacyjnego.
Zdaniem autora funkcje umożliwiajace
˛ symulowanie bł˛edów w emulatorach b˛eda˛ coraz
popularniejsze i maja˛ potencjał stać si˛e standardem w testowaniu oprogramowania. Wynika
to z faktu, że symulacja bł˛edu jest zadaniem znacznie łatwiejszym i precyzyjniejszym niż
wprowadzenie rzeczywistego bł˛edu, a emulatory znacznie poszerzaja˛ zakres stosowania tej
techniki.
3.2. Emulacja systemów komputerowych
Emulatory systemów komputerowych sa˛ bardzo popularnymi narz˛edziami w przemyśle
informatycznym. Na rynku dost˛epnych jest wiele rozwiazań,
˛
które różnia˛ si˛e posiadanymi
funkcjami i sa˛ przeznaczone do różnych zadań: testowanie oprogramowania [98], izolacja
środowiska wykonania oprogramowania [20], czy zarzadzanie
˛
wirtualnymi komputerami1 .
W niniejszych rozważaniach emulator systemu komputerowego jest zdefiniowany
nast˛epujaco:
˛
Definicja 3.2.1. Emulatorem systemu komputerowego A jest oprogramowanie działajace
˛ na
systemie komputerowym B, które umożliwia działanie niezmodyfikowanego oprogramowania
X przeznaczonego na system komputerowy A.
Definicja 3.2.1 określa główne wymagania sformułowane dla emulatorów – oprogramowanie X
nie może być zmodyfikowane w żaden sposób oraz musi realizować programowo środowisko
systemu komputerowego (patrz 2.1.1).
Niemniej emulatory moga˛ pracować na różnych
poziomach abstrakcji. Warto wyróżnić trzy poziomy abstrakcji:
— emulacja układów cyfrowych,
— emulacja logicznego funkcjonowania urzadzeń,
˛
— emulacja systemu operacyjnego.
Emulacja na poziome układów cyfrowych oznacza modelowanie systemu komputerowego
A poprzez niskopoziomowa˛ specyfikacj˛e sprz˛etu – np. definiowanie procesorów, pami˛eci i
innych urzadzeń
˛
w j˛ezyku VHDL. Przykłady badań ukierunkowanych na przeprowadzanie
eksperymentów na modelach mikrokontrolerów można znaleźć w [43, 44, 47] .
Warto
zaznaczyć, że ten sposób emulacji jest rozwiazaniem
˛
bardzo kosztownym obliczeniowo przy
zastosowaniu dla wszystkich komponentów systemu komputerowego, co czyni to rozwiazanie
˛
niepraktycznym.
Emulacja na poziomie logicznego funkcjonowania urzadzeń
˛
pozwala na modelowanie
sprz˛etu poprzez implementacj˛e funkcji, które sa˛ przez niego realizowane.
1
http://www.vmware.com/pdf/virtualization.pdf
44
Przykładem
jest emulacja dysku twardego systemu komputerowego A poprzez moduł programowy,
który wykorzystuje plik w systemie B do realizacji funkcji zapisu i odczytu danych.
Zadaniem modułu programowego jest wtedy implementacja protokołu wymiany danych mi˛edzy
urzadzeniem,
˛
a pozostałymi komponentami emulowanego systemu – np. SATA. Podejście
takie pozwala na emulacj˛e sprz˛etu bez znajomości jego wewn˛etrznej struktury. Dodatkowo
jest ono wydajniejsze od emulacji układów cyfrowych z uwagi na możliwość wykorzystania
mechanizmów dost˛epnych w systemie B bez narzutu na replikacj˛e wewn˛etrznych stanów
emulowanych urzadzeń.
˛
Emulacja na poziomie systemu operacyjnego zwiazana
˛
jest z ograniczeniem
oprogramowania X tylko do aplikacji użytkownika. Aplikacje te komunikuja˛ si˛e z systemem
operacyjnym poprzez wywołania systemowe (patrz 2.1.2). Koncepcja emulacji na poziomie
systemu operacyjnego polega na przechwytywaniu wywołań systemowych pochodzacych
˛
z
oprogramowania X i obsługi ich przez oprogramowanie emulatora, który w razie potrzeby
wywołuje system operacyjny działajacy
˛ na systemie B. Dzi˛eki tej metodzie na potrzeby
oprogramowania X emulowany jest jedynie procesor i pami˛eć systemu A, natomiast dost˛ep do
dodatkowych urzadzeń
˛
takich jak dyski twarde, czy interfejs sieciowy realizowany jest przez
system B.
Ciekawa˛ technika˛ cz˛esto wykorzystywana˛ w emulacji jest również możliwość
współdzielenia urzadzeń
˛
wyst˛epujacych
˛
w systemie A z systemem B – rozwiazanie
˛
takie jest możliwe przy wsparciu systemu operacyjnego maszyny emulujacej.
˛
Zasada
działania jest nast˛epujaca:
˛
dane wysyłane do urzadzenia
˛
sa˛ przechwytywane z emulowanej
magistrali do systemu operacyjnego rzeczywistego komputera, który nast˛epnie wysyła je
do urzadzenia
˛
(z zastosowaniem rzeczywistej magistrali). Analogicznie system operacyjny
rzeczywistego komputera przekazuje (ewentualnie po wst˛epnej obróbce) dane otrzymane z
urzadzenia
˛
do oprogramowania emulatora, po czym przekazywane sa˛ one do emulowanego
systemu za pośrednictwem emulowanej magistrali.
W [73] przedstawiono mechanizm
udost˛epniania rzeczywistych urzadzeń
˛
USB dla emulowanego systemu w sposób imitujacy
˛
bezpośrednie podłaczenie
˛
tych urzadzeń.
˛
Niemniej podobne rozwiazania
˛
sa˛ dost˛epne w wielu
komercyjnych rozwiazaniach
˛
(VMware, VirtualBox, Virtual PC) – w szczególności możliwe
jest wykorzystanie przez emulowany system rzeczywistego dysku twardego, urzadzeń
˛
USB,
czy kart graficznych.
W implementacjach emulatorów moga˛ być stosowane rozwiazania
˛
hybrydowe, gdzie
emulacja poszczególnych urzadzeń
˛
realizowana jest na różnych poziomach abstrakcji.
Przykładowo procesor systemu A może być emulowany na poziomie układów cyfrowych,
pami˛eć RAM jako plik rezydujacy
˛ w systemie B, a pozostałe urzadzenia
˛
sa˛ dost˛epne za
pośrednictwem systemu operacyjnego działajacego
˛
na systemie B.
45
W dalszej cz˛eści rozdziału opisane sa˛ wyłacznie
˛
zagadnienia zwiazane
˛
z emulacja˛ na
poziomie logicznego funkcjonowania urzadzeń.
˛
Emulacja na poziomie układów cyfrowych
została wykluczona z powodu niedost˛epności wewn˛etrznej specyfikacji poszczególnych
urzadzeń
˛
– stanowia˛ one własność intelektualna˛ producentów i cz˛esto nie sa˛ udost˛epniane
publicznie. Natomiast emulacja na poziomie systemu operacyjnego ograniczyłaby badania do
oprogramowania aplikacji użytkownika, co stoi w sprzeczności z jednym z celów rozprawy,
jakim jest ewaluacja oprogramowania systemu operacyjnego.
Przy emulacji na poziomie logicznego funkcjonowania urzadzeń
˛
implementacja modelu
pami˛eci oraz urzadzeń
˛
wejścia/wyjścia może być zbliżona mi˛edzy różnymi emulatorami.
Bardzo istotnym zagadnieniem jest sposób emulacji jednostek przetwarzajacych,
˛
który ma
decydujacy
˛ wpływ na wydajność. Należy wyróżnić trzy główne sposoby rozwiazania
˛
tego
problemu:
— interpretacja,
— translacja binarna,
— wirtualizacja.
Wszystkie z wymienionych technik maja˛ za zadanie obsług˛e zestawu instrukcji architektury
(ISA2 ) emulowanego procesora, jednak każda z nich ma swoje zalety oraz ograniczenia. Poniżej
zamieszczona jest charakterystyka poszczególnych rozwiazań.
˛
Interpretacja
Technika interpretowania polega na obsłudze emulowanych instrukcji procesora pojedynczo
przez program emulatora. Emulator pobiera instrukcj˛e programu emulowanego, dekoduje ja˛
przy pomocy zestawu instrukcji warunkowych if lub switch, a nast˛epnie pobiera argumenty
instrukcji i wykonuje przypisane jej działanie, modyfikujac
˛ struktur˛e danych reprezentujac
˛ a˛
stan emulowanego procesora.
Interpretacja jest bardzo prosta˛ technika˛ emulacji procesora, jednak nie jest ona wydajna.
Spowodowane jest to tym, że współczesne procesory sa˛ budowane w oparciu o potoki instrukcji.
Rozwiazanie
˛
to powoduje przyśpieszenie wykonania kodu, gdy trafnie przewidywane sa˛
adresy docelowe instrukcji skoków. Za każdym razem, gdy przewidywanie nie powiedzie
si˛e, nast˛epuje unieważnienie zawartości potoku i konieczne jest ładowanie nowego zestawu
instrukcji do wykonania. W przypadku interpretacji przewidywanie skoków jest zadaniem
bardzo trudnym z uwagi na dekodowanie emulowanych instrukcji, gdzie konieczne jest
wykonanie wielu skoków warunkowych w procesie wyboru odpowiedniej procedury obsługi.
Zagadnienie optymalizacji interpretacji jest szeroko opisane w literaturze [11, 13, 32,
67], jednak wiele z nich polega na manipulowaniu zestawem emulowanych instrukcji3 ,
2
Ang. Instruction Set Architecture.
Techniki te sa˛ stosowane np. w przypadku kompilowania j˛ezyka programowania do bytecode’u, który
podlega interpretacji.
3
46
co nie jest możliwe w przypadku emulowania konkretnego ISA. Zdaniem autora jedna˛ z
najbardziej interesujacych
˛
technik, która pozwala na przyśpieszenie interpretacji dowolnego
ISA jest context threading (patrz [13]). Technika ta jest dwuetapowa. Pierwszy etap to
przygotowanie dynamicznego bufora wypełnionego instrukcjami wywołań procedur obsługi
kolejnych emulowanych instrukcji. Drugi etap polega na wykonaniu instrukcji zawartych w
tym buforze. Pozwala to na wyeliminowanie dekodowania emulowanej instrukcji podczas
interpretacji. Pewnym problemem pozostaja˛ instrukcje skoku, które musza˛ być tłumaczone
na zestawy instrukcji maszyny emulujacej
˛
i również umieszczone w buforze, co czyni to
rozwiazanie
˛
zbliżonym do translacji binarnej.
Translacja binarna
Celem translacji binarnej jest przetłumaczenie instrukcji emulowanego systemu na instrukcje
emulujacego
˛
systemu komputerowego.
Można wyróżnić dwa rodzaje translacji binarnej:
statyczna oraz dynamiczna.
Statyczna translacja binarna polega na przetłumaczeniu pliku wykonywalnego
zawierajacego
˛
instrukcje maszyny emulowanej na plik wykonywalny maszyny emulujacej
˛
w celu późniejszego uruchomienia.
Technika ta jednak nie pozwala na uruchamianie
wszystkich typów programów. W szczególności nie jest możliwe uruchomienie programów
wykorzystujacych
˛
samo-modyfikacj˛e (patrz [46]). Zmiany wprowadzone w uruchomionym
programie zostana˛ przetłumaczone na instrukcje maszyny emulujacej
˛
i spowoduje to w
konsekwencji bł˛edne działanie. Dodatkowo próba emulowania całego systemu operacyjnego
ta˛ technika˛ byłaby bardzo niepraktyczna w zwiazku
˛
z koniecznościa˛ translacji statycznej nie
tylko systemu operacyjnego, ale również i programów użytkownika. W efekcie statyczna
translacja binarna jest rzadko stosowana w praktyce.
Technika dynamicznej translacji binarnej skupia si˛e na tłumaczeniu bloków instrukcji
podlegajacych
˛
emulacji w trakcie działania programu.
W momencie napotkania
nieprzetłumaczonego kodu emulator tłumaczy instrukcje systemu emulowanego na
reprezentacj˛e pośrednia.˛ Reprezentacja pośrednia jest etapem translacji binarnej, pozwalajacym
˛
na wykonanie nast˛epujacych
˛
operacji:
— zapis instrukcji logicznych wykonywanych wewnatrz
˛ bloku,
— wygenerowanie poprawnych adresów docelowych dla instrukcji skoków wewnatrz
˛
tłumaczonego bloku instrukcji,
— wygenerowanie wywołań odpowiednich procedur dla skoków poza przestrzeń aktualnie
przetwarzanego bloku,
— opcjonalna optymalizacja technikami takimi jak peephole optimization (patrz [3, 7]).
Rozwiazanie
˛
to jest bardzo efektywne, ponieważ pozwala na zachowanie cz˛esto wykonywanych
bloków i odwoływanie si˛e do nich bez konieczności ponownego tłumaczenia. Opcjonalne
zastosowanie peephole optimization polega na automatycznym skanowaniu ciagłych
˛
47
fragmentów kodu składajacych
˛
si˛e z od kilku do kilkunastu instrukcji (nazywanych oknem)
w celu eliminacji zb˛ednych operacji lub zamianie instrukcji na ich szybsze odpowiedniki.
Przykłady takich optymalizacji to np. zast˛epowanie wyrażeń, które można obliczyć w czasie
kompilacji, wyrażeniami stałymi, czy zamiana operacji mnożenia przez liczb˛e b˛edac
˛ a˛ pot˛ega˛
liczby 2 na operacj˛e przesuni˛ecia bitowego z uwagi na szybsza˛ realizacj˛e w czasie wykonania.
Peephole optimization może być stosowane zarówno na kodzie reprezentacji pośredniej jak i na
kodzie konkretnego ISA.
Technika dynamicznej translacji binarnej znana jest również pod nazwa˛ Just-in-time
compilation i jest szeroko stosowana w popularnych środowiskach Java (patrz [89]) oraz .Net
(patrz [107]), gdzie tłumaczeniu na ISA maszyny emulujacej
˛ podlega bytecode. Bytecode
jest typem reprezentacji pośredniej neutralnej wzgl˛edem docelowego ISA – tzn. składa
si˛e z podstawowego zestawu instrukcji, który może być przetłumaczony na każda˛ z
obsługiwanych ISA. Kod bytecode z założenia nie wykorzystuje wszystkich możliwości
docelowej architektury, ponieważ mogłoby to uniemożliwić przenośność na inne architektury.
Dopiero dzi˛eki zastosowaniu translacji binarnej tworzony jest kod wykonywalny przystosowany
do końcowej platformy.
Wirtualizacja
Szczególnym przypadkiem emulacji jest wirtualizacja.
Technika ta wymaga spełnienia
dodatkowego warunku zaw˛eżajacego
˛
definicj˛e 3.2.1:
oprogramowanie X może być
uruchamiane bezpośrednio na systemie komputerowym B. Warunek ten sprowadza si˛e do
możliwości emulowania jedynie oprogramowania skompilowanego na t˛e sama˛ architektur˛e
ISA, na której działa system emulujacy.
˛
Zasada działania wirtualizacji to trap-and-emulate (patrz [14]) – instrukcje emulowanego
systemu komputerowego sa˛ wykonywane bezpośrednio przez procesor systemu emulujacego,
˛
aż napotkana zostanie instrukcja wymagajaca
˛ interakcji z urzadzeniami
˛
wejścia/wyjścia (patrz
[2]).
Oprogramowanie emulatora przechwytuje takie żadania,
˛
emuluje działanie sprz˛etu,
a nast˛epnie zwraca odpowiedni rezultat do systemu emulowanego sygnalizujac
˛ gotowość
rezultatu poprzez wygenerowanie emulowanego przerwania sprz˛etowego.
Emulowane sa˛
również dodatkowe urzadzenia
˛
takie jak zegary, czy kontroler pami˛eci MMU.
Wirtualizacja jest najszybsza˛ technika˛ emulacji, ponieważ nie wymaga ani interpretowania,
ani tłumaczenia instrukcji systemu emulowanego. Niemniej warto zauważyć, że pierwsze
implementacje trap-and-emulate nie były szybsze od translacji binarnej (patrz [2]), co było
spowodowane cz˛estymi zmianami kontekstu procesora mi˛edzy systemem emulowanym a
emulujacym.
˛
Na dzień dzisiejszy wirtualizacja jest najpopularniejsza˛ technika˛ emulacji,
właśnie dzi˛eki swojej wydajności.
48
Każda z przedstawionych technik emulacji może być wykorzystywania w procesie
wstrzykiwania bł˛edów, jednak wybrana metoda może okazać si˛e nieodpowiednia do pewnych
zastosowań w zwiazku
˛
z powiazanymi
˛
z nia˛ ograniczeniami. Wybór emulatora na potrzeby
niniejszej rozprawy wraz z uzasadnieniem został opisany w sekcji 3.4.1.
3.3. Zastosowanie emulacji
Zastosowanie emulacji systemu komputerowego jest szczególnie użyteczne w badaniu
niezawodności oprogramowania z zastosowaniem techniki wstrzykiwania bł˛edów. Wpływa
na to wiele cech emulatorów zwi˛ekszajacych
˛
kontrol˛e nad środowiskiem eksperymentu oraz
bogate możliwości badania efektów wstrzykiwanych bł˛edów.
Poniżej przedstawione sa˛
najważniejsze cechy emulatorów, które czynia˛ je bardzo efektywnymi narz˛edziami w analizie
niezawodności.
Automatyzacja sterowania
Emulator systemu komputerowego jest programem, który udost˛epnia funkcje pozwalajace
˛
sterować zachowaniem emulowanego systemu komputerowego.
Możliwe jest zarówno
uruchamianie, zatrzymywanie, restart emulowanej maszyny jak i podłaczanie/odł
˛
aczanie
˛
urzadzeń
˛
peryferyjnych. Funkcje te pozwalaja˛ na automatyzacj˛e scenariuszy testowania na
poziomie oprogramowania, które w przypadku pracy z rzeczywistym urzadzeniem
˛
wymagałyby
dodatkowych urzadzeń
˛
(np. watchdog). Połaczenie
˛
tych funkcji z możliwościa˛ automatycznej
interakcji z oprogramowaniem uruchomionym w emulowanym systemie komputerowym
pozwala przeprowadzać eksperymenty według nast˛epujacego
˛
schematu:
— wprowadzenie emulowanego systemu komputerowego w pożadany
˛
stan (np. uruchomienie
wymaganych aplikacji użytkownika),
— symulacja bł˛edu w trakcie realizacji powierzonych zadań,
— zebranie informacji o efektach bł˛edów/kondycji systemu,
— przywrócenie wyjściowego stanu emulowanego systemu.
Obserwowalność efektów bł˛edów
Atutem stosowania emulowanego środowiska jest łatwy podglad
˛ stanu wewn˛etrznego
emulowanego systemu. Precyzja inspekcji stanu jest ściśle zwiazana
˛
z poziomem emulacji
– np. przy emulacji procesorów na poziomie ISA nie sa˛ dost˛epne stany ukrytych rejestrów4 .
Niemniej emulatory pozwalaja˛ na zatrzymanie wykonania emulowanego systemu w dowolnej
chwili i dokonanie diagnostyki pami˛eci, zawartości rejestrów procesora, jak i stanu
emulowanych urzadzeń.
˛
Możliwe jest również zapisywanie historii interakcji poszczególnych
urzadzeń
˛
– stworzenie dziennika przerwań obsługiwanych przez emulowany procesor jest
4
Sa˛ to rejestry niedost˛epne w interfejsie programistycznym procesora.
49
stosunkowo łatwe do realizacji jako moduł programu emulatora. W przypadku wystapienia
˛
sytuacji wyjatkowej
˛
na poziomie systemu operacyjnego na fizycznej maszynie informacje o
stanie wewn˛etrznym sa˛ ograniczone najcz˛eściej do komunikatów wyświetlanych na ekranie
(np. niebieski ekran bł˛edu systemu Windows lub komunikat kernel panic dla systemu
GNU/Linux, patrz 2.1.2) lub wymagaja˛ zastosowania dedykowanych interfejsów debugowania
(np. interfejs JTAG5 dost˛epny w wielu rozwiazaniach
˛
mikroprocesorowych – patrz [1]).
Dopiero specjalistyczne systemy umożliwiaja˛ działania takie jak uruchomienie „zapasowego”
systemu operacyjnego, zbierajacego
˛
informacje o bł˛edach i zapisujacego
˛
te dane na dysku do
późniejszego zbadania.
Możliwość multiplikacji emulowanego środowiska
Istotna˛ cecha˛ emulatorów jest możliwość multiplikacji środowiska testowania.
Ponieważ
emulator jest programem komputerowym, możliwe jest uruchomienie wielu instancji. Pozwala
to na jednoczesne przeprowadzanie wielu testów na jednym lub wi˛ekszej liczbie komputerów.
Właściwość ta prowadzi do znacznego obniżenia kosztów dzi˛eki usuni˛eciu z procesu testowania
konieczności dysponowania fizycznym sprz˛etem.
Dodatkowo kopiowanie konfiguracji
emulatora stanowi duże ułatwienie wzgl˛edem konfigurowania wielu fizycznych komputerów.
Nieinwazyjne monitorowanie działania systemu
Kontrola nad procesem wykonywania kodu systemu emulowanego daje unikatowa˛ możliwość
monitorowania zachowania systemu bez ingerencji w oprogramowanie.
Istnieje wiele
mechanizmów śledzenia wykonania, zarówno oprogramowania działajacego
˛
w przestrzeni
użytkownika (debuggery, profilery), jak i po stronie jadra
˛
systemu operacyjnego (sa˛ to
mechanizmy dedykowane dla każdego systemu). Rozwiazania
˛
te działaja˛ jednak w oparciu o
funkcje systemu operacyjnego. Zastosowanie emulacji pozwala na śledzenie wykonania przez
zewn˛etrzny komponent bez uruchamiania dodatkowego oprogramowania, ani instrumentacji.
Testowanie sterowników sprz˛etu
Emulacja urzadzeń
˛
peryferyjnych pozwala na przetestowanie oprogramowania sterowników
sprz˛etu w sytuacjach zarówno bł˛ednego działania, jak i trudnych do odtworzenia przez
programist˛e granicznych wartości wyjść.
Przykładem może być czujnik przyśpieszenia,
gdzie uzyskanie wysokich lub wykraczajacych
˛
poza zakres działania urzadzenia
˛
wskazań
wymagałoby rzeczywistego przyśpieszenia. Dzi˛eki zastosowaniu emulowanego rozwiazania
˛
możliwe jest uzyskanie dowolnego wyjścia z urzadzenia
˛
i przetestowanie reakcji stosu
programowego, właczaj
˛
ac
˛ w to sterowniki systemu operacyjnego.
Można rozwinać
˛
takie zastosowanie do rozpocz˛ecia prac nad sterownikami w emulowanym środowisku
programistycznym dla nowych urzadzeń
˛
zanim urzadzenia
˛
te b˛eda˛ fizycznie dost˛epne dla
5
Ang. Joint Test Action Group.
50
programisty (rozwiazanie
˛
takie opisano w [49]) – konieczne jest jedynie przygotowanie
programistycznego modelu danego urzadzenia
˛
w oparciu o specyfikacj˛e. Jest to szczególnie
cenna cecha, ponieważ pozwala zredukować czas potrzebny do wydania gotowego produktu,
jednocześnie umożliwiajac
˛ przeprowadzenie dodatkowych testów niezawodności.
Testowanie oprogramowania w nowych dziedzinach
Metody programowego wstrzykiwania bł˛edów SWIFI opisane w podrozdziale 2.4 polegaja˛ na
usługach dost˛epnych w systemie operacyjnym. Jest to istotne ograniczenie z dwóch powodów:
— zaburzenie działania systemu operacyjnego przy jednoczesnym poleganiu na jego usługach
utrudnia zbieranie danych o wynikach eksperymentów oraz obniża poziom zaufania do ich
poprawności,
— brak możliwości badania efektów bł˛edów wyst˛epujacych
˛
w urzadzeniach.
˛
Zastosowanie emulacji we wstrzykiwaniu bł˛edów dzi˛eki łatwej obserwowalności efektów
bł˛edów i możliwości nieinwazyjnego śledzenia wykonania stanowi unikatowe narz˛edzie
pozwalajace
˛ testować system operacyjny, co eliminuje ograniczenia wspomnianych metod.
Testowanie w bezpiecznych warunkach
Dla wielu urzadzeń
˛
docelowe środowisko działania jest ucia˛żliwe lub szkodliwe dla
człowieka ze wzgl˛edu na czynniki takie jak temperatura, czy promieniowanie. Emulacja
pozwala na przeprowadzenie cz˛eści testów bez narażania programisty na niedogodności, czy
niebezpieczeństwo.
3.4. Środowisko zautomatyzowanych testów
W zwiazku
˛
z potencjalnymi zaletami zastosowania emulacji w badaniu niezawodności
oprogramowania opisanymi w podrozdziale 3.3 autor przeprowadził przeglad
˛ dost˛epnych
na rynku emulatorów oraz opartych o nie narz˛edzi wspierajacych
˛
wstrzykiwanie bł˛edów.
W literaturze jednak niewiele jest prac poświ˛econych badaniu niezawodności systemów
operacyjnych oraz technik obsługi bł˛edów wyst˛epujacych
˛
w przestrzeni jadra
˛
systemu
operacyjnego (patrz 2.4). Dodatkowo nie udało si˛e autorowi znaleźć wyczerpujacych
˛
badań
wpływu bł˛edów na różne architektury sprz˛etowe lub różne systemy operacyjne. Ch˛eć dokładnej
analizy tych zagadnień stanowiła motywacj˛e do przygotowania oryginalnego środowiska
zautomatyzowanych testów, które pozwala kompleksowo zbadać zachowanie systemów
operacyjnych w obliczu bł˛edów.
W niniejszym podrozdziale przedstawiono oryginalne narz˛edzie QEMU Fault Injection
Framework (QEFI), którego podstawa˛ działania jest programowe symulowanie bł˛edów (SWIFI)
stanowiacych
˛
model rzeczywistych bł˛edów (patrz rozdział 2) w emulowanym systemie
51
komputerowym. Opisane zostały decyzje projektowe podj˛ete przy tworzeniu QEFI, możliwości
i ograniczenia jego zastosowań oraz realizowana metodyka przeprowadzania testów.
3.4.1. Wybór emulatora systemu komputerowego
Na rynku dost˛epnych jest wiele rozwiazań
˛
pozwalajacych
˛
na uruchamianie systemu
komputerowego w emulowanym środowisku. Najbardziej popularne programy pozwalajace
˛
na emulacj˛e to: Bochs, QEMU, User Mode Linux, VirtualBox, Virtual PC, Xen, KVM,
VMWare. Spośród nich tylko Bochs stosuje technik˛e interpretacji opisana˛ w podrozdziale 3.2.
Pozostałe emulatory stosuja˛ wirtualizacj˛e – wyjatkiem
˛
jest QEMU, które oprócz wirtualizacji
może pracować również w trybie dynamicznej translacji binarnej (patrz [12]).
Cz˛eść z wymienionych programów jest wykorzystywana w projektach badawczych.
Bochs wykorzystany został w Instytucie Informatyki Politechniki Warszawskiej do badania
testowalności procesora (patrz [98]), QEMU jest podstawa˛ projektu FAU Machine (patrz [93])
majacego
˛
na celu stworzenie w pełni deterministycznego emulatora, natomiast Xen posłużył
jako platforma automatycznego testowania oprogramowania pod wzgl˛edem bezpieczeństwa
(patrz [116]).
Jako podstawa przygotowanego przez autora środowiska zautomatyzowanych testów został
wybrany emulator QEMU. Decyzja ta uzasadniona jest nast˛epujacymi
˛
cechami QEMU:
— wsparcie dla emulacji wielu architektur sprz˛etowych,
— zadowalajaca
˛ wydajność – porównanie liczby cykli procesora potrzebnej do emulacji
poszczególnych operacji maszyny emulowanej wzgl˛edem emulatora Bochs można znaleźć
w [77], gdzie QEMU dla wi˛ekszości testowanych operacji było znacznie szybsze6 ,
— dynamiczna translacja – pozwala na nieinwazyjne monitorowanie systemu emulowanego,
— licencja open-source, dzi˛eki czemu modyfikowanie źródeł nie jest ograniczone, a efekt prac
może być przedstawiany publicznie,
— przeprowadzone
zostały
badania
potwierdzajace
˛
zbliżone
efekty
bł˛edów
przy
wstrzykiwaniu bł˛edów w system rzeczywisty i emulowany przez QEMU (patrz 3.4.2).
Projektem badawczym, który również wykorzystuje QEMU jest wymieniony powyżej FAU
Machine. Wyposażony jest on w możliwość wstrzykiwania bł˛edów, jednak autorzy położyli
nacisk na funkcje, które sa˛ niewymagane z punktu widzenia niniejszej rozprawy – opracowany
został zaawansowany interpreter j˛ezyka VHDL wraz z systemem pozwalajacym
˛
na dokładne
odtworzenie sekwencji przerwań zgłaszanych w systemie. Dzi˛eki temu możliwe jest dogł˛ebne
testowanie integracji i odporności na bł˛edy projektowanych nowych układów. Natomiast
kluczowe dla niniejszej rozprawy funkcje takie jak zaawansowana automatyzacja scenariuszy
testowych, profilowanie, możliwość zaburzania pracy różnych komponentów systemu, czy
6
Testowane były m.in. nast˛epujace
˛ operacje: kopiowanie zawartości rejestrów, operacje arytmetyczne,
mnożenie liczb zmiennoprzecinkowych, skoki pośrednie z adresem docelowym odczytanym z rejestru EAX,
obsługa przerwań Page fault.
52
Emulowany
system (I)
Poprawne [%]
Manifestacja [%]
Bład
˛ [%]
Poprawne [%]
Manifestacja [%]
Bład
˛ [%]
Poprawne [p.p.]
Manifestacja [p.p.]
Bład
˛ [p.p.]
P3
Iteracje
P2
Cel
Program
P1
∆ = I − II
Rzeczywisty
system (II)
Dane
Kod
Rejestry
Dane
Kod
Rejestry
Dane
Kod
Rejestry
8256
8240
1152
8192
5928
1152
b.d.
281248
1152
86,38
18,68
19,53
53,30
23,94
25,87
b.d.
72,40
20,12
2,97
60,84
79,43
0,06
64,25
72,14
b.d.
20,12
73,92
10,65
20,48
1,04
46,64
11,81
2,00
b.d.
7,48
5,96
87,06
20,43
18,84
51,61
21,36
24,83
b.d.
75,96
18,97
2,89
59,45
79,51
0,07
64,84
72,22
b.d.
17,93
74,79
10,05
20,12
1,65
48,32
13,80
2,95
b.d.
6,11
6,24
-0,68
-1,75
0,69
1,69
2,58
1,04
b.d.
-3,56
1,15
0,08
1,39
-0,08
-0,01
-0,59
-0,08
b.d.
2,19
-0,87
0,60
0,36
-0,61
-1,68
-1,99
-0,95
b.d.
1,37
-0,28
Tabela 3.1: Wyniki wstrzykiwania bł˛edów dla systemu emulowanego i rzeczywistego (na
podstawie: [80])
zbieranie i analiza zbiorczych wyników testowania sa˛ rozwini˛ete niewystarczajaco.
˛
Niemniej
możliwe jest w przyszłości integracja cz˛eści funkcji FAU Machine z QEFI.
3.4.2. Dokładność emulacji
Kluczowym aspektem dla wiarygodności testów przeprowadzanych z użyciem QEFI
jest dokładność symulacji QEMU w przypadku wystapienia
˛
bł˛edu.
W [80] opisano
przebieg eksperymentu sprawdzajacego
˛
skuteczność QEMU jako platformy testowania
oprogramowania.
Autorzy przygotowali narz˛edzie wstrzykiwania bł˛edów w proces
użytkownika zaimplementowane jako moduł jadra
˛
systemu operacyjnego GNU/Linux
działajacego
˛
na architekturze x86. Narz˛edzie to wykorzystano do manipulowania danymi,
kodem oraz rejestrami trzech przykładowych programów. Przebieg każdego wstrzykni˛ecia
bł˛edu został opisany nast˛epujacymi
˛
cechami:
wynik poprawny, wynik niepoprawny
oraz manifestacja bł˛edu (manifestacja oznacza wyłacznie
˛
pojawienie si˛e dodatkowych
komunikatów, wi˛ec program mógł si˛e zakończyć zarówno z wynikiem poprawnym, jak i
niepoprawnym). Najistotniejszym elementem tego eksperymentu było przeprowadzenie testów
w dwóch środowiskach: rzeczywistym oraz emulowanym przez QEMU. Wyniki eksperymentu
zamieszczone sa˛ w tabeli 3.1.
Według przedstawionych wyników w wi˛ekszości przypadków różnica w ilościowych
wynikach wynosi poniżej jednego procenta.
Uwiarygodnia to zastosowanie QEMU jako
platformy testowania niezawodności oprogramowania, a dodatkowo wykryte różnice pomi˛edzy
53
systemem rzeczywistym i emulowanym stanowia˛ cenne źródło informacji o tym, jak należy
poprawić sam proces emulacji.
Warto podkreślić, że rozwiazanie
˛
opisane w [80] zaburza tylko i wyłacznie
˛
procesy aplikacji
użytkownika – automatyzacja eksperymentów oraz zbieranie wyników jest realizowana przez
aplikacje uruchomione w emulowanym systemie operacyjnym. Wyklucza to zaburzanie kodu
sytemu operacyjnego, co jest jednym z celów niniejszej rozprawy.
3.4.3. Nieinwazyjne śledzenie wykonania
Emulator QEMU wspiera działanie w dwóch trybach – wirtualizacji oraz dynamicznej
binarnej translacji. W przypadku wirtualizacji możliwe jest wyłacznie
˛
emulowanie architektury
zgodnej z architektura˛ systemu emulujacego,
˛
natomiast w przypadku translacji binarnej takiego
ograniczenia nie ma (zagadnienie to zostało szerzej opisane w 3.2). Pomimo, że wirtualizacja
jest technika˛ szybsza˛ od binarnej translacji, to zastosowanie tej drugiej niesie dodatkowe
korzyści zwiazane
˛
ze zwi˛ekszona˛ obserwowalnościa˛ działania emulowanego systemu.
Technika monitorowania wykonywanych instrukcji polega na modyfikacji procesu
dynamicznej translacji tak,
aby wygenerowane bloki kodu emulujace
˛
zachowanie
poszczególnych instrukcji przeplatać z procedurami zbierajacymi
˛
dane dotyczace
˛ bieżacego
˛
kontekstu wykonania. Autor jest zaangażowany w rozwój tej techniki, a szczegółowy jej opis
można znaleźć w [24, 23]. Dzi˛eki tej metodzie emulator może realizować nast˛epujace
˛ zadania:
wyznaczanie pokrycia kodu, obserwacja przetwarzanych danych, określenie zaangażowania
instrukcji wykonywanych w przestrzeni użytkownika i jadra
˛
sytemu operacyjnego przy
realizacji poszczególnych usług.
Nieinwazyjne śledzenie wykonania jest szczególnie użyteczne w kontekście wstrzykiwania
bł˛edów, ponieważ nie wymaga uruchamiania żadnego oprogramowania profilujacego
˛
wewnatrz
˛
emulowanego systemu komputerowego. Zapobiega to sytuacji, w której po wstrzykni˛eciu
bł˛edu emulowany system ulega awarii, zaburzajac
˛ działanie programu profilujacego
˛
lub
uniemożliwiajac
˛ zapisanie wyników jego działania. W zwiazku
˛
z wymienionymi zaletami
nieinwazyjnego śledzenia wykonania QEFI zostało wzbogacone o t˛e funkcj˛e.
3.4.4. Wydajność emulacji
Wydajnościa˛ emulacji określany jest narzut czasowy przy wykonaniu oprogramowania
w środowisku emulatora w porównaniu z wykonaniem na rzeczywistym systemie. Pomiar
wydajności w przypadku QEMU jest zadaniem trudnym, ponieważ jest zależny od wielu
czynników. W [77] przedstawione sa˛ wyniki pomiarów wydajności emulatorów QEMU i
Bochs, w których położono nacisk na badanie wydajności emulacji poszczególnych instrukcji
ISA i zarzadzania
˛
pami˛ecia.˛ W [24] autor przeprowadził pomiar wykorzystujac
˛ dost˛epny
w QEMU specjalny tryb emulacji pojedynczego procesu systemu operacyjnym GNU/Linux.
54
Tryb ten polega na uruchomieniu programu z użyciem emulowanego procesora, natomiast
wywołania systemowe sa˛ przekazywane do rzeczywistego systemu operacyjnego. Pomiary
wydajności z [77] i [24], dały narzut odpowiednio 46 (od 0,26s do 12s) i 4,3 (od 4,7s do 20,35s)
razy dłuższego działania niż bez emulacji. Oznacza to bardzo istotna˛ zależność wydajności
emulacji od wybranego scenariusza poddawanego pomiarom.
3.4.5. Metodyka badań
W wyniku prac prowadzonych przez autora nad automatyzacja˛ testów przygotowana
została oryginalna metodyka badań wykorzystujacych
˛
emulator systemu komputerowego
zaimplementowana w narz˛edziu QEFI. Wst˛epne prace nad QEFI opisane zostały w [23, 25, 26].
Celem metodyki jest przeprowadzanie serii zautomatyzowanych testów, pozwalajacych
˛
zebrać
zbiorcze wyniki dotyczace
˛ podatności na bł˛edy testowanego systemu (SUT7 ).
Podstawowe poj˛ecia
Na potrzeby procesu przeprowadzania automatycznych testów zdefiniowane zostały
nast˛epujace
˛ poj˛ecia:
— SUT – instancja emulowanego systemu komputerowego.
— Scenariusz – seria operacji interakcji z SUT.
— Profilowanie – zbieranie informacji o zdarzeniach wyst˛epujacych
˛
w SUT.
— Wstrzykni˛ecie bł˛edu – modyfikacja środowiska SUT symulujaca
˛ wystapienie
˛
bł˛edu.
— Wynik – dane b˛edace
˛ celem realizacji scenariusza (np. przetworzony plik).
— Funkcja oceny wyniku – funkcja wartościujaca
˛ jakościowo lub ilościowo rezultat
wykonania scenariusza.
— Test – pojedyncze wykonanie scenariusza wraz ze wstrzykni˛eciem bł˛edu.
— Dziennik wykonania – zapis interakcji przeprowadzonej z SUT w ramach testu oraz
dodatkowych informacji o parametrach wstrzykni˛ecia bł˛edu i danych nieinwazyjnego
śledzenia.
— Eksperyment – seria testów opartych o ten sam scenariusz różniaca
˛ si˛e wstrzykni˛etym
bł˛edem (np. inna zaburzona komórka pami˛eci, inny moment wstrzykni˛ecia bł˛edu).
Konfiguracja instancji SUT składa si˛e ze specyfikacji emulowanego systemu
komputerowego oraz obrazów nośników pami˛eci masowej8 .
Konfiguracja systemu
zawiera informacje o architekturze procesora, pojemności pami˛eci RAM, urzadzeniach
˛
komunikacyjnych (np. interfejs sieciowy Ethernet, urzadzenia
˛
USB) oraz urzadzeniach
˛
pami˛eci masowej. Każdy SUT wyposażony jest w co najmniej jedno urzadzenie
˛
pami˛eci
7
Ang. System Under Tests.
Obraz nośnika pami˛eci masowej jest to kopia zawartości i struktury danych zapisanych na nośniku w postaci
jednego lub wi˛ecej plików.
8
55
masowej – np. emulowany dysk twardy lub karta pami˛eci Compact Flash z zainstalowanym
systemem operacyjnym i dodatkowym oprogramowaniem podlegajacym
˛
testom.
Scenariusz jest zapisem automatycznej interakcji z SUT. Operacje b˛edace
˛ składowymi
scenariusza dziela˛ si˛e na dwa typy: komendy środowiska emulacji oraz operacje angażujace
˛
oprogramowanie działajace
˛ w SUT. Komendy służa˛ sterowaniu emulowanym systemem
komputerowym – sa˛ to operacje takie jak podłaczenie
˛
urzadzeń
˛
peryferyjnych (np. pami˛eci
masowej USB), wstrzymanie/wznowienie emulacji, wstrzykni˛ecie bł˛edu (patrz algorytm 3.3),
czy ustanowienie warunkowego wstrzykni˛ecia bł˛edu. Operacje interakcji z oprogramowaniem
sa˛ to dowolne działania korzystajace
˛ z usług SUT – np. nawiazanie
˛
połaczenia
˛
TCP/IP i
zgłoszenie żadania
˛
HTTP lub wysłanie komendy przez konsol˛e dost˛epna˛ przez emulowany port
szeregowy. Każda odpowiedź SUT jest rejestrowana w dzienniku wykonania i w późniejszym
etapie służy ocenieniu dost˛epności poszczególnych usług oraz analizie typów zgłaszanych
awarii.
SUT może być profilowany pod katem
˛
wyst˛epowania pewnych zdarzeń. Profilowanie
realizowane jest przez emulator i polega na wykrywaniu i odnotowywaniu zdefiniowanych
akcji wykonanych przez SUT. Przykładowe zdarzenia to wykonanie przez emulowany procesor
określonego typu instrukcji lub wykonanie instrukcji spod wskazanego adresu.
Wstrzykni˛ecie bł˛edu oznacza modyfikacj˛e środowiska SUT symulujac
˛ a˛ wystapienie
˛
bł˛edu.
Dla każdego bł˛edu określone jest urzadzenie,
˛
typ bł˛edu, lokalizacja oraz moment wstrzykni˛ecia.
Wszystkie urzadzenia
˛
wspierane przez emulator moga˛ być wzbogacone o funkcj˛e symulacji
bł˛edu – np.: pami˛eć RAM, urzadzenia
˛
peryferyjne, rejestry procesora. Dost˛epne typy bł˛edów
oparte sa˛ na modelach opisanych w 2.2.
Lokalizacja określa przestrzeń, która poddana
zostanie zaburzaniu. Przykładowo dla pami˛eci RAM jest to zakres adresów, a dla procesora
zbiór rejestrów, niemniej samo zaburzenie dotyczy tylko jednego, losowo wybranego zasobu
– pojedynczej komórki pami˛eci lub rejestru. Moment wstrzykni˛ecia bł˛edu może być stały
lub warunkowy. W przypadku stałego momentu wstrzykiwania bład
˛ zostanie wprowadzony
zawsze na tym samym etapie wykonania scenariusza. Natomiast warunkowe wstrzykni˛ecie
zwiazane
˛
jest z wystapieniem
˛
pewnego zdarzenia wyzwalajacego
˛
(np. zgłoszenia przerwania
przez jedno z emulowanych urzadzeń
˛
lub wykonania określonej instrukcji przez procesor)
oraz sprawdzeniem wyniku funkcji warunku wstrzykni˛ecia. W chwili wystapienia
˛
zdarzenia
wyzwalajacego
˛
sprawdzana jest wartość funkcji warunku i w przypadku jego spełnienia
uruchamiana jest procedura wstrzykni˛ecia bł˛edu.
Kompletny scenariusz wymaga określenia oczekiwanego wyniku pozwalajacego
˛
stwierdzić,
czy wstrzykni˛ety bład
˛ miał wpływ na system. Przykładowo wynikiem moga˛ być odpowiedzi
działajacego
˛
w SUT serwera HTTP, rezultat próby zalogowania si˛e do systemu poprzez
określony kanał komunikacyjny lub brak przekłamań w przetwarzanych przez SUT plikach.
Dla otrzymanych wyników określone sa˛ funkcje oceny służace
˛ wartościowaniu efektów
56
wstrzykni˛ecia bł˛edu. Funkcje oceny pozwalaja˛ określić stopień realizacji powierzonego SUT
zadania oraz parametrów funkcjonowania systemu. Przykładowe funkcje oceny realizacji
zadania:
— jakościowa charakterystyka wyniku (np. SUT nie odpowiada na wysyłane żadania),
˛
— ilościowy udział poprawnych danych (np. n z k przetwarzanych przez SUT plików ma
poprawna˛ zawartość),
— odst˛epstwo wyniku od wyniku referencyjnego (np. dla wyniku b˛edacego
˛
liczba˛ różnica
mi˛edzy uzyskanym i oczekiwanym wynikiem, a dla wyniku w postaci ścieżki w grafie
różnica w liczbie kraw˛edzi wzgl˛edem oczekiwanej ścieżki).
Przykładowe parametry funkcjonowania systemu:
— czas potrzebny SUT do wygenerowania wyniku,
— obcia˛żenie (np. użyta pami˛eć, wykorzystanie procesora) podczas generowania wyniku,
— informacja o wykrytych przez oprogramowanie bł˛edach,
— czy i w jakim stopniu wynik został oznaczony jako niepewny z uwagi na wykryte w systemie
bł˛edy.
Opracowane algorytmy
Schemat wykonania scenariusza został przedstawiony w postaci pseudokodu w algorytmie
3.1. Tak skonstruowany scenariusz pozwala na przeprowadzenie pojedynczego testu, którego
celem jest zapis wpływu bł˛edu na SUT. Należy wyróżnić trzy główne etapy wykonania
scenariusza: działania przygotowawcze (linie 16-18 algorytmu 3.1), wstrzykni˛ecie bł˛edu lub
konfiguracja warunkowego wstrzykni˛ecia bł˛edu (linie 19-23) oraz przeprowadzanie operacji
majacych
˛
na celu zbadanie, czy system wykonuje poprawnie powierzone zadania (linia
24).
Działania przygotowawcze maja˛ na celu wprowadzenie SUT w odpowiedni stan
poczatkowy
˛
oraz zebranie dodatkowych danych dotyczacych
˛
uruchomionego systemu – krok
ten służy przykładowo oczekiwaniu na rozruch systemu operacyjnego w SUT, zalogowanie si˛e
użytkownika przez konsol˛e szeregowa˛ i zebranie informacji o systemie.
Wykonanie kroków poszczególnych etapów realizowane jest przez funkcj˛e execSteps.
W trakcie wykonania scenariusza komendy emulatora oraz komendy przekazywane do
SUT wydawane sa˛ funkcja˛ issueCommand (linie 5,9 algorytmu 3.1).
W przypadku
emulatora sa˛ to bezpośrednie komendy środowiska emulacji, natomiast komendy SUT
moga˛ być dostarczane dowolnym kanałem (np. sieć lub konsola dost˛epna˛ przez port
szeregowy). Odpowiedzi zapisywane sa˛ z użyciem funkcji readOutput (linie 6-7,10). Dla
komend SUT odczytywane sa˛ dodatkowo komunikaty emulatora (linia 7) ze wzgl˛edu na
możliwość generowania przez emulator dodatkowych informacji o przebiegu wykonania SUT
(np. wystapienie
˛
zdarzeń wyzwalajacych
˛
warunkowe wstrzykni˛ecie bł˛edu lub informacje
pochodzace
˛ z profilowania). Funkcje isSU T Command, getIdleT imeout, getReadT imeout,
getChannel służa˛ odczytaniu właściwości pojedynczego kroku scenariusza.
57
Algorytm 3.1 Pseudokod wykonania scenariusza
Input: Emulator, SU T, f aultData, initSteps, taskSteps, maxSize
Output: executionLog
1: function EXEC S TEPS(steps)
2:
log ← ∅;
3:
for step in steps do
4:
if isSU T Command(step) then
5:
issueCommand(SU T, step);
6:
log ← log ∪ readOutput(getChannel(step),
getIdleT imeout(step), getReadT imeout(step), maxSize);
7:
log ← log ∪ readOutput(Emulator,
getIdleT imeout(step), getReadT imeout(step), maxSize);
8:
else
9:
issueCommand(Emulator, step);
10:
log ← log ∪ readOutput(Emulator,
getIdleT imeout(step), getReadT imeout(step), maxSize);
11:
end if
12:
end for
13:
return log;
14: end function
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
executionLog ← ∅;
startEmulator();
executionLog ← executionLog ∪ execSteps(initSteps);
if ! isConditionalError(f aultData) then
injectImmediateF ault(f aultData);
else
setupConditionalF aultInjection(f aultData);
end if
executionLog ← executionLog ∪ execSteps(taskSteps);
terminateEmulator()
return executionLog;
Algorytm 3.2 przedstawia sposób działania funkcji readOutput. Funkcja readOutput
służy akumulacji kolejnych linii tekstu w dzienniku wykonania.
parametrami:
source, idleT imeout, readT imeout oraz maxSize.
Wywoływana jest z
Parametr source
oznacza źródło odczytu danych, czyli wyjście emulatora lub kanał komunikacji z SUT.
Parametr idleT imeout oznacza jak długo należy czekać na pojawienie si˛e nowych danych
w źródle. Parametr readT imeout służy ograniczeniu maksymalnego czasu zbierania danych
przez funkcj˛e readOutput.
Natomiast parametr maxSize oznacza maksymalna˛ liczb˛e
linii odczytanych ze źródła.
Parametry readT imeout oraz maxSize pozwalaja˛ wykryć
sytuacj˛e generowania danych w źródle w nieskończonej p˛etli – wystarczajace
˛ do tego celu
byłoby zastosowanie tylko jednego z tych parametrów, jednak ze wzgl˛edów praktycznych
58
Algorytm 3.2 Pseudokod funkcji zbierania dzienników wykonania
1: function READ O UTPUT(source, idleT imeout, readT imeout, maxSize)
2:
result ← ∅;
3:
startT ime ← readCurrentT ime();
4:
loop
5:
line ← readLineT imeout(source, idleT imeout);
6:
if line == ∅ then
7:
result ← result ∪ IdleT imeoutM ark;
8:
return result;
9:
end if
10:
result ← result ∪ line;
11:
if |result|== maxSize then
12:
result ← result ∪ M axSizeReachedM ark;
13:
return result;
14:
end if
15:
if readCurrentT ime() − startT ime > readT imeout then
16:
result ← result ∪ ReadT imeoutM ark;
17:
return result;
18:
end if
19:
end loop
20: end function
lepsze jest zastosowanie obu parametrów9 . Funkcja readOutput wykorzystuje wewn˛etrznie
funkcj˛e readLineT imeout – odczytuje ona kolejna˛ lini˛e ze źródła, a jeżeli dane nie sa˛
dost˛epne przez określony czas zwracany jest specjalny znacznik braku wyniku (oznaczony
symbolem ∅). Wykorzystana jest również funkcja readCurrentT ime, która zwraca aktualny
czas. Przyczyna zakończenia działania funkcji jest zaznaczana w zebranym logu w postaci
specjalnych znaczników IdleT imeoutM ark (brak nowych danych), M axSizeReachedM ark
(osiagni˛
˛ eto maksymalny rozmiar odpowiedzi) oraz ReadT imeoutM ark (przekroczono czas
zbierania odpowiedzi).
Natychmiastowe wstrzykni˛ecie bł˛edu (linia 20 algorytmu 3.1) realizowane jest funkcja˛
injectImmediateF ault, która została przedstawiona w algorytmie 3.3. Operacja modyfikacji
środowiska SUT przyjmuje parametr f aultData, który zawiera informacje o urzadzeniu,
˛
typie oraz lokalizacji bł˛edu. Wstrzykni˛ecie musi być poprzedzone zatrzymaniem emulacji
(funkcja pauseEmulation) oraz wyczyszczeniem danych w pami˛eci podr˛ecznej (cache)
emulatora (funkcja f lushCachedData). Operacje te sa˛ konieczne ze wzgl˛edu na wybrany
typ emulatora wykorzystujacy
˛ translacj˛e binarna˛ (patrz 3.2), gdzie przetłumaczone bloki kodu
sa˛ przechowywane w pami˛eci podr˛ecznej i modyfikacja kodu źródłowego nie spowodowałaby
9
Parametr maxSize pozwala na ograniczenie wielkości dziennika wykonania, natomiast readT imeout
pozwala skrócić czas działania funkcji w przypadku generowania nowych danych na źródle co kilkadziesiat
˛ sekund
– dla źródła generujacego
˛
nowa˛ lini˛e co 30 sekund i maxSize = 6000 linii czas testu wydłużyłby si˛e do 50 godzin.
59
Algorytm 3.3 Pseudokod funkcji wstrzykni˛ecia bł˛edu
1: function INJECT I MMEDIATE FAULT(f aultData)
2:
pauseEmulation();
3:
f lushCachedData();
4:
injectF ault(f aultData);
5:
resumeEmulation();
6: end function
Algorytm 3.4 Pseudokod funkcji warunkowego wstrzykni˛ecia bł˛edu
1: f aultInjected ← F ALSE;
2: function CONDITIONAL FAULT I NJECTION C ALLBACK(f aultData)
3:
if f aultInjected then
4:
return ;
5:
end if
6:
if checkInjectCondition(f aultData) then
7:
injectImmediateF ault(f aultData);
8:
f aultInjected ← T RU E;
9:
end if
10: end function
ponownego ich przetłumaczenia. Po przeprowadzeniu wstrzykni˛ecia bł˛edu proces emulacji jest
wznawiany (funkcja resumeEmulation).
Warunkowe wstrzykni˛ecie bł˛edu jest operacja˛ dwuetapowa.˛
Polega na implementacji
mechanizmu typu callback w emulatorze, który wywołuje zaprogramowane akcje w przypadku
wystapienia
˛
określonego zdarzenia b˛edacego
˛
zdarzeniem wyzwalajacym
˛
dla warunkowego
wstrzykni˛ecia bł˛edu. W pierwszym etapie ustanawiane jest zdarzenie, które ma powodować
wyzwolenie procedury callback – jest to np. odczyt danych z emulowanego urzadzenia
˛
lub
wykonanie określonego typu instrukcji przez procesor (linia 22 algorytmu 3.1). Drugim etapem
jest wywołanie procedury callback, gdy wystapi
˛ określone zdarzenie.
Algorytm 3.4 przedstawia działanie funkcji conditionalF aultInjectionCallback. Funkcja
checkInjectCondition może być dowolnie sformułowana.
Przykładowo bład
˛ może być
wprowadzony z zadanym prawdopodobieństwem – oznacza to możliwość wstrzykni˛ecia
bł˛edu przy kolejnych wystapieniach
˛
zdarzenia wyzwalajacego.
˛
Rozwiazanie
˛
to umożliwia
zwi˛ekszenie pokrycia przestrzeni bł˛edów (patrz 2.5.2). Możliwe jest również wykorzystanie
informacji z profilowania dost˛epnych w emulatorze lub uzależnienie wstrzykni˛ecia od
wystapienia
˛
pewnej serii zdarzeń wyzwalajacych.
˛
Weryfikacja, czy SUT poprawnie wykonuje zadania, przeprowadzana jest poprzez
wysyłanie kolejnych żadań.
˛
Żadania
˛
te sa˛ ściśle zwiazane
˛
z charakterem oczekiwanych
wyników – moga˛ to być operacje zwiazane
˛
z przetwarzaniem plików, komunikacja˛ sieciowa˛
lub obsługa˛ urzadzeń.
˛
Dobór zadań powinien być podyktowany analiza,˛ które komponenty sa˛
celem ewaluacji wrażliwości na bł˛edy.
60
Algorytm 3.5 Pseudokod algorytmu przetwarzania wyników eksperymentu
Input: executionLogs, propertyT ests
Output: experimentStatistics
1: experimentStatistics ← ∅;
2: for executionLog in executionLogs do
3:
testResults ← ∅;
4:
for propertyT est in propertyT ests do
5:
testResults[propertyT est] = analizeLog(experimentResults, propertyT est);
6:
end for
7:
experimentStatistics ← experimentStatistics ∪ testResults;
8: end for
Pojedyncze wykonanie scenariusza jest nazywane testem, a seria testów różniacych
˛
si˛e
parametrami wstrzykni˛etego bł˛edu składa si˛e na eksperyment. Wynikiem przeprowadzenia
eksperymentu sa˛ dzienniki wykonania, które poddawane sa˛ analizie.
Analiza polega na
podsumowaniu nast˛epujacych
˛
cech przeprowadzonych testów: wyznaczenie wartości funkcji
oceny, określenie parametrów wstrzykni˛etych bł˛edów, zebranie danych pochodzacych
˛
z
profilowania.
Badanie pojedynczych cech jest przeprowadzane przez osobna˛ procedur˛e.
Algorytm 3.5 przedstawia pseudokod przetwarzania wyników eksperymentu.
Procedury sprawdzajace
˛
kolejne cechy dzienników wykonania moga˛ mieć postać
dowolnych programów.
Procedura przyjmuje na wejściu dziennik wykonania testu, a
wynikiem jest wartość badanej cechy. Procedury realizujace
˛ analiz˛e dzienników wykonania w
podstawowej implementacji opiera si˛e o mechanizm wyrażeń regularnych, jednak moga˛ to być
bardziej zaawansowane automaty (np. badajace
˛ średni czas odpowiedzi SUT). Funkcje oceny
realizacji zadania sa˛ charakterystyczne dla każdego scenariusza. Natomiast zestaw procedur
przedstawionych poniżej jest współdzielony mi˛edzy eksperymentami:
— parametry funkcjonowania systemu:
— czy wstrzykni˛ety bład
˛ został zamanifestowany,
— czy zlecone zadania zostały wykonane poprawnie,
— czy i jaki komunikat bł˛edu został zgłoszony przez system operacyjny,
— czy komunikat o bł˛edzie zawierał informacj˛e stack-trace (patrz 2.1.2),
— czy system operacyjny był dost˛epny przez cały przebieg eksperymentu,
— parametry wstrzykni˛etych bł˛edów:
— określenie fizycznego adresu zaburzanej pami˛eci,
— określenie wirtualnego adresu zaburzanej pami˛eci10 ,
— wartość przechowywana w pami˛eci przed zaburzeniem,
— wartość przechowywana w pami˛eci po zaburzeniu,
— dane pochodzace
˛ z profilowania:
10
O ile informacja ta jest dost˛epna.
61
— liczba wywołań funkcji conditionalF aultInjectionCallback,
— liczba wykonań zaburzonych instrukcji kodu11 ,
— wywołania funkcji alokacji pami˛eci w systemie operacyjnym SUT12 ,
— lista wywołanych funkcji systemu operacyjnego SUT13 .
Do zliczania typów komunikatów systemu przyj˛eto nast˛epujac
˛ a˛ metodyk˛e: dla każdego
artefaktu sprawdzany jest dziennik wykonania pod katem
˛
wyst˛epowania komunikatów danego
typu bł˛edu (np. Paging request failed). Oznacza to, że jeżeli w pojedynczym dzienniku zapisane
sa˛ komunikaty różnego typu to sa˛ one zliczone, natomiast komunikaty tego samego typu nie sa˛
zliczone kilkakrotnie. Przypadki generowania komunikatów w p˛etli można wykrywać poprzez
odpowiednio przygotowana˛ procedur˛e.
W wyniku automatycznej analizy dzienników wykonania uzyskane sa˛ zbiorcze wyniki
pozwalajace
˛ ocenić wpływ danej konfiguracji bł˛edu na SUT. Baza procedur analizujacych
˛
dzienniki wykonania może być rozszerzana stosownie do potrzeb.
Warto zaznaczyć,
że dane uzyskane w ten sposób moga˛ być poddane procesowi eksploracji danych –
opis udanego zastosowania eksploracji danych do danych pochodzacych
˛
z eksperymentów
niezawodnościowych można znaleźć w pracach prowadzonych przez Instytut Informatyki
Politechniki Warszawskiej [37, 101].
Zaprezentowana metodyka może być rozszerzana o dodatkowe funkcje, takie jak
poprzedzenie eksperymentu uruchomieniem pojedynczego testu bez wprowadzania bł˛edu w
celu wyznaczenia interesujacego
˛
podzbioru przestrzeni zaburzania (patrz 2.5.2). Uzupełnienie
to zostało wykorzystane w 4.5.3, gdzie w poprzedzajacym
˛
teście wyznaczony został zbiór
wywołanych funkcji systemu operacyjnego SUT, które były zaburzane podczas właściwego
eksperymentu.
3.4.6. Architektura QEFI
Metodyka opisana w sekcji 3.4.5 została zaimplementowana w środowisku QEFI. W
niniejszej sekcji przedstawiona jest architektura, która pozwoliła na implementacj˛e wszystkich
funkcji opisanej metodyki.
Założenia b˛edace
˛ podstawa˛ opracowanej architektury to:
1. minimalna ingerencja w oprogramowanie QEMU,
2. rozdzielenie procesu emulacji od sterowania przebiegiem testu,
3. rozdzielenie przeprowadzania testu od analizy wyników,
4. możliwość uruchamiania równolegle wielu instancji testów.
Założenie 1 zostało opracowane z myśla˛ o możliwej integracji opracowanych rozszerzeń z
oficjalna˛ wersja˛ QEMU – minimalna ingerencja w kod źródłowy zwi˛eksza szanse na przyj˛ecie
11
12
13
Dotyczy eksperymentów zaburzania kodu systemu operacyjnego SUT.
Wykorzystane w eksperymencie opisanym w 4.5.3.
Dotyczy eksperymentów zaburzania kodu systemu operacyjnego SUT.
62
takiego kodu przez autorów projektu QEMU. Założenie 2 jest rozszerzeniem założenia 1
niosacym
˛
dodatkowe korzyści: uniezależnienie od technologii, w której zostało wykonane
QEMU (j˛ezyk C), oraz możliwość zarejestrowania ewentualnej awarii oprogramowania
QEMU. Założenie 3 umożliwia rozszerzanie bazy procedur analizujacych
˛
cechy dzienników
wykonania bez konieczności ponownego przeprowadzania eksperymentu. Założenie 4 ma
na celu umożliwienie skrócenia czasu przeprowadzania eksperymentu poprzez wykorzystanie
wieloprocesorowych serwerów.
Na podstawie opracowanych założeń przygotowane zostały trzy programy:
— Zmodyfikowana na potrzeby QEFI wersja emulatora QEMU,
— Nadzorca – oprogramowanie automatyzujace
˛ wykonanie testu,
— Analizator – oprogramowanie analizujace
˛ dzienniki wykonania.
Test jest przeprowadzany z udziałem instancji QEMU oraz instancji Nadzorcy, gdzie testowany
system komputerowy (SUT) jest emulowany przez QEMU. Nadzorca oraz QEMU sa˛
osobnymi procesami w systemie operacyjnym i komunikuja˛ si˛e poprzez sieć protokołem
TCP/IP. Założenie 4 realizowane jest poprzez uruchamianie wielu par procesów QEMU
i Nadzorca, a sterowane jest to z udziałem skryptów powłoki systemu GNU/Linux.
Zebrane przez Nadzorc˛e dzienniki wykonania testów przekazywane sa˛ do Analizatora po
przeprowadzeniu eksperymentu w trybie wsadowym. Analizator jest programem w j˛ezyku
Python realizujacym
˛
przetwarzanie dzienników pod katem
˛
wyst˛epowania poszczególnych cech
zgodnie z algorytmem 3.5.
Współpraca wymienionych komponentów przedstawiona jest na rysunku 3.1.
Na
rysunku komponenty oznaczone kolorem pomarańczowym sa˛ opracowane przez autora.
Kolorem niebieskim zaznaczone sa˛ miejsca implementacji algorytmów opisanych w sekcji
3.4.5, kolorem szarym oznaczone jest oryginalne oprogramowanie QEMU, a kolorem
zielonym oprogramowanie poddawane testom. Poniżej zamieszczony jest szczegółowy opis
opracowanych programów oraz procesu przeprowadzania eksperymentów.
Nadzorca
Nadzorca jest głównym komponentem realizujacym
˛
automatyczne przeprowadzanie testu na
podstawie przygotowanego scenariusza. Jest to osobny proces w systemie operacyjnym, który
komunikuje si˛e z SUT poprzez jeden lub wi˛ecej kanałów (połaczenie
˛
1 z rysunku 3.1):
— tunelem do portu szeregowego SUT14 ,
— poprzez sieć TCP/IP:
— bezpośrednie połaczenie
˛
z usługami SUT,
14
Tunel do portu szeregowego działa w sposób nast˛epujacy:
˛
oprogramowanie QEMU uruchamia serwer
TCP/IP, gdzie dane przychodzace
˛ sa˛ przekazywane do portu szeregowego emulowanego systemu, a dane wysyłane
przez emulowany system sa˛ przekazywane do klientów serwera TCP/IP.
63
Nadzorca
Algorytm2)
Scenariusz
QEMU
)
C
Sterowanie
środowiskiem
emulacji
P
Moduł2
wstrzykiwania2
błędów
Algorytm2C
Dziennik
wykonania
Algorytm2h
Analizator
/
Algorytmy2PF2/
h
,
9
SUT
Z
Moduł
śledzenia
wykonania
f
Legenda:
222I2Oprogramowanie2QEFI.
222I2Oryginalne2oprogramowanie2QEMU.
222I2Testowane2oprogramowanie.
222I2Miejsce2wykonania2algorytmu.
)2I2Wysyłanie2komend2do2SUT2-kanałem2jest2np.2sieć2lub
222222konsola2dostępna2przez2port2szeregowyO.2
C2I2Wysyłanie2komend2do2QEMU2-kanałem2jest2połączenie
222222TCPWIPO.2
P2I2Uruchamianie2procedury2wstrzykiwania2błędów2jako
222222opcja2QEMU.2
/2I2Wstrzyknięcie2błędu2poprzez2modyfikację2środowiska2
222222SUT.2
h2I2Zbieranie2danych2wyjściowych2z2SUT.2
f2I2Śledzenie2zdarzeń.2
Z2I2Wyzwalanie2opóźnionej2procedury2wstrzykiwania2
222222błędów.2
,2I2Zbieranie2danych2o2wykonaniu.
92I2Przekazanie2dzienników2wykonania2do2analizy2w2
222222trybie2wsadowym.2
Rysunek 3.1: Architektura QEFI
64
— poprzez uruchomienie dodatkowych programów (np. ssh lub wget) skonfigurowanych
na interakcj˛e z SUT.
Tunel do portu szeregowego jest szczególnym kanałem komunikacji z SUT – systemy
operacyjne uruchamiane w emulowanym systemie komputerowym skonfigurowano tak, aby
udost˛epnić konsol˛e operatora oraz komunikować wszelkie wykryte bł˛edy przez port szeregowy.
Podczas uruchamiania Nadzorca nawiazuje
˛
również połaczenie
˛
TCP/IP konsola˛ sterowania
QEMU (połaczenie
˛
2 z rysunku 3.1). Konsola sterowania udost˛epnia wszelkie operacje majace
˛
zwiazek
˛
z przebiegiem emulacji i wstrzykiwania bł˛edów – np. pauza/wznowienie emulacji,
podglad/modyfikacja
˛
zawartości pami˛eci RAM emulowanego systemu, czy konfiguracja
warunkowego wstrzykni˛ecia bł˛edu.
Dodatkowo na konsoli wypisywane sa˛ informacje
pochodzace
˛ z profilowania i procesu wstrzykiwania bł˛edów.
Dzienniki wykonania stanowiace
˛
pełen zapis interakcji z SUT oraz emulatorem
umieszczane sa˛ w plikach tekstowych. Pliki te sa˛ przedmiotem późniejszej analizy przez
Analizator.
Modyfikacje QEMU
Oprogramowanie QEMU zostało wzbogacone na potrzeby QEFI o dwa dodatkowe moduły:
moduł śledzenia wykonania oraz moduł wstrzykiwania bł˛edów. Moduł śledzenia wykonania
jest odpowiedzialny za monitorowanie skonfigurowanych przy uruchomieniu QEMU zdarzeń.
Przykładowymi zdarzeniami sa:
˛
— wykonanie instrukcji skoku przez emulowany procesor SUT,
— wykonanie kodu SUT zaburzonego poprzednio wstrzykni˛eciem bł˛edu,
— wywołanie wskazanych funkcji jadra
˛ systemu operacyjnego,
— zgłoszenie przerwania przez wskazane urzadzenie,
˛
— wykonanie akcji przez wskazane urzadzenie.
˛
Cz˛eść z wymienionych zdarzeń nie jest dost˛epna do wykorzystania w każdej z konfiguracji SUT
– szczegółowy opis wykorzystania poszczególnych zdarzeń wykorzystanych w eksperymentach
przedstawiony jest w rozdziale 4.
Moduł wstrzykiwania bł˛edów służy modyfikacji środowiska wykonania SUT w sposób,
który symuluje wystapienie
˛
bł˛edu. Dowolne z emulowanych przez QEMU urzadzeń
˛
może być
wzbogacone o funkcj˛e wstrzykiwania bł˛edów. Moduł wstrzykiwania bł˛edów realizuje zarówno
natychmiastowe wstrzykni˛ecie bł˛edu (algorytm 3.3), jak i warunkowe (algorytm 3.4). Diagram
sekwencji realizacji warunkowego wstrzykni˛ecia przedstawiony jest na rysunku 3.2.
Analizator
Analizator przetwarza dzienniki wykonania i realizuje algorytmy oceny w celu przygotowania
zbiorczych statystyk kampanii.
15
Wyjściowe dane zapisywane sa˛ w formacie CSV15
Ang. Comma-separated Values.
65
Nadzorca
QEMU
SUT
setupConditionalFaultInjection()
issueCommand()
obsługa emulowanej funkcji
conditionalFaultInjectionCallback()
Rysunek 3.2: Diagram sekwencji warunkowego wstrzykni˛ecia bł˛edu
pozwalajacym
˛
na wizualizacj˛e oraz dalsza˛ analiz˛e przez operatora z użyciem oprogramowania
typu Microsoft Excel, czy pakietu R-project16 .
Przeprowadzanie eksperymentów
Sposób wykonania pojedynczego testu umożliwia uruchomienie wielu testów jednocześnie.
Jest to istotna cecha, dzi˛eki której wykorzystane sa˛ możliwości wieloprocesorowych systemów
komputerowych do przeprowadzania eksperymentów na masowa˛ skal˛e.
QEFI zostało
wyposażone w funkcj˛e uruchamiania wielu instancji testów jednocześnie. Prawidłowe działanie
takiej konfiguracji zostało zapewnione poprzez nast˛epujace
˛ decyzje projektowe:
— każda para programów Nadzorca/QEMU uruchamiana jest w dedykowanym katalogu
roboczym,
— każda para programów Nadzorca/QEMU wykorzystuje unikatowe numery portów dla
połaczeń
˛
TCP/IP,
— liczby służace
˛ do inicjalizacji generatorów liczb pseudolosowych sa˛ przydzielane globalnie
każdej instancji Nadzorcy17 ,
— obrazy dysków twardych emulowanych systemów komputerowych używane sa˛ w trybie
migawki, czyli żadna modyfikacja zawartości dysku nie jest zapisywana do pliku obrazu, a
jedynie przechowywana w pami˛eci przez czas działania SUT.
QEFI z powodzeniem zostało uruchomione na serwerach Instytutu Informatyki Politechniki
Warszawskiej, dzi˛eki czemu możliwe było znaczne skrócenie czasu potrzebnego na
16
http://www.r-project.org
Generatory liczb pseudolosowych wykorzystywane sa˛ przy wyznaczaniu zaburzanych lokalizacji oraz w
funkcji delayedF aultInjectionCallback przedstawionej w algorytmie 3.4.
17
66
przeprowadzanie eksperymentów. Kolejnym etapem zwi˛ekszajacym
˛
możliwości równoległego
uruchamiania testów byłoby przystosowanie QEFI do rozproszonych środowisk typu cluster18
oraz grid19 .
Instytut Informatyki Politechniki Warszawskiej z powodzeniem opracował
rozwiazanie
˛
przeprowadzania eksperymentów SWIFI w środowiskach rozproszonych [99,
100]. Przystosowanie QEFI do takiego trybu pracy wymagałoby opracowania nast˛epujacych
˛
mechanizmów:
— konfiguracji środowiska QEFI na w˛ezłach przetwarzania,
— dystrybucji środowiska eksperymentu,
— zbierania dzienników wykonania przeprowadzonych testów,
— automatyzacji działania w˛ezłów przetwarzania.
Możliwym rozwiazaniem
˛
problemu konfiguracji w˛ezłów przetwarzania byłoby przygotowanie
obrazu maszyny wirtualnej (plik o wielkości około 3GB), który zawierałby przygotowane
środowisko QEFI (skompilowane wersje programów Nadzorca oraz QEMU). Obraz należałoby
pobrać na w˛ezły przetwarzania i uruchomić maszyn˛e wirtualna.˛ Rozwiazanie
˛
tego typu jest
mniej pracochłonne od konfiguracji QEFI na każdym z w˛ezłów osobno, ponieważ maskowane
sa˛ różnice poszczególnych w˛ezłów przetwarzania (np. różne systemy operacyjne, inne
wersje zainstalowanych bibliotek programistycznych). Dystrybucja środowiska eksperymentu
sprowadza si˛e do dystrybucji na w˛ezły przetwarzania trzech plików: obrazu dysku twardego
SUT, konfiguracji QEMU dla SUT oraz konfiguracji Nadzorcy. Najwi˛ekszym z wymienionych
plików jest obraz dysku SUT – w zależności od konfiguracji może to być od kilkuset
MB to kilkunastu GB. Natomiast zbieranie dzienników wykonania może być realizowane
poprzez automatyczne wysyłanie ich na dedykowany serwer plików.
Oprogramowanie
automatyzacji działania w˛ezłów przetwarzania powinno realizować nast˛epujace
˛ zadania:
automatyczne pobieranie środowiska eksperymentu, przeprowadzenie eksperymentu oraz
wysłanie dzienników wykonania przeprowadzonych testów do wskazanego repozytorium.
3.4.7. Charakterystyka bł˛edów symulowanych w QEFI
W zaproponowanej architekturze QEFI możliwe jest symulowanie bł˛edów trwałych,
przemijajacych
˛
i migoczacych
˛
modelowanych jako bł˛edy sklejeń, sprz˛eżeń oraz bit-flip. Bł˛edy
te moga˛ być wprowadzane do poszczególnych emulowanych urzadzeń,
˛
takich jak pami˛eć RAM,
rejestry procesora, czy pami˛eci masowe. Istotna˛ cecha˛ QEFI jest potencjalna możliwość
symulowania bł˛edów behawioralnych np. zgłaszanie przez urzadzenie
˛
niemaskowalnych
przerwań – bł˛edy tego typu były obserwowane przy zastosowaniu fizycznych zaburzeń
pracy układu w [8] (promieniowanie radioaktywne, zwarcie/rozwarcie ścieżek układów,
promieniowanie elektromagnetyczne).
18
Przetwarzanie na wielu homogenicznych systemach komputerowych (w˛ezłach) połaczonych
˛
wydajna˛
siecia.˛
19
Przetwarzanie na wielu heterogenicznych systemach komputerowych (w˛ezłach) połaczonych
˛
siecia.˛
67
Ze wzgl˛edu na wykorzystanie emulacji procesora nie jest brane pod uwag˛e badanie
wpływu bł˛edów na mikroarchitektur˛e procesora – potok instrukcji, układ przewidywania
skoków, czy pami˛eć podr˛eczna20 nie sa˛ emulowane w QEMU. Niemniej prowadzone sa˛
prace nad badaniem propagacji bł˛edów fizycznych na model logiczny. W [43] przedstawiono
mechanizm wstrzykiwania bł˛edów na poziomie emulatora procesora przygotowanego w j˛ezyku
VHDL. Dzi˛eki takiemu podejściu autorzy mogli wpływać na ukryte rejestry procesora,
niewidoczne dla interfejsu programistycznego. Uzyskane wyniki pokazuja,˛ że cz˛eść bł˛edów
wprowadzonych w ukryte rejestry manifestuje si˛e jako bł˛edy typowe dla pami˛eci (np. bł˛edy
sklejeń w rejestrach), a cz˛eść nie manifestuje si˛e jako bł˛edy na poziomie logicznym. Świadczy
to o komplementarności obu podejść.
QEFI pozwala na efektywne21 przeprowadzanie
eksperymentów ukierunkowanych na system jako całość z wykorzystaniem modeli bł˛edów,
które sa˛ opracowywane wykorzystujac
˛ emulacj˛e na poziomie mikroarchitektury.
Podobne zachowanie wia˛że si˛e z implementacja˛ emulacji urzadzeń,
˛
gdzie QEFI
umożliwia wpływanie na protokół komunikacji urzadzenia
˛
i systemu na poziomie logicznym.
Rozwiazaniem
˛
tego problemu byłaby integracja niskopoziomowych modeli urzadzeń
˛
w j˛ezyku
VHDL (prace zmierzajace
˛ w tym kierunku opisane sa˛ w [93]), niemniej pewna˛ przeszkod˛e
stanowi fakt, iż dost˛epność niskopoziomowych specyfikacji wielu urzadzeń
˛
wykorzystywanych
komercyjnie jest ograniczona.
3.4.8. Zastosowanie metodyki
Przestawiona metodyka jest oryginalnym rozwiazaniem
˛
realizujacym
˛
SWIFI. Dzi˛eki
zastosowaniu emulacji możliwe jest badanie wpływu bł˛edów urzadzeń,
˛
pami˛eci oraz procesora
na oprogramowanie zarówno systemu operacyjnego, jak i aplikacji użytkownika. Skuteczność
zaproponowanej metodyki zależy od nast˛epujacych
˛
elementów:
— doboru modeli wstrzykiwanych bł˛edów,
— adekwatności profilu wstrzykiwanych bł˛edów w urzadzenia,
˛
— zgodności profilu testowania z profilem wykorzystania testowanego oprogramowania.
Sposób wyznaczania modeli bł˛edów został opisany w 3.4.7.
Zagadnienie opracowywania profilu bł˛edów najcz˛eściej wyst˛epujacych
˛
w urzadzeniach
˛
zostało przedstawione w [55]. Niestety badania tego typu nie sa˛ przeprowadzane dla urzadzeń
˛
oferowanych konsumentom lub ich wyniki nie sa˛ podawane do publicznej wiadomości.
Możliwościa˛ poprawienia tego stanu jest wzbogacenie systemów operacyjnych o próby
diagnozowania, czy dana awaria programowa została wywołana bł˛edami urzadzeń
˛
i zbieranie
tych danych z udziałem telemetrii.
20
Symulacja bł˛edów w pami˛eci podr˛ecznej jest potencjalnie możliwa niewielkim nakładem pracy, po
wzbogaceniu QEMU o jej emulacj˛e.
21
Przykładowo próba modelowania pami˛eci RAM w j˛ezyku VHDL do badania wpływu przekłamań na
działanie aplikacji byłaby bardzo kosztowna obliczeniowo.
68
Problem opracowania profilu testowania dla systemów komputerowych typu COTS nie
jest trywialny w zwiazku
˛
z szerokim spektrum zastosowań. Możliwe jest jednak określenie
krytycznych scenariuszy, czy niebezpiecznych stanów. Przykładem wrażliwego scenariusza
jest proces aktualizacji oprogramowania (patrz [85]). Natomiast przykładem niebezpiecznego
stanu jest „zawieszenie” si˛e systemu bez możliwości dokonania jakiejkolwiek diagnostyki lub
informacji o przyczynie awarii. Prace polegajace
˛ na zwi˛ekszaniu niezawodności powinny być
ukierunkowane w pierwszej kolejności na te właśnie aspekty działania systemu, a nast˛epnie
pozostałych funkcji zwiazanych
˛
z obsługa˛ żadań
˛
użytkownika.
Zastosowanie emulacji wpływa również na sposób zbierania pomiarów czasu wykonania
testów. Pomiar czasu testu wykonanego na emulowanym systemie mógłby być odmienny
od czasu zmierzonego na rzeczywistym urzadzeniu
˛
ze wzgl˛edu na narzut emulacji22 oraz
fakt, że emulator jest zwykłym procesem i podlega wywłaszczeniu – oznacza to, że wi˛eksze
obcia˛żenie systemu przeprowadzajacego
˛
eksperyment wpływa na czas emulacji. Niemniej
możliwe jest badanie liczby wykonanych instrukcji przez emulowany procesor i szacowanie
na tej podstawie czasu wykonania poszczególnych etapów testu. Warto jednak zwrócić uwag˛e
na ograniczenia wnioskowania na podstawie liczby wykonanych instrukcji przez emulowany
procesor. W rzeczywistych procesorach te same instrukcje moga˛ mieć różny czas wykonania
zależny od kontekstu – dost˛epności danych w pami˛eci podr˛ecznej, czy skuteczności działania
układu przewidywania skoków.
3.5. Podsumowanie
W niniejszym rozdziale przedstawiona została charakterystyka wykorzystania emulatora
w badaniu niezawodności oprogramowania wraz z opisem oryginalnej metodyki badawczej
i algorytmów zaimplementowanej w systemie QEFI opartym o emulator QEMU.
Zaproponowana metodyka wraz z opracowanymi algorytmami oferuje korzyści wzgl˛edem
dost˛epnych rozwiazań
˛
w postaci poddawania testom systemu komputerowego jako
całości, zwi˛ekszonej kontroli nad eksperymentem i możliwościa˛ nieinwazyjnego śledzenia
wykonania.
QEFI jest podstawowym narz˛edziem w badaniach opisanych w rozdziałach
4 i 5, gdzie posłużyło poszerzeniu stanu wiedzy o niezawodności różnych konfiguracji
systemów komputerowych oraz projektowaniu i ocenie skuteczności nowych mechanizmów
zwi˛ekszajacych
˛
niezawodność.
22
Czasy emulacji instrukcji nie odpowiadaja˛ czasom wykonania instrukcji przez rzeczywisty procesor [77].
69
4. Badania eksperymentalne
Zastosowanie QEFI w procesie wstrzykiwania bł˛edów wprowadza nowe możliwości
badania niezawodności systemów komputerowych.
Opracowano oryginalne scenariusze
eksperymentów oparte o metodyk˛e opisana˛ w rozdziale 3, które ukierunkowane sa˛ na
badanie różnych architektur sprz˛etowych, systemów operacyjnych, a także poszczególnych
komponentów systemu operacyjnego GNU/Linux. Uzyskane wyniki pozwalaja˛ poszerzyć
stan wiedzy poprzez porównanie charakterystyk badanych systemów oraz służa˛ identyfikacji
krytycznych cz˛eści systemu operacyjnego.
Przeprowadzenie eksperymentów opartych o ten sam scenariusz testowy z zastosowaniem
SUT wykorzystujacych
˛
różne architektury jednostek przetwarzajacych
˛
pozwala porównać
podatność na bł˛edy różnych architektur (poziom ISA). Eksperymenty wykorzystujace
˛ taka˛
sama˛ architektur˛e sprz˛etowa,˛ ale różne systemy operacyjne, pozwalaja˛ ocenić wpływ sposobu
implementacji systemu operacyjnego na wrażliwość na bł˛edy.
Ostatnia cz˛eść rozdziału poświ˛econa została opisowi eksperymentów ukierunkowanych na
badanie wrażliwości systemu operacyjnego GNU/Linux. Zrealizowane zostały eksperymenty
symulujace
˛ bł˛edy wyst˛epujace
˛ w różnych urzadzeniach
˛
emulowanych systemów.
W
szczególności uwaga została poświ˛econa eksperymentom profilowanym na różne typy danych
wykorzystywanych przez system operacyjny. Uzyskane wyniki eksperymentów zaburzania
kodu, stosu oraz danych alokowanych systemu operacyjnego pozwalaja˛ na określenie
zachowania systemu komputerowego w przypadku wystapienia
˛
bł˛edów oraz wyznaczenie
wartości metryk opisanych w rozdziale 2. Zastosowanie profilowania pozwoliło również na
znaczne zwi˛ekszenie efektywności przeprowadzonych eksperymentów. Zebrane dane stanowia˛
punkt wyjścia dla dalszych rozważań dotyczacych
˛
projektowania mechanizmów zwi˛ekszania
niezawodności przedstawionych w rozdziale 5.
4.1. Plan przeprowadzonych eksperymentów
Celem
przeprowadzonych
eksperymentów
jest
zbadanie
wrażliwości
na
bł˛edy
oprogramowania systemów operacyjnych, a nast˛epnie opracowanie nowych mechanizmów
zwi˛ekszania niezawodności. Brany pod uwag˛e jest szeroki aspekt zastosowania systemów
operacyjnych – różnych implementacji systemów, wykorzystania różnych architektur
sprz˛etowych, a także wrażliwości na bł˛edy poszczególnych komponentów systemu.
71
QEFI
dzi˛eki
swojej
architekturze
umożliwia
przeprowadzanie
nowych
typów
eksperymentów: porównanie architektur sprz˛etowych na poziomie ISA, porównanie różnych
implementacji systemów operacyjnych, a także eksperymenty ukierunkowane na szczegółowe
badanie niezawodności oprogramowania wskazanego systemu operacyjnego.
W celu
ilustracji tych możliwości zostały opracowane oryginalne scenariusze eksperymentów.
Eksperymenty opisane w niniejszym rozdziale prezentuja˛ możliwości QEFI według
nast˛epujacego
˛
schematu: najpierw przedstawione sa˛ eksperymenty służace
˛ całościowemu
porównywaniu różnych konfiguracji SUT w obliczu bł˛edu tego samego typu, a nast˛epnie
szczegółowym badaniom poddany został wybrany system z wykorzystaniem mechanizmów
profilowania oraz zastosowaniem bł˛edów innych typów (bł˛edy symulowane w emulowanych
urzadzeniach).
˛
Główne założenie dotyczace
˛ projektowania scenariuszy to wykorzystanie krytycznych
usług systemu komputerowego.
W szczególności dotyczy to możliwości komunikacji
i diagnostyki systemu, a także wykorzystania usług systemu operacyjnego niezb˛ednych
do działania aplikacji (np. zarzadzanie
˛
procesami, pami˛eć wirtualna, system plików,
wykorzystanie wskazanych urzadzeń).
˛
Przy badaniu niezawodności systemu operacyjnego
konieczny jest odpowiedni dobór uruchomionych aplikacji, które korzystaja˛ z jego usług. Warto
zauważyć, że nacisk położony jest na sposób interakcji aplikacji z systemem operacyjnym,
ponieważ wiele aplikacji użytkownika realizujacych
˛
zupełnie inne funkcje może korzystać z
tych samych usług systemu. Przykładowo program wypisujacy
˛ zawartość pliku tekstowego
na konsol˛e użytkownika oraz program wyliczajacy
˛ sum˛e md5 zawartości pliku maja˛ zupełnie
inna˛ implementacj˛e, inaczej obcia˛żaja˛ procesor, ale oba z nich wykorzystuja˛ przede wszystkim
interfejs systemu plików oraz dost˛ep do konsoli użytkownika. Istotny jest również kontekst
uruchamiania tych aplikacji – w zależności od lokalizacji przetwarzanego pliku moga˛ być
wywoływane procedury systemu operacyjnego odpowiedzialne za dost˛ep do dysku twardego,
peryferyjnych urzadzeń
˛
pami˛eci (np. karty Compact Flash, Pendrive USB), czy zasobów
sieciowych (przy wykorzystaniu NFS1 ).
Podczas opracowywania scenariuszy zostało przyj˛ete założenie, iż eksperymenty
ukierunkowane na różne architektury sprz˛etowe oraz implementacje systemów operacyjnych
wykorzystuja˛ ten sam scenariusz w celu umożliwienia porównania wyników. Założenie to
wynika z ch˛eci określenia wrodzonej podatności na bł˛edy różnych konfiguracji, niemniej wia˛że
si˛e z pewnymi ograniczeniami. Opracowany scenariusz musi być możliwy do uruchomienia
z minimalnymi modyfikacjami na wszystkich systemach operacyjnych.
Dodatkowo w
zwiazku
˛
z wykorzystaniem różnych emulowanych architektur sprz˛etowych ograniczona jest
możliwość profilowania SUT. Opracowanie mechanizmów profilowania opisanych w 3.4
wymaga ingerencji w oprogramowanie emulatora specyficzne dla emulowanej architektury
1
Ang. Network File System.
72
oraz dogł˛ebnej analizy implementacji systemu operacyjnego działajacego
˛
w SUT. Niemniej
scenariusz opisany w 4.2 i wykorzystany w 4.3 i 4.4 pozwala na efektywne porównanie
badanych systemów komputerowych bez zastosowania tych mechanizmów – SUT w jego
przebiegu realizuje usługi zwiazane
˛
obsługa˛ konsoli operatora, zarzadzaniem
˛
procesami,
komunikacja˛ sieciowa˛ oraz systemem plików. Profilowanie zostało zaimplementowane dla
systemu działajacego
˛
pod kontrola˛ systemu GNU/Linux na architekturze x86 i wykorzystane
w eksperymentach opisanych w 4.5.1, 4.5.3 – implementacja może być również przeniesiona
na pozostałe konfiguracje stosownie do potrzeb.
Eksperymenty ukierunkowane na badanie zachowania jadra
˛
systemu operacyjnego
przy bł˛edach w urzadzeniach
˛
wejścia/wyjścia opisane w 4.5.1 wykorzystuja˛ scenariusze
sprofilowane pod katem
˛
wykorzystania urzadzeń.
˛
Dla wstrzykiwania bł˛edów w protokół
wymiany danych pomi˛edzy systemem operacyjnym i interfejsem sieciowym wykorzystano
ponownie scenariusz opracowany w 4.2, ponieważ wykorzystuje on usługi sieciowe. Natomiast
dla eksperymentów wstrzykiwania bł˛edów w urzadzenia
˛
zwiazane
˛
z obsługa˛ USB opracowano
dedykowany scenariusz.
W eksperymentach opisanych w 4.5.2 zaburzana przestrzeń została zaw˛eżona do
statycznego kodu2 , danych tylko do odczytu i danych statycznych (patrz 2.1.2) systemu
operacyjnego. W eksperymentach wykorzystano również scenariusz opracowany w 4.2 w
celu ilustracji poziomu zwi˛ekszenia wartości współczynnika manifestacji bł˛edów wzgl˛edem
eksperymentów przeprowadzonych w 4.2.
Eksperymenty zaprezentowane 4.5.3 wykorzystuja˛ mechanizmy profilowania opisane w
3.4 do zaw˛eżenia zaburzanej przestrzeni do kodu systemu operacyjnego wykonywanego3
w scenariuszu, a także stosu i danych alokowanych.
scenariusze.
Eksperymenty te oparte sa˛ o dwa
Pierwszy z nich, to scenariusz opisany w 4.2 – wyniki uzyskane z jego
użyciem moga˛ zostać porównane z wynikami eksperymentów opisanymi w 4.2 i 4.5.2 w
celu ilustracji zwi˛ekszenia efektywności eksperymentów dzi˛eki zastosowaniu mechanizmów
profilowania (poprzez zwi˛ekszenie wartości współczynnika manifestacji bł˛edów). Natomiast
drugi scenariusz realizuje testowanie SUT udost˛epniajacego
˛
usług˛e serwera HTTP w celu
zbadania efektów bł˛edów w scenariuszu realizowanym w wielu produkcyjnych systemach oraz
zestawieniu tych wyników z wynikami uzyskanymi z zastosowaniem pierwszego scenariusza.
W przypadku eksperymentów zaburzania pami˛eci RAM modelowano bł˛edy typu bit-flip.
Uzasadnione to jest udokumentowanym cz˛estym wyst˛epowaniem tego typu bł˛edu (patrz 2.2.4).
W przypadku bł˛edów urzadzeń
˛
również zastosowano bład
˛ typu bit-flip symulujac
˛ wyst˛epowanie
zaburzeń w rejestrach tych urzadzeń.
˛
W planie eksperymentów przyj˛eto założenie o zbadaniu
efektów wybranego typu bł˛edów w różnych konfiguracjach, niemniej inne typy bł˛edów
2
Kod wykonywany w przestrzeni jadra
˛
systemu operacyjnego, który nie jest cz˛eścia˛ ładowanego modułu
(patrz 2.1.2).
3
Dzi˛eki czemu gwarantowana jest aktywacja bł˛edu.
73
(np. bł˛edy w rejestrach procesora, czy bł˛edy zgłaszania niemaskowalnych przerwań) moga˛
stanowić podstaw˛e dalszych badań.
4.2. Profilowanie wrażliwości na bł˛edy badanej architektury sprz˛etowej
Podstawowym zagadnieniem zwiazanym
˛
z przeprowadzaniem eksperymentów jest
określenie liczby testów wystarczajacej
˛ do określenia wiarygodnej charakterystyki wrażliwości
na bł˛edy systemu.
W celu wyznaczenia tej liczby dla eksperymentu wstrzykiwania
pojedynczego bł˛edu typu bit-flip w pami˛eć RAM emulowanego systemu przeprowadzono
eksperyment składajacy
˛ si˛e z 500 000 testów. Nast˛epnie zbadano statystyczna˛ wiarygodność
uzyskanych wyników, określono bład
˛ w przypadku zmniejszenia liczby testów w
eksperymencie oraz wyznaczono liczb˛e testów dla eksperymentów opisanych w 4.3 i 4.4. Cele
poboczne przeprowadzonego eksperymentu to zebranie ogólnej charakterystyki zgłaszanych
awarii oraz zbadanie wykorzystania pami˛eci przez system.
Konfiguracja eksperymentu
Emulowany system komputerowy jest to system x86 działajacy
˛ pod kontrola˛ systemu
operacyjnego Debian Lenny z jadrem
˛
GNU/Linux w wersji 2.6.26. Obraz dysku twardego z
zainstalowanym systemem pochodzi z oficjalnych repozytoriów projektu Debian4 . SUT ma
dost˛ep do zasobów sieciowych poprzez emulowany interfejs Ethernet.
Według założeń eksperymentu przekłamana komórka pami˛eci RAM jest wybrana losowo,
a moment wstrzykni˛ecia bł˛edu jest stały (patrz 3.4.5) – założenia takie zostały wprowadzone,
ponieważ w podstawowej konfiguracji emulator nie ma możliwości określenia przeznaczenia
poszczególnych rejonów pami˛eci, ani nie jest wyposażony w dodatkowa˛ instrumentacj˛e
pozwalajac
˛ a˛ określić stan emulowanego systemu operacyjnego. Wprowadzenie mechanizmów
zbierajacych
˛
wymienione informacje wymaga dodatkowego nakładu pracy. Prace te zostały
wykonane dla architektury x86, a ich wynik opisany jest w sekcjach 4.5.2 oraz 4.5.3).
Niemniej warto zaznaczyć, że atutami wynikajacymi
˛
z modyfikacji bezpośrednio adresów
pami˛eci fizycznej jest możliwość badania podatności na bł˛edy poszczególnych obszarów
przestrzeni pami˛eci RAM oraz jednakowa procedura wstrzykiwania bł˛edów niezależnie
od tego, czy wybrane komórki pami˛eci zawieraja˛ kod, czy dane emulowanego systemu
(tak jak to ma miejsce w 4.5.3).
Wada˛ takiego rozwiazania
˛
sa˛ przypadki zaburzania
pami˛eci niewykorzystywanej przez system w momencie wstrzykni˛ecia, co powoduje, że
bł˛edy nie sa˛ aktywowane. W celu ograniczenia tego efektu do minimum, podj˛eta została
decyzja o użyciu najmniejszej ilości pami˛eci, która pozwala na uruchomienie emulowanego
systemu komputerowego i przeprowadzenie eksperymentu.
Wielkość pami˛eci została
wyznaczona poprzez seri˛e prób uruchomienia emulowanego systemu komputerowego z
4
http://people.debian.org/˜aurel32/qemu/i386
74
1
2
3
4
5
6
7
8
[QEMU] Uruchomienie SUT.
[ SUT] Zalogowanie si˛
e do systemu administratora przez konsol˛
e dost˛
epna˛
,→ przez port szeregowy.
[QEMU] Wstrzykni˛
ecie pojedynczego bł˛
edu typu bit-flip w losowo wybrana˛
,→ komórk˛
e pami˛
eci RAM.
[ SUT] Pobranie przez sieć pliku z lokalizacji sieciowej za pomoca˛
,→ programu wget.
[ SUT] Wypisanie na konsol˛
e operatora zawartości pobranego pliku.
[ SUT] Utworzenie katalogu i przeniesienie do niego pobranego pliku.
[ SUT] Ponowne wypisanie na konsol˛
e operatora zawartości pobranego pliku.
[QEMU] Wyłaczenie
˛
SUT.
Scenariusz QEFI 4.1: Zaburzanie pami˛eci RAM przy obsłudze konsoli operatora, komunikacji
sieciowej oraz wykorzystaniu systemu plików
różna˛ pojemnościa˛ pami˛eci RAM. W pierwszym kroku sprawdzane było 8 MB pami˛eci,
a w każdym nast˛epnym pami˛eć o 8 MB wi˛eksza od wielkości w kroku poprzednim.
Dla architektury x86 wymagana ilość pami˛eci została ustalona na 32 MB. Niemniej
w celu umożliwienia porównywania wyników eksperymentów opisanych w niniejszym
rozdziale (eksperymenty AMD64-GNU/Linux, PowerPC-GNU/Linux, MIPS-GNU/Linux,
ARM-GNU/Linux, x86-GNU/Linux, x86-FreeBSD, x86-Minix) wprowadzone zostało
dodatkowe założenie, aby wszystkie badane konfiguracje emulowanych systemów były
wyposażone w taka˛ sama˛ ilość pami˛eci. Minimalna ilość pami˛eci, która spełnia te wymagania,
została wyznaczona na 48 MB – próba ustawienia mniejszej ilości pami˛eci RAM powodowała,
że system operacyjny skompilowany na architektur˛e AMD64 nie uruchamiał si˛e.
Scenariusz testu5 uruchamianego w ramach eksperymentu składa si˛e z kroków
zamieszczonych w scenariuszu 4.1. W powyższym zapisie znacznikami [QEMU] oznaczono
komendy środowiska emulacji, natomiast znacznikami [SUT] komendy wysyłane do
SUT (patrz 3.4.5, 3.4.6).
Zdefiniowany scenariusz oprócz podstawowych usług systemu
operacyjnego takich jak zarzadzanie
˛
procesami czy pami˛ecia˛ wykorzystuje dodatkowo
nast˛epujace
˛ usługi: obsług˛e konsoli operatora, uruchamianie nowych procesów, stos sieciowy
oraz system plików.
Wyniki
Artefaktami przeprowadzenia eksperymentu sa˛ dzienniki wykonania, które zgodnie z metodyka˛
(patrz 3.4.5) zostały poddane analizie.
Badanie cech dzienników wykonano poprzez
dopasowywanie wyrażeń regularnych na plikach b˛edacych
˛
zapisem przebiegu każdego
eksperymentu. Określenie, czy zadanie zostało wykonane poprawnie polega na sprawdzeniu,
czy dwukrotnie została wypisana na konsol˛e operatora zawartość pobranego pliku (odpowiedzi
SUT w krokach 5 i 7 scenariusza 4.1). Komunikaty jadra
˛ systemu operacyjnego sa˛ wykrywane
5
W dalszej cz˛eści rozprawy poj˛ecia „scenariusz testu” oraz „scenariusz eksperymentu” stosowane sa˛
zamiennie i odnosza˛ si˛e do serii kroków interakcji z SUT zgodnie z definicja˛ zamieszczona˛ w 3.4.5.
75
dzi˛eki specjalnemu znacznikowi, który poprzedza wszelkie tego typu wiadomości wypisywane
na konsol˛e operatora6 . Rozstrzygni˛ecie, czy system operacyjny pozostał dost˛epny polega
na sprawdzeniu wyrażeniem regularnym, czy po kolejnych komendach wydawanych przez
emulowanego administratora pojawiał si˛e znak zach˛ety7 .
Czas wykonania pojedynczego testu wynosi od 3 do 4 minut w zależności od wydajności
maszyny przeprowadzajacej
˛ eksperyment. Wi˛ekszość czasu poświ˛econego na test przypada na
rozruch emulowanego systemu komputerowego (krok 1 w scenariuszu 4.1) – około 2 minut.
Pozostały czas jest podzielony na okresy oczekiwania na odpowiedź systemu po wydanej
komendzie. Czas wykonania eksperymentu składajacego
˛
si˛e z 500 000 iteracji testów to około
30 dni, przy czym wykorzystywane były maszyny o nast˛epujacych
˛
konfiguracjach: 4 x AMD
Opteron 16C 6276 2.33GHz (64 procesory logiczne), 320 GB RAM; 2 x Intel Xeon CPU
E5-2630 2.30GHz (24 procesory logiczne), 32 GB RAM.
W przeprowadzonym eksperymencie bł˛edy zamanifestowały si˛e w 0,58% testów (jest
to wartość współczynnika Fs ).
Dokładność tego współczynnika zależna jest od liczby
przeprowadzonych testów i możliwe jest określenie przedziału ufności.
W tym celu
można przedstawić eksperyment jako ciag
˛ prób Bernoulliego z parametrem p. Zgodnie z
teoria˛ statystyczna˛ (na podstawie [66]) przedział ufności dla obserwowanego parametru p̂ i
dokładności α wyrażony jest wzorem:
Wzór 4.2.1.
s
[p̂ − zα/2
s
p(1 − p)
p(1 − p)
; p̂ + zα/2
]
N
N
,gdzie
p – parametr rozkładu Bernoulliego,
p̂ – obserwowana wartość parametru p,
α – dokładność oszacowania ufności,
zα/2 – kwantyl rz˛edu 1 − α/2 standaryzowanego rozkładu normalnego,
N – liczba prób.
Dla α = 0, 05, czyli przedziałowi o ufności 95% wartość zα/2 wynosi 1,96. Pewnym
problemem jest zależność wzoru 4.2.1 od nieznanej wartości parametru p. Niemniej można
zastosować nierówność, że dla 0 ≤ p ≤ 1 zachodzi p(1 − p) ≤
1
.
4
Przy podstawieniu
wyznaczonych wartości przedział ufności wynosi [p̂ − 0, 001386; p̂ + 0, 001386]. Niemniej
oszacowanie to jest zawyżone w przypadku, gdy wartość parametru p jest z zakresu 0 ≤ p ≤
6
Znacznik ten składa si˛e ma nast˛epujacy
˛
format:
„[znacznik czasowy wystapienia
˛
komunikatu]”. Przykład komunikatów opatrzonych takim zancznikiem znajduje si˛e na listingu 4.3 w
liniach 2-34.
7
Znak konsoli operatora informujacy
˛ o gotowości przyj˛ecia kolejnej komendy.
76
0,0020
0,0010
●
●
●
●
●●
●●
●●●
●●●●
●●●●●●
● ●● ●● ●● ●● ●●
●● ●● ●●● ●●● ●●● ●●● ●
0
Zakres przedzialu 95% ufnosci
●
50000
150000
250000
350000
450000
Liczba testów
Rysunek 4.1: Bład
˛ wzgl˛edny w zależności od liczby testów w eksperymencie
0, 01, gdyż wtedy zachodzi nierówność p(1 − p) ≤ 0, 0099, co z kolei pozwala wyznaczyć
zakres ufności na [p̂ − 0, 000276; p̂ + 0, 000276].
Z uwagi na długi czas przeprowadzania eksperymentu przygotowana została analiza majaca
˛
na celu określenie z ilu testów może składać si˛e eksperyment, aby zachować zbliżony poziom
manifestacji bł˛edów jednocześnie minimalizujac
˛ czas potrzebny do przeprowadzenia testów.
Na rysunku 4.1 przedstawiony jest wykres rozpi˛etości zakresu przedziału ufności w przy
założeniu p̂ = 0, 0058 (wartość ta została wybrana jako najdokładniejszy dost˛epny pomiar
współczynnika manifestacji bł˛edów) dla różnej liczby testów (N ) według wzoru 4.2.1. Na
podstawie wykresu wybrana została liczba 50 000 testów w eksperymencie z uwagi na
akceptowalny czas przeprowadzenia takiego eksperymentu (około 3 dni) oraz zakres przedziału
ufności 95% na poziomie p̂ ± 0, 00066 (0,066 p.p.).
W dalszej cz˛eści niniejszego podrozdziału wyniki przeprowadzonego eksperymentu
500 000 testów zostały przedstawione jako 10 iteracji eksperymentu składajacego
˛
si˛e 50 000
testów w celu zobrazowania różnic pomi˛edzy kolejnymi próbkami. Dodatkowo liczba 50 000
testów w eksperymencie została przyj˛eta w testach opisanych w podrozdziałach 4.3 oraz 4.4,
co umożliwia porównywanie uzyskanych wyników.
Wyniki przedstawiajace
˛ odsetek wstrzykni˛etych bł˛edów, które zostały zamanifestowane
(współczynnik Fs ) w poszczególnych iteracjach eksperymentu, zostały zamieszczone na
rysunku 4.2.
Kolorem zielonym zaznaczono odsetek testów, w których wynik zadania
realizowanego w scenariuszu był prawidłowy, natomiast kolorem czerwonym odsetek testów
zakończonych nieprawidłowym wynikiem zadania – według kategorii manifestacji bł˛edu
77
0.8
0.6
0.4
0.0
0.2
Testy %
PU + PS
NU + NS
1
2
3
4
5
6
7
8
9
10
Rysunek 4.2: Wartość współczynnika Fs dla różnych iteracji eksperymentu badanej
architektury sprz˛etowej
opisanej w 2.5.2 wartości te sa˛ wyrażone jako Ps + Pu i Ns + Nu .
Procentowy
udział poszczególnych kategorii manifestacji bł˛edu został przedstawiony na rysunku 4.3.
Przykłady typów manifestacji zostały przedstawione w dalszej cz˛eści niniejszego podrozdziału.
Dost˛epność systemu przy nieprawidłowym wyniku końcowym (dla kategorii manifestacji Nu
i Ns ) została przedstawiona na rysunku 4.4 z zastosowaniem kategorii dost˛epności systemu
opisanych w 2.5.2.
W przypadku testów, w których pojawiły si˛e komunikaty jadra
˛
systemu operacyjnego,
przeprowadzono analiz˛e typów bł˛edów zgodnie z metodyka˛ opisana˛ w 3.4.5. Zestawienie
procentowych udziałów różnych typów bł˛edów przedstawiono w tabeli 4.1.
Rysunek 4.5 przedstawia współczynnik manifestacji bł˛edów w pami˛eci fizycznej dla
obszarów pami˛eci wielkości 1 MB. Współczynnik ten wyrażony jest jako procent testów,
podczas których zamanifestowany został bład,
˛ w stosunku do wszystkich testów wstrzykni˛ecia
bł˛edu w dany obszar pami˛eci. Przykładowo dla iteracji 1 można odczytać, że w przedziale
adresów fizycznych od 0 do 1048576 (1 MB) 7% wstrzykni˛etych bł˛edów spowodowało
zamanifestowanie bł˛edu.
tbhp
Przykłady manifestacji bł˛edów
Poniżej przedstawione sa˛ zaobserwowane w dziennikach wykonania różne typy manifestacji
bł˛edów: Pu , Nu , Ns . Typ Ps został pomini˛ety, ponieważ różni si˛e on od Ns jedynie uzyskaniem
prawidłowego wyniku, pomimo pojawienia si˛e komunikatów systemu operacyjnego.
78
100
80
60
40
0
20
Testy %
PU
PS
NU
NS
1
2
3
4
5
6
7
8
9
10
60
40
DU
DS
NDU
NDS
0
20
Testy %
80
100
Rysunek 4.3: Rozkład typów zamanifestowanych bł˛edów w różnych iteracjach eksperymentu
badanej architektury sprz˛etowej
1
2
3
4
5
6
7
8
9
10
Rysunek 4.4: Dost˛epność systemu operacyjnego w różnych iteracjach eksperymentu badanej
architektury sprz˛etowej
79
10
5
Testy %
10
0
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
5
5
5
5
5
5
5
5
5
0
Testy %
1
10
0
Testy %
2
10
0
Testy %
3
10
0
Testy %
4
10
0
Testy %
5
10
0
Testy %
6
10
0
Testy %
7
10
0
Testy %
8
10
0
Testy %
9
10
4
MB
Rysunek 4.5: Współczynnik Fs / MB pami˛eci fizycznej dla różnych iteracji eksperymentu
badanej architektury sprz˛etowej
80
Komunikat [%]
1
2
3
4
5
6
7
Paging request failed 27,12 24,86 23,84 29,54 26,21 25,1 23,13
Segfault
21,02 23,74 24,15 21 20,71 25,1 19,93
Null dreference
10,85 14,53 12,07 11,39 13,27 14,12 12,81
Null dereference 0
6,44 4,47 4,33 3,56 4,53 7,45 4,63
Panic in interrupt
8,81 8,1 8,36 12,46 13,92 7,06 7,12
General protection
7,46 9,78 9,6 9,25 10,36 10,59 8,19
Bad PC value
3,73 5,03 8,05 3,2 7,77 3,53 7,83
Panic - kill init
3,39 3,35 3,1 4,27 2,91 1,96 4,27
Undefined instruction 2,03 3,63 6,5 6,76 8,41 4,31 6,76
Double fault
1,36 1,12 1,24 0,71 0,65 0,39 1,42
Bad page state
0,68 1,96 1,86 1,42 0,97 2,75 1,07
8
23,91
26,71
13,04
4,97
9,94
6,83
6,52
5,28
7,14
0,93
1,86
9
27,02
17,19
12,28
7,02
9,82
9,82
7,37
3,51
7,37
3,86
3,16
10
28,3
22,64
13,21
5,35
8,81
8,49
5,35
3,77
5,03
2,2
2,83
Tabela 4.1: Udział komunikatów zgłaszanych przez system operacyjny w różnych iteracjach
eksperymentu
1
2
3
4
debian-i386:~# wget --progress=dot 194.29.167.156:2000
--%s-- 2013-02-24 07:48:40
Connecting to 194.29.167.156:2000... connected.
HTTP request sent, awaiting response... 200 OK
Listing 4.1: Przykład Pu
Na listingu 4.1 przedstawiono zaobserwowana˛ manifestacj˛e bł˛edu polegajac
˛ a˛ na zmianie
komunikatów prezentowanych użytkownikowi, co nie miało wpływu na wykonanie przez
SUT powierzonego zadania (Pu ). Nieprawidłowości znajduja˛ si˛e w linii 2, gdzie wyst˛epuje
znacznik %s oraz data.
W eksperymentach, w których bład
˛ si˛e nie manifestuje linia
wypisywana na tym etapie wykonania scenariusza ma postać: „-2013-03-26 03:46:12http://194.29.167.156:2000/”, czyli wystapiły
˛
dwie zmiany:
— w miejscu wypisywania daty pojawił si˛e znacznik %s,
— w miejscu wypisywania docelowego adresu URL wypisana została data.
Obrazuje to jak bł˛edy wyst˛epujace
˛ w systemie moga˛ mieć pozornie nieszkodliwe efekty. W
tym przypadku wynik powierzonego zadania nie zależał od przekłamanej linii, jednak łatwo
wyobrazić sobie przypadek, gdy zmiana formatu wypisywanych danych może mieć negatywny
wpływ na inne programy korzystajace
˛ z tych danych.
1
2
debian-i386:~# rm tmp/index.html
rm: relocation error: rm: symbol sc0<vdcR+G9E0_e, version GLIBC_2.0 not
,→ defined in file libc.so.6 with link time reference
Listing 4.2: Przykład Nu
Listing 4.2 przedstawia manifestacj˛e typu Nu , która powoduje niewykryta˛ przez system
sytuacj˛e awaryjna.˛ Wprowadzone zaburzenie spowodowało, że nie jest możliwe uruchomienie
81
żadnego programu wykorzystujacego
˛
standardowa˛ bibliotek˛e j˛ezyka C (libc), ponieważ
uszkodzenie zaburzyło proces ładowania tej biblioteki współdzielonej (patrz 2.1.2). Awaria tego
typu powoduje brak możliwości uruchomienia jakiegokolwiek nowego procesu w systemie.
Listing 4.3 przedstawia manifestacj˛e typu Ns , w której jadro
˛ systemu operacyjnego zgłosiło
sytuacj˛e awaryjna.˛ Jest to typowy dla systemu GNU/Linux komunikat, w którym zawarte sa˛
mi˛edzy innymi nast˛epujace
˛ informacje:
— opis typu awarii (linia 2),
— identyfikator procesora, który wykonywał zadanie ulegajace
˛ awarii (linia 5),
— lista modułów załadowanych do jadra
˛ systemu operacyjnego (linia 6),
— identyfikator procesu ulegajacego
˛
awarii i informacja o wersji jadra
˛ systemu operacyjnego
(linia 8),
— zawartości rejestrów procesora (linie 9-13),
— informacje o procesie/watku
˛ systemu, na rzecz którego wykonywany był kod wywołujacy
˛
awari˛e (linia 14),
— zawartość stosu (linie 15-17),
— stos wywołań funkcji stack-trace (linie 19-30),
— zrzut pami˛eci zawierajacej
˛ instrukcje wykonywane przez procesor (linia 32).
Opis zgłaszanych komunikatów
Komunikaty najcz˛eściej zgłaszane przez system operacyjny wymienione w tabeli 4.1 maja˛
nast˛epujace
˛ znaczenie:
Paging request failed Próba odwołania si˛e przez kod wykonywany w przestrzeni jadra
˛
systemu operacyjnego do pami˛eci, która nie została wcześniej zaalokowana (patrz 2.1.2).
Segfault Jest to komunikat analogiczny do Paging request failed, z ta˛ różnica,˛ że program
wykonujacy
˛ nieprawidłowe odwołanie uruchomiony był w przestrzeni użytkownika (patrz
2.1.2).
Null dereference Próba dereferencji wskaźnika majacego
˛
wartość 0.
Null dereference 0 Komunikat ten jest analogiczny do komunikatu Null dereference, gdzie
sam wskaźnik również jest przechowywany pod adresem 0.
Panic in interrupt Wystapienie
˛
bł˛edu w trakcie wykonywania procedury obsługi przerwań
(patrz 2.1.2).
General protection Komunikat ten zgłaszany jest przy wszelkich naruszeniach zasad ochrony
zdefiniowanych w procesorze. Oprócz nieprawidłowego dost˛epu do pami˛eci (np. pisanie do
pami˛eci read-only, próba wykonania kodu ze strony nie majacej
˛ uprawnień wykonania) jest
to także próba wykonania instrukcji uprzywilejowanych.
Bad PC value Rejestr wskaźnika instrukcji ma niedozwolona˛ wartość (wykaz niedozwolonych
wartości można znaleźć w [56]).
82
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
debian-i386:~# wget --progress=dot 194.29.167.156:2000
[1471925.388302] BUG: unable to handle kernel NULL pointer dereference at
,→ 00000282
[1471925.394970] IP: [<c227b080>]
[1471925.397151] *pde = 00000000
[1471925.399116] Oops: 0000 [#1] SMP
[1471925.400822] Modules linked in: loop button serio_raw parport_pc
,→ parport snd_pcsp psmouse snd_pcm snd_timer i2c_piix4 snd soundcore
,→ i2c_core snd_page_alloc evdev ext3 jbd mbcache ata_generic
,→ ide_cd_mod cdrom ide_disk libata scsi_mod dock ide_pci_generic piix
,→ ide_core e1000 floppy thermal processor fan thermal_sys
[1471925.400822]
[1471925.400822] Pid: 2028, comm: bash Not tainted (2.6.26-2-686 #1)
[1471925.400822] EIP: 0060:[<c227b080>] EFLAGS: 00000282 CPU: 0
[1471925.400822] EIP is at 0xc227b080
[1471925.400822] EAX: 00000282 EBX: c0117357 ECX: 0000000a EDX: 00000002
[1471925.400822] ESI: c1046a40 EDI: b7000000 EBP: c1065580 ESP: c21e3e1c
[1471925.400822] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
[1471925.400822] Process bash (pid: 2028, ti=c21e2000 task=c24584a0
,→ task.ti=c21e2000)
[1471925.400822] Stack: 08000000 c0163c45 00046a40 c1000000 00000000
,→ 08356000 c21e3ea4 08356000
[1471925.400822]
00000000 00000001 bfae4000 c227bbf8 c2dc6b74
,→ c2dc6b5c 08355fff c18416fc
[1471925.400822]
c18416fc c18416fc 08048000 c0164bc3 00000000
,→ b73e3000 00000000 c21e3ea4
[1471925.400822] Call Trace:
[1471925.400822] [<c0163c45>] free_pgd_range+0x15e/0x174
[1471925.400822] [<c0164bc3>] free_pgtables+0x86/0x93
[1471925.400822] [<c0165b9a>] exit_mmap+0x7f/0xd3
[1471925.400822] [<c012078e>] mmput+0x20/0x7e
[1471925.400822] [<c0178751>] flush_old_exec+0x3e3/0x495
[1471925.400822] [<c019b55c>] load_elf_binary+0x310/0x1082
[1471925.400822] [<c016471c>] get_user_pages+0x2a0/0x334
[1471925.400822] [<c0177b3e>] copy_strings+0x169/0x173
[1471925.400822] [<c0177c03>] search_binary_handler+0x8f/0x1a4
[1471925.400822] [<c0178d58>] do_execve+0x138/0x1c6
[1471925.400822] [<c010213b>] sys_execve+0x2a/0x4a
[1471925.400822] [<c0103857>] sysenter_past_esp+0x78/0xb1
[1471925.400822] =======================
[1471925.400822] Code: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
,→ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
,→ 00 00 00 <00> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
,→ 00 00
[1471925.400822] EIP: [<c227b080>] 0xc227b080 SS:ESP 0068:c21e3e1c
[1471925.472978] ---[ end trace 1cb41acd1be81ded ]---
Listing 4.3: Przykład Ns
83
Panic - kill init Bł˛edy, które wystapiły
˛
spowodowały zakończenie procesu init – tj. przodka
wszystkich procesów uruchomionych w systemie operacyjnym (patrz 2.1.2).
Undefined instruction Próba wykonania instrukcji, która nie jest prawidłowa˛ instrukcja˛
zdefiniowana˛ w ISA.
Double fault Wystapienie
˛
bł˛edu podwójnego, czyli zgłoszenie bł˛edu przez procesor w trakcie
wykonania procedury obsługi innego bł˛edu.
Bad page state Wykryto bład
˛ w strukturach danych odpowiedzialnych za zarzadzanie
˛
stronami
pami˛eci wirtualnej (patrz 2.1.2).
Wnioski
Z analizy rysunku 4.3 wynika, że około 10-15% testów z zamanifestowanymi bł˛edami
zakończyło si˛e uzyskaniem poprawnego wyniku (Ps + Pu ), a system operacyjny wykrywa
obecność bł˛edu w około 75% przypadków (Ps + Ns ). Warto również zauważyć, że spośród
testów zakończonych nieprawidłowym wynikiem (dost˛epność systemu przy nieprawidłowym
wyniku przedstawiona jest na rysunku 4.4) ponad 60% cechuje brak dost˛epności systemu
(N DU + N DS ), co uniemożliwia dalsza˛ interakcj˛e z systemem w celach diagnostycznych.
Dodatkowo analiza tabeli 4.1 pozwala stwierdzić, że najcz˛eściej zgłaszane komunikaty przez
system sa˛ zwiazane
˛
z bł˛edami pami˛eci (komunikaty Segfault, Paging request failed, Null
dereference oraz Null dereference 0).
Analiza zakresów adresów fizycznych, które powoduja˛ manifestacj˛e bł˛edów (rysunek 4.5),
wskazuje wyraźnie, że niektóre obszary sa˛ kilkakrotnie bardziej podatne na wystapienie
˛
bł˛edu.
Oznacza to, że różne rodzaje danych składowanych w pami˛eci (kod, stos, przetwarzane dane)
maja˛ inny stopień podatności na bł˛edy. Jest to cenna obserwacja, ponieważ uzupełniona o
informacj˛e jakiego typu dane były składowane w tych obszarach pami˛eci stanowi wskazówk˛e
dla projektantów systemów komputerowych o podwyższonej odporności na bł˛edy. Dzi˛eki
tej wiedzy, można obniżyć koszty produkcji systemu umieszczajac
˛ tylko dane pewnego
rodzaju w droższej pami˛eci RAM wyposażonej w system ECC. Niemniej zastosowanie takiego
rozwiazania
˛
wymaga wsparcia systemu operacyjnego.
Długi czas pojedynczego eksperymentu jest wada˛ obecnej implementacji.
Niemniej
możliwe jest w przyszłości przyśpieszenie testu poprzez wykorzystanie opcji migawki
stanu emulatora.
Rozwiazanie
˛
takie polega na przygotowaniu migawki systemu przed
wstrzykni˛eciem bł˛edu i uruchamianie kolejnych instancji eksperymentu z wykorzystaniem tych
danych – pozwoliłoby to na wyeliminowanie z eksperymentu czasu potrzebnego na rozruch
emulowanego systemu operacyjnego, czyli czas potrzebny na przeprowadzenie pojedynczego
testu potencjalnie może być zredukowany z 4 do 2 minut.
Wybrana metoda wstrzykiwania bł˛edów bezpośrednio w pami˛eć fizyczna˛ cechuje si˛e
niskim poziomem manifestacji bł˛edów. Dodatkowym problemem wynikajacym
˛
ze sposobu
implementacji QEMU sa˛ trudności w sprawdzeniu, czy dane spod zaburzonego adresu
84
fizycznego zostały aktywowane, co pozwoliłoby na wyznaczenie współczynnika naturalnej
odporności I zgodnie z definicja˛ przedstawiona˛ w sekcji 2.5.2. Rozwiazanie
˛
tych problemów
wia˛że si˛e z wykonaniem dodatkowych prac specyficznych dla konkretnej architektury
emulowanego systemu – prace te zostały wykonane i ich wyniki opisano w sekcji 4.5.3.
4.3. Porównanie wrażliwości na bł˛edy różnych architektur sprz˛etowych
Projektowanie systemów komputerowych o zwi˛ekszonej odporności na bł˛edy z
zastosowaniem elementów COTS wymaga metodyki oceny wybranych elementów systemu.
Podstawowym komponentem systemu komputerowego jest procesor.
Wszelkie dane
pozwalajace
˛ porównać jednostki przetwarzajace
˛ stanowia˛ cenny wkład przy wyborze najlepszej
architektury. W literaturze można znaleźć niewiele opracowań zawierajacych
˛
takie porównania.
Według autora najciekawsze eksperymenty można znaleźć w [48] oraz [21], gdzie autorzy
opracowali system wstrzykiwania bł˛edów w przestrzeń systemu operacyjnego przy użyciu
ładowanego modułu. Taka konfiguracja wstrzykiwania bł˛edów wymaga jednak osobnych
maszyn do przeprowadzania eksperymentów i zbierania wyników. Powoduje to problemy przy
skalowaniu środowiska testowego, przez co autorzy w [48] porównali zaledwie dwie platformy
sprz˛etowe pracujace
˛ pod kontrola˛ tej samej wersji systemu operacyjnego opartego o jadro
˛
GNU/Linux. W przypadku [21] porównane sa˛ różne systemy operacyjne, jednak wszystkie
uruchomione na różnych platformach sprz˛etowych. Utrudnia to wnioskowanie o cechach
niezawodności samych systemów operacyjnych lub poszczególnych architektur, a dodatkowo
wymaga przygotowania ładowanych modułów wstrzykujacych
˛
osobno dla każdego systemu
operacyjnego.
Zastosowanie QEFI umożliwia badanie czy poszczególne ISA naturalnie sprzyjaja˛
wi˛ekszej niezawodności w obliczu bł˛edów pami˛eci RAM ograniczajac
˛ trudności, które
dotycza˛ metodyk opisanych w [48] i [21].
Zastosowanie emulacji pozwoliło na
przeprowadzenie eksperymentów bez wykorzystania rzeczywistych urzadzeń
˛
(dzi˛eki czemu
przetestowano wi˛eksza˛ liczb˛e architektur), a także wyeliminowało konieczność opracowywania
dedykowanego oprogramowania wstrzykiwania bł˛edów na każda˛ z architektur.
W niniejszym podrozdziale opisany jest eksperyment, którego celem było porównanie
zachowania różnych architektur sprz˛etowych w obliczu pojedynczego bł˛edu typu bit-flip w
pami˛eci RAM.
Konfiguracja eksperymentu
Badaniom poddane zostały nast˛epujace
˛ architektury: AMD64, ARM, MIPS, PowerPC oraz
x86. W celu zminimalizowania różnic wynikajacych
˛
z oprogramowania uruchomionego na
emulowanych systemach, wszystkie konfiguracje działały pod kontrola˛ systemu operacyjnego
Debian Lenny z jadrem
˛
GNU/Linux w wersji 2.6.26. Obrazy dysków twardych z instalacjami
85
systemu operacyjnego dla różnych architektur zostały pobrane ze stron projektu Debian8 .
Wszystkie instalacje zawieraja˛ oprogramowanie w tych samych wersjach i sa˛ w stanie, który
jest osiagni˛
˛ ety zaraz po zakończeniu procesu instalacji systemu operacyjnego. Dzi˛eki spójnym
wersjom oprogramowania scenariusz testowy jest identyczny ze scenariuszem przedstawionym
w podrozdziale 4.2.
Dla każdej architektury przeprowadzono eksperyment składajacy
˛ si˛e z 50 000 testów
– uzasadnienie takiej liczby testów zostało przedstawione w podrozdziale 4.2. Wyjatkiem
˛
jest architektura x86, która jest zbiorczym wynikiem 500 000 testów otrzymanych przy
opracowywaniu eksperymentów z podrozdziału 4.2, z uwagi na fakt, iż jest to najdokładniejszy
pomiar.
Wyniki
Sposób analizy dzienników wykonania jest taki sam jak dla eksperymentu opisanego w
podrozdziale 4.2. Na rysunku 4.6 przedstawiony jest współczynnik manifestacji bł˛edu (Fs )
dla każdej z architektur.
Procentowy udział poszczególnych kategorii manifestacji bł˛edu
został przedstawiony na rysunku 4.7.
Dost˛epność systemu dla testów, w których wynik
przeprowadzenia scenariusza był nieprawidłowy zobrazowano na rysunku 4.8. Rysunek 4.9
przedstawia współczynnik manifestacji bł˛edów w pami˛eci fizycznej dla obszarów pami˛eci
wielkości 1 MB. Tabela 4.2 zawiera rozkład typów komunikatów jadra
˛ systemu operacyjnego.
Opis zgłaszanych komunikatów
Cz˛eść komunikatów najcz˛eściej zgłaszanych przez system operacyjny została opisana w
podrozdziale 4.2 na stronie 82.
Poniżej znajduje si˛e opis pozostałych komunikatów,
uwzgl˛ednionych w zestawieniu:
Unaligned access Komunikat ten jest zgłaszany na architekturze MIPS i oznacza prób˛e
odczytania instrukcji spod niewyrównanego adresu.
Reserved instruction Próba wykonania instrukcji zarezerwowanej dla trybu jadra
˛
systemu
operacyjnego w trybie użytkownika.
Kernel bug detected Jest to komunikat oznaczajacy
˛ wystapienie
˛
bł˛edu podczas wykonywania
kodu o nieokreślonym typie9 w przestrzeni jadra
˛ dla architektury MIPS.
Exception in kernel mode Jest analogicznym komunikatem do Kernel bug detected dla
architektury PowerPC.
Sched while atomic Wywołanie planera zadań w trakcie wykonania sekcji krytycznej.
EXT FS error Komunikat bł˛edu systemu plików EXT3.
I/O error Komunikat bł˛edu zwiazanego
˛
z operacjami wejścia/wyjścia.
8
http://people.debian.org/˜aurel32/qemu/
Analiza kodu źródłowego systemu GNU/Linux dla architektury MIPS wykazała, że tylko cz˛eść bł˛edów ma
zdefiniowane komunikaty (np. Paging request failed). Jeżeli bład
˛ nie ma dedykowanego komunikatu zgłaszany
jest komunikat Kernel bug detected.
9
86
0.8
0.6
0.4
0.0
0.2
Testy %
PU + PS
NU + NS
AMD64
PowerPC
MIPS
ARM
x86
60
40
PU
PS
NU
NS
0
20
Testy %
80
100
Rysunek 4.6: Wartość współczynnika Fs dla różnych architektur
AMD64
PowerPC
MIPS
ARM
x86
Rysunek 4.7: Rozkład typów zamanifestowanych bł˛edów na różnych architekturach
87
100
80
60
0
20
40
Testy %
DU
DS
NDU
NDS
AMD64
PowerPC
MIPS
ARM
x86
5
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
5
10
4
10
5
10
5
0
5
10
0
Testy %
Testy %
AMD64
PowerPC
0
Testy %
MIPS
0
Testy %
ARM
0
Testy %
x86
10
Rysunek 4.8: Dost˛epność systemu operacyjnego na różnych architekturach
MB
Rysunek 4.9: Współczynnik Fs / MB pami˛eci fizycznej dla różnych architektur
88
Komunikat %
Bad page state
Bad PC value
Null dereference
Null dereference 0
Paging request failed
Sched while atomic
Double fault
Exception in kernel mode
EXT FS error
General protection
I/O error
Kernel bug detected
Page allocation failure
Panic in interrupt
Panic - kill init
Reserverd instruction
Segfault
Unaligned access
Undefined instruction
Unclassified
Tabela 4.2:
sprz˛etowych
AMD64
2,63
0
14,8
5,26
27,63
0,33
1,32
0
0
26,32
0
0
0
0
5,92
0
19,41
0
11,51
2,63
PowerPC
3,61
0
0
0
53,01
2,41
0
37,95
0
0
0
0
0,6
21,08
11,45
0
0
0
0
6,02
MIPS
4,11
0
0
0
49,32
0
0
0
0
0
0
10,96
0
20,55
8,9
17,81
0
19,86
0
7,53
ARM
2,22
0
30,37
21,48
45,93
0,74
0
0
0
0
0
0
0,74
12,59
13,33
0
0
0
12,59
1,48
x86
2,43
7,74
16,83
6,87
34,04
0,3
1,83
0
0,43
11,87
0,17
0
0
12,43
4,74
0
29,35
0
7,61
1,39
Komunikaty systemu operacyjnego zgłaszane na rożnych architekturach
Page allocation failure Kounikat
wyst˛epujacy
˛
na
architekturach
ARM
i
PowerPC,
oznaczajacy
˛ wyczerpanie dost˛epnej pami˛eci operacyjnej.
Komunikaty systemu operacyjnego, które nie zostały przypisane do żadnej z wymienionych
kategori zgrupowane jako komunikaty typu „Unclassified”.
Wnioski
Zastosowanie emulatora systemu komputerowego pozwoliło na porównanie podatności na
bł˛edy kilku architektur sprz˛etowych bez konieczności posiadania fizycznych urzadzeń.
˛
Dodatkowo wstrzykiwanie bł˛edu na poziomie emulatora znacznie upraszcza proces konfiguracji
eksperymentu w porównaniu do zastosowania wstrzykiwania bł˛edu z użyciem ładowanych
modułów systemu operacyjnego, które wymagaja˛ osobnej kompilacji na każda˛ z docelowych
platform (podejście takie zastosowano w [48], gdzie porównano tylko dwie platformy: x86 i
PowerPC).
Platforma, która osiagn˛
˛ eła najwi˛ekszy współczynnik manifestacji bł˛edu to AMD64 (na
podstawie rysunku 4.6). Zachowanie takie może wynikać z faktu, że AMD64 jest jedyna˛
platforma˛ w zestawieniu, która działa na 64 bitowych adresach pami˛eci. Cecha ta wpływa na
zwi˛ekszenie wykorzystywanej pami˛eci. Zostało to potwierdzone poprzez zebranie informacji o
ilości wolnej pami˛eci w każdym z emulowanych systemów komputerowych. Po uruchomieniu
89
systemu operacyjnego na systemie opartym o architektur˛e AMD64 było dost˛epnych wyłacznie
˛
10 MB dost˛epnej pami˛eci, podczas gdy na pozostałych systemach było to około 20MB.
Interesujac
˛ a˛ obserwacja˛ jest brak korelacji mi˛edzy manifestacja˛ bł˛edów architektur CISC
(x86 i AMD64) i RISC (PowerPC, MIPS, ARM). O ile różnica w odsetku manifestacji bł˛edów
platform CISC może być wyjaśniona rozmiarami wykorzystywanych adresów pami˛eci, to
w przypadku pozostałych architektur trudno jest stwierdzić jednoznacznie przyczyn˛e różnic
i wymagałoby to dalszych badań. Niemniej przeprowadzone testy potwierdzaja˛ tendencj˛e
wi˛ekszego odsetku manifestacji bł˛edów na platformie PowerPC wzgl˛edem platformy x86, co
zostało opisane również w [48].
Niezależnie od architektury, dla testów zakończonych nieprawidłowym wynikiem, w około
50% przypadków system staje si˛e niedost˛epny (rysunek 4.8).
Zebrane dane dowodza,˛ że na wszystkich emulowanych systemach pojawienie si˛e bł˛edu
typu bit-flip, jeżeli jest zamanifestowany, w 85-90% przypadków skutkuje nieprawidłowym
wykonaniem powierzonego zadania. Dodatkowo istotna˛ informacja˛ jest to, że jadro
˛
systemu
operacyjnego wykrywa bład
˛ w znacznym stopniu (Ps + Ns z rysunku 4.7). Na platformach
z rodziny RISC jest to około 45% zamanifestowanych bł˛edów, natomiast na platformach x86 i
AMD64 odpowiednio 65% i 75%. Jest to przesłanka do tego, aby podjać
˛ badania skupiajace
˛ si˛e
na diagnozowaniu przyczyny awarii przez system operacyjny i podj˛eciu działań naprawczych o
ile jest to możliwe. Dodatkowa˛ wskazówk˛e dotyczac
˛ a˛ kierunku dalszych badań niesie analiza
tabeli 4.2, gdzie na wszystkich platformach komunikat Paging request failed jest najcz˛eściej
zgłaszany przez system operacyjny.
Przeprowadzone badanie podatności różnych architektur systemów operacyjnych dostarcza
interesujacych
˛
danych uzupełniajac
˛ stan wiedzy, jednak istotna˛ kwestia˛ jest niski współczynnik
eksperymentów, które zakończyły si˛e manifestacja˛ bł˛edu. Jest to ucia˛żliwe ze wzgl˛edu na
uruchamianie wielu eksperymentów, które nie przynosza˛ żadnych wartościowych wyników.
Rozwiazaniem
˛
jest tworzenie eksperymentów sprofilowanych na różne cz˛eści systemu
operacyjnego.
Dzi˛eki takiemu podejściu oprócz zwi˛ekszenia poziomu manifestacji bł˛edu
możliwe jest wyznaczenie lokalizacji w pami˛eci fizycznej poszczególnych cz˛eści systemu
operacyjnego. Badania przeprowadzone zgodnie z tymi wytycznymi zostały opisane w sekcjach
4.5.2 i 4.5.3.
4.4. Porównanie wrażliwości różnych systemów operacyjnych
W [21] można znaleźć porównanie wrażliwości na bł˛edy różnych systemów operacyjnych,
ale nie jest ono w pełni satysfakcjonujace,
˛ ponieważ systemy operacyjne były uruchamiane
na różnych architekturach sprz˛etowych.
W eksperymencie opisanym poniżej zestawiono
wyniki zaburzania pami˛eci systemów działajacych
˛
pod kontrola:
˛ GNU/Linux, kFreeBSD oraz
90
Minix działajacych
˛
na jednej architekturze sprz˛etowej. Dzi˛eki temu zbadano, czy systemy
wykorzystujace
˛ mikrojadro
˛
lub jadro
˛
monolityczne (patrz 2.1.2), badź
˛ różne implementacje
systemów operacyjnych opartych o jadro
˛ monolityczne różnia˛ si˛e pod wzgl˛edem podatności na
bł˛edy.
Konfiguracja eksperymentu
Badaniom zostały poddane nast˛epujace
˛ systemy operacyjne: Debian Lenny oparty o jadro
˛
GNU/Linux w wersji 2.6.26, Debian Squeeze oparty o jadro
˛ kFreeBSD w wersji 7.2 oraz Minix
w wersji 3.2. Obraz systemu opartego o jadro
˛
kFreeBSD został pobrany ze stron projektu
Debian10 , natomiast stworzenie obrazu systemu Minix wymagało przeprowadzenia procesu
instalacji systemu w nowo utworzonej instancji emulowanego systemu komputerowego. Wybór
tych systemów operacyjnych jest uzasadniony nast˛epujacymi
˛
czynnikami:
— wszystkie systemy działaja˛ na architekturze x86,
— zestawienie systemów GNU/Linux oraz kFreeBSD pozwoli porównać podatność na bł˛edy
różnych implementacji systemów opartych o architektur˛e jadra
˛
monolitycznego (patrz
2.1.2),
— właczenie
˛
do zestawienia systemu Minix opartego o architektur˛e mikrojadra
˛
pozwoli
porównać jego podatność na bł˛edy wzgl˛edem systemów opartych o architektur˛e jadra
˛
monolitycznego.
Scenariusz
testu
w
ramach
eksperymentu
jest
identyczny
ze
scenariuszem
przeprowadzonym w eksperymencie opisanym w podrozdziale 4.2 z wyjatkiem
˛
systemu
Minix, gdzie zamiast programu wget został użyty program curl o podobnym działaniu.
Było to spowodowane brakiem kompilacji programu wget dla systemu Minix. Znaczacym
˛
utrudnieniem jest fakt, że system Minix jest systemem ciagle
˛ rozwijanym i nie było możliwe
skonfigurowanie testowanej wersji systemu tak, aby komunikaty jadra
˛
systemu operacyjnego
były wypisywane na konsol˛e operatora dost˛epna˛ przez port szeregowy. Powoduje to, że
niemożliwe było wyznaczenie procentowego udziału bł˛edów, które zamanifestowały si˛e
komunikatami jadra
˛
systemu operacyjnego dla tego systemu, niemniej jednak możliwe jest
zebranie informacji o rezultacie wykonywanego zadania oraz dost˛epności systemu.
Konfiguracja typu bł˛edu, momentu wstrzykni˛ecia bł˛edu oraz rozmiaru pami˛eci RAM jest
identyczna z eksperymentem przeprowadzonym dla różnych architektur sprz˛etowych (patrz
4.3). Dzi˛eki temu wyniki dla systemu operacyjnego Debian Lenny opartego na GNU/Linux sa˛
rezultatami uzyskanymi w eksperymencie opisanym w podrozdziale 4.2. Tak jak w przypadku
porównania różnych architektur sprz˛etowych przeprowadzono 50 000 testów w pojedynczym
eksperymencie.
10
http://people.debian.org/˜aurel32/qemu/kfreebsd-i386
91
0.8
0.6
0.4
0.0
0.2
Testy %
PU + PS
NU + NS
kFreeBSD
GNU/Linux
Minix
Rysunek 4.10: Wartość współczynnika Fs dla różnych systemów operacyjnych
Wyniki
Wyniki przedstawiajace
˛ odsetek eksperymentów zakończonych zamanifestowaniem bł˛edu
(współczynnik Fs ) zostały zamieszczone na rysunku 4.10.
Klasyfikacja wyników
procentowych udziałów typu manifestacji bł˛edu według klasyfikacji opisanej w 2.5.2 jest
przedstawiona na rysunku 4.11.
Dost˛epność systemu dla testów, w których wynik
przeprowadzenia scenariusza był nieprawidłowy zobrazowano na rysunku 4.12. Rysunek 4.13
przedstawia współczynnik manifestacji bł˛edów w pami˛eci fizycznej dla obszarów pami˛eci
wielkości 1 MB. Natomiast tabela 4.3 zawiera rozkład najcz˛eściej zgłaszanych komunikatów
systemu operacyjnego.
Wnioski
Wstrzykiwanie bł˛edów w oparciu o emulator systemu komputerowego pozwoliło na równie
łatwe porównanie systemów operacyjnych jak w przypadku architektur komputerowych. Nie
było konieczne tworzenie osobnych mechanizmów wstrzykiwania bł˛edu dla każdej platformy.
Zestawienie procentowe zamanifestowanych bł˛edów (rysunek 4.10) wyraźnie pokazuje
dwie tendencje: zarówno implementacja, jak i architektura mikrojadra/j
˛
adra
˛
monolitycznego
systemu operacyjnego maja˛ wpływ na stopień wrażliwości na wstrzykni˛ete bł˛edy. System
oparty o jadro
˛
kFreeBSD nie tylko cz˛eściej manifestował bł˛edy, ale też wynik końcowy
rzadziej był prawidłowy (tylko 5% wyników w porównaniu z 12% dla GNU/Linux) i system
w wi˛ekszej liczbie przypadków stawał si˛e niedost˛epny (rysunki 4.11, 4.12). Zdecydowanie
wyróżnia si˛e system Minix, któremu najcz˛eściej udało si˛e wykonać powierzone zadanie.
92
100
80
60
40
0
20
Testy %
PU
PS
NU
NS
kFreeBSD
GNU/Linux
Minix
60
20
40
DU
DS
NDU
NDS
0
Testy %
80
100
Rysunek 4.11: Rozkład typów zamanifestowanych bł˛edów w systemach operacyjnych
kFreeBSD
GNU/Linux
Minix
Rysunek 4.12: Dost˛epność systemów operacyjnych
93
10
5
0
Testy %
Minix
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
4
8
12
16
20
24
28
32
36
40
44
5
10
8
0
5
10
0
Testy %
Testy %
kFreeBSD GNU/Linux
4
MB
Rysunek 4.13: Współczynnik Fs / MB pami˛eci fizycznej dla różnych systemów operacyjnych
Komunikat %
Bad page state
Bad PC value
Null dereference
Null dereference 0
Paging request failed
Sched while atomic
Double fault
EXT FS error
General protection
I/O error
Panic in interrupt
Panic - kill init
Privileged instruction
Segfault
Undefined instruction
Unclassified
kFreeBSD
0,84
0
0
0
79,83
0
4,2
0
2,52
0
0
0
2,52
0
0
10,08
GNU/Linux
2,43
7,74
16,83
6,87
34,04
0,3
1,83
0,43
11,87
0,17
12,43
4,74
0
29,35
7,61
1,39
Tabela 4.3: Komunikaty o bł˛edach zgłaszane przez systemy operacyjne
94
Prawdopodobnie wynika to z faktu, że system Minix jest projektowany pod katem
˛
zwi˛ekszonej
odporności na bł˛edy [52, 53, 54]. Wśród mechanizmów, które zwi˛ekszaja˛ tolerancj˛e na bł˛edy
jest zredukowany rozmiar kodu wykonywanego w przestrzeni jadra
˛
systemu operacyjnego, a
także koncepcja reinkarnacji usług systemu operacyjnego w przypadku awarii. Koncepcja ta
polega na ponownym uruchomieniu usług (np. obsługi stosu sieciowego), które uległy awarii,
w sposób przezroczysty dla użytkownika (maskowanie bł˛edów). Niestety sprawność tych
mechanizmów nie mogła zostać sprawdzona w opisanym eksperymencie z uwagi na trudności
ze skonfigurowaniem systemu Minix tak, aby komunikaty jadra
˛
systemu operacyjnego były
wypisywane na konsol˛e operatora podłaczon
˛
a˛ przez port szeregowy.
Analiza podatności zakresów pami˛eci fizycznej (rysunek 4.13) pozwala stwierdzić, że
każdy z systemów ma inna˛ charakterystyk˛e podatności na bł˛edy.
Systemy GNU/Linux
oraz kFreeBSD maja˛ zbliżone charakterystyki, jednak kFreeBSD wykazuje znacznie wi˛eksza˛
podatność w niskich adresach pami˛eci fizycznej. Natomiast w przypadku Minix nie wyst˛epuja˛
rejony o znacznie podwyższonej podatności, przy czym należy podkreślić, że dla tego
systemu przedstawione sa˛ wyłacznie
˛
wyniki dotyczace
˛ testów zakończonych nieprawidłowym
wynikiem z uwagi na trudności w konfiguracji systemu Minix do wydruku komunikatów
systemu komputerowego przez konsol˛e dost˛epna˛ przez port szeregowy.
Interesujace
˛ jest zróżnicowanie komunikatów zgłaszanych przez GNU/Linux w porównaniu
do kFreeBSD, gdzie wi˛ekszość wstrzykni˛eć bł˛edów manifestuje si˛e jako Paging request failed.
Świadczy to o lepszej jakości oprogramowania GNU/Linux. Komunikaty te stanowia˛ cenna˛
wskazówk˛e przy diagnozowaniu awrii systemu i podejmowaniu procedur naprawczych.
Pomimo dobrych wyników systemu Minix warto zaznaczyć, że system ten jest
systemem eksperymentalnym. Świadcza˛ o tym problemy konfiguracyjne oraz niedost˛epność
oprogramowania. GNU/Linux jest dojrzałym systemem używanym produkcyjnie i wszelkie
rozwiazania
˛
zwi˛ekszajace
˛ jego niezawodność moga˛ mieć szerokie grono odbiorców oraz
poszerzyć zastosowania tego systemu o dziedziny wymagajace
˛ zwi˛ekszonej niezawodności.
4.5. Eksperymenty ukierunkowane na jadro
˛
systemu operacyjnego
W poprzednich podrozdziałach zostały przedstawione eksperymenty porównujace
˛
zachowanie różnych systemów operacyjnych oraz wybranego systemu operacyjnego w
wersjach na różne platformy sprz˛etowe. Eksperymenty te pozwalaja˛ obserwować ogólne cechy
tych konfiguracji, jednak istnieje potrzeba gł˛ebszej analizy w celu identyfikacji krytycznych
komponentów. Wyznaczenie składowych, które sa˛ szczególnie podatne na bł˛edy, jest kluczowa˛
informacja˛ przy projektowaniu rozwiazań
˛
zapobiegajacych
˛
awariom.
W niniejszym podrozdziale przedstawione sa˛ eksperymenty ukierunkowane na badanie
niezawodności poszczególnych komponentów systemu operacyjnego. Zbadany został wpływ
95
bł˛ednie działajacych
˛
urzadzeń
˛
oraz bł˛edów pami˛eci w zależności od danych, które zostały
zaburzone. Uzyskane wyniki skonfrontowano z wynikami eksperymentów przeprowadzonych
innymi metodami, których opis można znaleźć w literaturze.
4.5.1. Bł˛edy urzadze
˛ ń wejścia/wyjścia
Tworzenie oprogramowania obsługujacego
˛
urzadzenia
˛
wejścia/wyjścia jest zadaniem
bardzo wymagajacym.
˛
Programiści najcz˛eściej dysponuja˛ ograniczonymi możliwościami
śledzenia wykonania kodu i wiele scenariuszy testowych jest przygotowywanych w oparciu
o specyfikacj˛e.
W celu zbadania możliwości jakie daje użycie emulatora systemu komputerowego
przy badaniu niezawodności oprogramowania sterowników urzadzeń
˛
wejścia/wyjścia
przeprowadzono trzy eksperymenty. Obejmowały one przekłamania typu bit-flip w danych
przekazywanych od urzadzenia
˛
do systemu operacyjnego.
Zbadane zostały nast˛epujace
˛
przypadki:
— wstrzykni˛ecie w dane pobrane z pami˛eci typu USB MSD11 ,
— wstrzykni˛ecie w zawartość rejestrów kontrolera USB typu UHCI12 udost˛epnionych
systemowi operacyjnemu,
— wstrzykni˛ecie w deskryptor odebranego pakietu interfejsu sieciowego karty e1000.
Scenariusze eksperymentów opartych o USB obrazuja˛ podatność na bł˛edy wyst˛epujace
˛
na dwóch warstwach współpracy urzadzenia
˛
wejścia/wyjścia z systemem operacyjnym. W
przypadku wstrzykni˛ecia bł˛edu w dane pobrane z pami˛eci USB MSD bład
˛ wyst˛epuje na
zewn˛etrznym urzadzeniu
˛
(np. popularne urzadzenie
˛
typu pendrive), natomiast zaburzanie
działania kontrolera USB jest symulacja˛ bł˛edu wyst˛epujacego
˛
w jednym z urzadzeń
˛
stanowiacych
˛
integralna˛ cz˛eść systemu komputerowego.
W przypadku badania interfejsu sieciowego podj˛eta została próba rozszerzenia
eksperymentów znanych z literatury polegajacych
˛
na zakłócaniu pakietów przychodzacych
˛
z sieci.
Przykładowy opis takiego eksperymentu przeprowadzonego w Instytucie
Informatyki Politechniki Warszawskiej można znaleźć w [38], gdzie przy użyciu mechanizmu
netfilter/iptables13 zintegrowanego z systemem operacyjnym wprowadzano zmiany w
zawartość pakietów.
Eksperyment przeprowadzony z użyciem QEFI pozwolił natomiast
zbadać protokół wymiany danych na poziomie interfejsu mi˛edzy urzadzeniem
˛
a systemem
operacyjnym, czyli symulowane było uszkodzenie urzadzenia,
˛
a nie kanału przesyłu tak jak
w przypadku eksperymentów znanych z literatury.
11
12
13
Ang. Mass Storage Device.
Ang. Universal Host Controller Interface.
http://www.netfilter.org
96
1
2
3
4
5
6
7
[QEFI] Uruchomienie SUT.
[ SUT] Zalogowanie si˛
e do systemu administratora przez konsol˛
e dost˛
epna˛
,→ przez port szeregowy.
[QEFI] Podłaczenie
˛
do SUT urzadzenia
˛
USB MSD.
[ SUT] Podłaczenie
˛
USB MSD w systemie operacyjnym SUT.
[QEFI] Konfiguracja opóźnionego wstrzykni˛
ecia bł˛
edu wyzwalanego
,→ prawdopodobieństwem.
[ SUT] Wyliczenie wartości funkcji skrótu md5 pliku znajdujacego
˛
si˛
e na
,→ urzadzeniu.
˛
[QEFI] Wyłaczenie
˛
SUT.
Scenariusz QEFI 4.2: Scenariusz testowania USB MSD
Konfiguracja eksperymentu
Wszystkie eksperymenty wykorzystywały system Debian Squeeze oparty o jadro
˛
GNU/Linux
w wersji 2.6.32.
Dla każdego scenariusza testowego przeprowadzonych zostało 10 000
testów – zgodnie z wzorem 4.2.1 dla tej liczby testów przedział ufności można oszacować na
±0, 0098 p.p., co przy znaczaco
˛ mniejszej przestrzeni zaburzanych danych pozwala skutecznie
porównywać uzyskane współczynniki manifestacji bł˛edów.
Scenariusz testowy dla eksperymentów urzadzenia
˛
USB MSD oraz kontrolera USB składa
si˛e z kroków przedstawionych w scenariuszu 4.2.
Eksperyment testujacy
˛ interfejs sieciowy był zbliżony do eksperymentów opisanych w
podrozdziale 4.3. Jedyna˛ różnica˛ wzgl˛edem Scenariusza QEFI 4.1 jest zmiana parametrów
wstrzykiwania bł˛edu, który był wyzwalany warunkowo z pewnym prawdopodobieństwem
(patrz 3.4.5).
Wyniki
Na rysunku 4.14 przedstawiony jest odsetek bł˛edów, które zostały zamanifestowane
(współczynnik Fs ) w każdym z eksperymentów. Rysunek 4.15 zawiera zestawienie typów
bł˛edów zgłoszonych przez system operacyjny, a szczegółowy wykaz komunikatów systemu
operacyjnego zamieszczony jest w tabeli 4.4. W tabeli pomini˛ety został wykaz komunikatów
systemu operacyjnego dla scenariusza USB MSD, ponieważ wystapił
˛
tylko jeden typ
komunikatu – Access beyond the device. Dost˛epność systemu dla testów, w których wynik
przeprowadzenia scenariusza był nieprawidłowy zobrazowano na rysunku 4.16.
Wnioski
Poziom manifestacji bł˛edów (rysunek 4.15) jest diametralnie różny dla każdego z
przedstawionych scenariuszy testowych. Najwi˛ecej przekłamań zostało zamanifestowanych w
scenariuszu USB MSD, ponieważ w zdecydowanej wi˛ekszości zaburzenia w odczytywanych
danych powodowały zmian˛e wartości funkcji skrótu md5 w kroku 6. scenariusza (99,2%
przypadków spośród zamanifestowanych bł˛edów). Interesujace
˛ jest również, że blisko 80%
97
100
80
60
40
0
20
Testy %
PU + PS
NU + NS
USB MSD
USB UHCI
e1000
60
40
PU
PS
NU
NS
0
20
Testy %
80
100
Rysunek 4.14: Wartość współczynnika Fs dla bł˛edów urzadzeń
˛
wejścia/wyjścia
USB MSD
Rysunek 4.15:
wejścia/wyjścia
USB UHCI
e1000
Rozkład typów zamanifestowanych bł˛edów dla bł˛edów urzadzeń
˛
98
100
80
60
40
0
20
Testy %
DU
DS
NDU
NDS
USB MSD
USB UHCI
e1000
Rysunek 4.16: Dost˛epność systemu operacyjnego przy bł˛edach urzadzeń
˛
wejścia/wyjścia
Komunikat %
Controller process error
EXT FS error
General protection
I/O error
Panic in interrupt
Undefined instruction
Reset USB device
USB UHCI
14,24
4,32
0
7,58
0
0
91,21
e1000
0
0
1,07
0
100
100
0
Tabela 4.4:
Komunikaty systemu operacyjnego zgłaszane przy bł˛edach urzadzeń
˛
wejścia/wyjścia
99
bł˛edów zgłoszonych w eksperymencie testujacym
˛
kontroler USB nie zamanifestowało si˛e
żadnym komunikatem systemu operacyjnego, a powodowały one zawieszenie si˛e emulowanego
systemu komputerowego (rysunek 4.16/N DS + N DU ). W przypadku komunikatów jadra
˛ dla
eksperymentu testujacego
˛
interfejs sieciowy komunikaty Panic in interrupt oraz Undefined
instruction maja˛ równy udział procentowy, ponieważ komunikaty te zawsze wyst˛epowały
razem.
Przedstawione eksperymenty obrazuja˛ możliwości jakie stwarza wykorzystanie emulatora
systemu komputerowego przy testowaniu oprogramowania obsługujacego
˛
urzadzenia
˛
wejścia/wyjścia. Wykazały one, że zaburzenia w różnych punktach wymiany danych mi˛edzy
urzadzeniem
˛
wejścia/wyjścia a systemem operacyjnym przynosza˛ znaczaco
˛ inne efekty.
Widoczne jest to szczególnie przy porównaniu eksperymentów USB MSD oraz kontrolera
USB. W przypadku pami˛eci masowej bład
˛ manifestował si˛e prawie w 100% eksperymentów
i oznaczał przekłamanie w przetwarzanych danych.
Jest to sytuacja, która może być
stosunkowo łatwo wychwycona, jeżeli użytkownik posiada wyniki funkcji skrótu i dokonuje
weryfikacji zawartości plików znajdujacych
˛
si˛e na urzadzeniu
˛
pami˛eci masowej. Natomiast
zaburzanie kontrolera USB manifestowało si˛e rzadziej, jednak skutki były znacznie bardziej
dotkliwe – najcz˛eściej było to zawieszenie si˛e systemu.
Warto zaznaczyć, że z dużym
prawdopodobieństwem wyniki eksperymentu USB MSD zmieniłyby si˛e, jeżeli scenariusz
testowy obejmowałby wi˛ecej operacji na plikach (np. tworzenie, usuwanie plików i katalogów)
– spodziewany byłby wtedy wi˛ekszy udział komunikatów systemu operacyjnego o wykrytych
nieprawidłowościach w systemie plików.
Analiza wyników zaburzania interfejsu sieciowego wykazała, że przekłamania w
deskryptorach pakietów przychodzacych
˛
z sieci wywołuja˛ bardzo niewiele awarii. Jednak
pomimo niewielkiej wartości współczynnika manifestacji bł˛edów (5%) dla eksperymentu
e1000, prawie 90% testów z zamanifestowanym bł˛edem powodowało niedost˛epność systemu
operacyjnego.
Niski współczynnik manifestacji zwiazany
˛
jest najprawdopodobniej z
mechanizmem retry wbudowanym w protokół TCP/IP. W przypadku uszkodzenia deskryptora
pakietu w sposób zaburzajacy
˛ dane (czyli np. zmiana wartości wskaźnika wskazujacego
˛
na
bufor z danymi) skutkowało to wyliczeniem sum kontrolnych o nieprawidłowych wartościach i
powtórzeniem komunikacji.
4.5.2. Zaburzanie kodu, danych statycznych i danych tylko do odczytu systemu
operacyjnego
W podrozdziale 4.2 wykazano potrzeb˛e zebrania informacji o tym jakiego typu dane sa˛
zaburzane oraz zwi˛ekszenia efektywności eksperymentów. W niniejszej sekcji przedstawiono
wynik wst˛epnych prac nad tymi zagadnieniami z użyciem statycznej analizy zawartości pami˛eci
RAM.
100
Jadro
˛
systemu operacyjnego GNU/Linux w wirtualnym systemie plików (VFS14 )
udost˛epnia w poddrzewie /proc/ informacje o uruchomionych procesach oraz dodatkowe
informacje zwiazane
˛
ze środowiskiem wykonania.
W wersji jadra
˛
dla architektury x86
dost˛epny jest plik /proc/iomem, który zawiera informacj˛e o odwzorowaniu różnych
komponentów systemu komputerowego (np. pami˛eci RAM/ROM, Video RAM/ROM, szyny
PCI, etc.)
w fizycznej przestrzeni adresowej.
Ponadto dost˛epna jest tam informacja o
zakresach adresów fizycznych, w których znajduja˛ si˛e kod, dane statyczne oraz dane tylko
do odczytu obrazu jadra
˛
systemu operacyjnego.
W niniejszej sekcji przedstawione sa˛
wyniki eksperymentów ukierunkowanych na zaburzanie pojedynczego bitu w wymienionych
segmentach systemu operacyjnego. Zaburzanie tych danych może być wykonywane dzi˛eki
działaniom przygotowawczym opisanym w metodyce (patrz 3.4.5) służacym
˛
konfiguracji
wstrzykiwania bł˛edów.
Konfiguracja eksperymentu
Konfiguracja eksperymentu była identyczna z eksperymentem przeprowadzonym w
podrozdziale 4.2 z wyjatkiem
˛
zastosowania systemu operacyjnego Debian Squeeze opartego o
jadro
˛ GNU/Linux w wersji 2.6.32 oraz wstrzykiwania bł˛edu w jeden z wyznaczonych zakresów
pami˛eci fizycznej. Dla każdego zakresu uruchomiono 10 000 testów. Mniejsza liczba testów
zwiazana
˛
jest z zaburzaniem znacznie mniejszego obszaru danych (najwi˛ekszy z badanych
obszarów, obraz jadra
˛
systemu operacyjnego, zajmuje około 2 MB pami˛eci, co stanowi
1
24
pami˛eci RAM, dla której przeprowadzano 50 000 eksperymentów w podrozdziale 4.2).
Wyniki
Podobnie jak w poprzednich eksperymentach sporzadzone
˛
zostały wykresy: procentowego
udziału zamanifestowanych bł˛edów (współczynnik Fs ) w ramach eksperymentów (rysunek
4.17), typów manifestowanych bł˛edów (rysunek 4.18), dost˛epności systemu dla testów
zakończonych nieprawidłowym wynikiem (rysunek 4.19) oraz typów komunikatów systemu
operacyjnego (tabela 4.5). Rysunek 4.20 przedstawia umiejscowienie w pami˛eci fizycznej
zaburzanych danych.
Wnioski
Analiza wyników eksperymentów jednoznacznie wskazuje na wi˛eksza˛ podatność na bł˛edy
sekcji zawierajacej
˛ kod systemu operacyjnego w porównaniu z sekcjami danych statycznych
i danych tylko do odczytu. Zaburzanie wymienionych sekcji danych manifestuje si˛e bł˛edem
w znikomym odsetku przeprowadzonych eksperymentów.
Wynika to z faktu, że ilość
przetwarzanych instrukcji kodu jest znacznie wi˛eksza, niż danych statycznych i danych tylko
do odczytu.
14
Ang. Virtual File System.
101
6
5
4
3
0
1
2
Testy %
PU + PS
NU + NS
Kod statyczny
Dane statyczne
Dane tylko do odczytu
60
20
40
PU
PS
NU
NS
0
Testy %
80
100
Rysunek 4.17: Wartość współczynnika Fs dla segmentów systemu operacyjnego
Kod statyczny
Dane statyczne
Dane tylko do odczytu
Rysunek 4.18: Rozkład bł˛edów dla segmentów systemu operacyjnego
102
100
80
60
40
0
20
Testy %
DU
DS
NDU
NDS
Kod statyczny
Dane statyczne
Dane tylko do odczytu
Rysunek 4.19: Dost˛epność systemu operacyjnego przy bł˛edach w segmentach systemu
operacyjnego
Komunikat %
Bad page state
Bad PC value
Null dereference
Null dereference 0
Paging request failed
Sched while atomic
General protection
Panic in interrupt
Panic - kill init
Segfault
Stack protector
Undefined instruction
Unclassified
Kod statyczny
0,51
13,64
31,06
10,86
47,22
3,03
12,12
18,43
8,84
2,02
0,25
7,32
2,02
Dane statyczne
0
3,57
17,86
3,57
78,57
0
64,29
57,14
0
0
0
0
0
Dane tylko do odczytu
0
29,41
29,41
5,88
70,59
0
23,53
23,53
23,53
0
0
0
0
Tabela 4.5: Komunikaty o bł˛edach zgłaszane przy zaburzaniu segmentów systemu
operacyjnego
Dane tylko do odczytu
Dane statyczne
Kod jądra
0
4
8
12
16
20
24
28
32
36
40
44
Pamięć fizyczna MB
Rysunek 4.20: Lokalizacja w pami˛eci fizycznej segmentów systemu operacyjnego
103
Wspólnym mianownikiem wszystkich eksperymentów jest znaczny (powyżej 30%) udział
bł˛edu Paging request failed zgłaszanego przez system operacyjny. Jest to zachowanie podobne
do efektów zaobserwowanych podczas wstrzykiwania bł˛edu w losowo wybrane miejsce
pami˛eci (tabela 4.1). Sugeruje to możliwości wychwytywania bł˛edów poprzez sprawdzanie,
czy zgłoszenie przez system operacyjny tego typu komunikatu zwiazane
˛
jest z wyst˛epowaniem
bł˛edu w systemie. Zagadnienie to jest dalej rozpatrywane w rozdziale 5.
Dzi˛eki zaw˛eżeniu zakresu zaburzanych adresów możliwe było zwi˛ekszenie efektywności
przeprowadzonych testów. Ponieważ miejsce załadowania obrazu jadra
˛ systemu operacyjnego
w pami˛eci fizycznej jest stałe, to porównanie rysunków 4.20 oraz 4.9 pozwala wyjaśnić
wi˛eksza˛ podatność na bł˛edy zakresu pami˛eci fizycznej od 16 do 18 MB. Niemniej dla pełnego
wyjaśnienia rejonów o podwyższonej podatności na bł˛edy z rysunku 4.9 potrzebne sa˛ dalsze
badania. Informacja,˛ której nie dostarcza przedstawiony eksperyment jest podatność na bł˛edy
pozostałych danych wykorzystywanych w przestrzeni jadra
˛
systemu operacyjnego – kodu
załadowanych modułów, stosu oraz danych alokowanych dynamicznie. Braki te uzupełnione
sa˛ eksperymentami opisanymi w sekcji w 4.5.3.
4.5.3. Zastosowanie profilowania do zaburzania kodu, stosu oraz danych alokowanych
systemu operacyjnego
Eksperymenty zaburzajace
˛ pami˛eć RAM przedstawione do tej pory wymagały minimalnej
ingerencji w środowisko emulatora. Niemniej uzyskane w nich rezultaty nie sa˛ pełne, ponieważ
brakowało w nich informacji o zaburzanych danych (patrz 4.2) lub zaburzany był kod systemu
operacyjnego, niezależnie od tego, czy kod ten był wykonywany w przebiegu scenariusza
(patrz 4.5.2).
Istotnym problemem jest również niska efektywność przeprowadzanych
eksperymentów, gdzie maksymalny odsetek zamanifestowanych bł˛edów wynosił zaledwie 5%
dla zaburzania rejonu pami˛eci zawierajacego
˛
kod systemu operacyjnego.
W celu rozwiazania
˛
wymienionych problemów podj˛ete zostały działania polegajace
˛ na
wzbogaceniu środowiska emulatora QEMU o autorskie mechanizmy pozwalajace
˛ profilować
i zaburzać zarówno kod, stos, a także dane alokowane przez system operacyjny. Wprowadzone
zmiany polegaja˛ na modyfikacji procesu binarnej translacji opisanej w podrozdziale 3.2 oraz
sekcji 3.4.3. Opracowany został zintegrowany z QEMU moduł śledzenia wykonania (patrz
3.4.6). Śledzenie każdego z wymienionych typów danych wymagało zastosowania innych
technik, które sa˛ opisane w dalszej cz˛eści rozdziału.
Dzi˛eki zastosowaniu profilowania
osiagni˛
˛ eto duża˛ efektywność przeprowadzanych eksperymentów w sensie współczynnika
manifestacji wstrzykni˛etych bł˛edów.
Eksperymenty opisane poniżej maja˛ na celu wyznaczenie charakterystyki niezawodności
systemu operacyjnego przy różnych obcia˛żeniach. Wykorzystano dwa scenariusze testowe.
Pierwszy z nich to scenariusz opisany w 4.2. Wyniki uzyskane w eksperymencie pozwalaja˛
104
na ocen˛e zysku z zastosowania profilowania wzgl˛edem eksperymentów przeprowadzonych w
4.2 oraz 4.5.2. Natomiast drugi scenariusz wzorowany jest na cz˛estym zastosowaniu systemu
komputerowego jako serwera HTTP.
Profilowanie i zaburzanie kodu systemu operacyjnego
Poprawa efektywności zaburzania kodu systemu operacyjnego zwiazana
˛
jest z wyznaczeniem
funkcji, które sa˛ wywoływane w trakcie przebiegu scenariusza testowego. Jednym z możliwych
rozwiazań
˛
byłoby skorzystanie z mechanizmów profilowania dost˛epnych w jadrze
˛
systemu
GNU/Linux. Alternatywna˛ opcja˛ było zastosowanie nieinwazyjnego śledzenia opracowanego
przez autora i opisanego w [24].
Technika ta polega na nagraniu adresów docelowych
skoków wykonanych przez procesor pracujacy
˛ w trybie jadra
˛
systemu operacyjnego (w
celu odfiltrowania skoków wykonywanych przez programy użytkownika) oraz na ich
podstawie wyznaczenie wykonywanych funkcji z pomoca˛ informacji zawartych w pliku
/proc/kallsyms15 . Podczas przeprowadzanych eksperymentów wybrana została metoda
nieinwazyjna, ponieważ jest to metoda dokładna16 i w czasie profilowania nie angażuje w żaden
sposób badanego systemu operacyjnego.
Zastosowanie
profilowania
powoduje
konieczność
jednokrotnego
uruchomienia
eksperymentu bez wstrzykni˛ecia bł˛edu w celu wyznaczenia zbioru funkcji jadra
˛
wykorzystywanych podczas zadanego scenariusza testowego.
nast˛epnie do określenia zakresów zaburzanej pami˛eci.
Zebrane informacje służa˛
Reasumujac,
˛ wykorzystanie
profilowania w eksperymencie wia˛że si˛e z nast˛epujacymi
˛
czynnościami:
1. modyfikacja scenariusza o krok odczytujacy
˛ zawartość pliku /proc/kallsyms,
2. przeprowadzenie pojedynczego testu bez wstrzykiwania bł˛edu i zebranie informacji o
funkcjach wykonanych w przestrzeni systemu operacyjnego17 ,
3. podczas przeprowadzania testów ze wstrzykiwaniem bł˛edu:
a) losowe wybranie funkcji systemu operacyjnego, która jest celem zaburzenia,
b) wyznaczenie zakresu pami˛eci, pod którym znajduje si˛e docelowa funkcja18 ,
c) wykorzystanie wyznaczonego zakresu jako parametru procedury wstrzykiwania bł˛edu.
Dodatkowym mechanizmem, który został wprowadzony do translacji binarnej, jest
wykrywanie liczby wykonań zaburzonej instrukcji. Modyfikacja ta polega na umieszczeniu
w buforze translacji binarnej procedury pozostawiajacej
˛
ślad w dzienniku eksperymentu.
15
Plik /proc/kallsyms udost˛epnia list˛e wszystkich funkcji systemu operacyjnego zawartych w
statycznym obrazie jadra
˛ oraz modułach wraz z ich adresami w wirtualnej przestrzeni adresowej.
16
Standardowe mechanizmy profilowania (np. oprofile) systemu GNU/Linux polegaja˛ na zbieraniu próbek
co pewien określony interwał czasu, przez co zbierane sa˛ informacje o cz˛esto wykonywanych procedurach, ale nie
o wszystkich procedurach wykonanych podczas profilowania.
17
Wyznaczenie zbioru wykonanych funkcji odbywa si˛e poprzez dopasowanie nagranych technika˛
nieinwazyjnego śledzenia adresów instrukcji do funkcji systemu operacyjnego, do których te funkcje należa.˛
18
Wyznaczenie to odbywa si˛e na podstawie odczytanej zawartości pliku /proc/kallsyms w danym
teście, ponieważ funkcje zdefiniowane w ładowanych modułach moga˛ być załadowane w inne rejony pami˛eci
dla każdego testu.
105
Dodawana procedura jest zawsze umieszczana bezpośrednio przed kodem emulujacym
˛
zmieniona˛ instrukcj˛e. Zebrane dzi˛eki temu dane pozwalaja˛ stwierdzić ile razy wykonana była
przekłamana instrukcja i powiazać
˛ te wyniki z informacjami o manifestacji bł˛edów.
Zaburzanie stosu systemu operacyjnego
Zaburzenie stosu watków
˛
wykonania w przestrzeni systemu operacyjnego jest zadaniem,
które wymaga dynamicznego wyznaczania docelowych adresów wstrzykni˛eć bł˛edów. Jest
to spowodowane faktem, że stos jest struktura˛ cz˛esto modyfikowana.˛ Próba dwuetapowego
wstrzykni˛ecia, jak to miało miejsce w przypadku kodu, może być nieskuteczna w zwiazku
˛
ze
zwini˛eciem stosu w odst˛epie czasu mi˛edzy wyznaczeniem zaburzanej przestrzeni, a faktycznym
wstrzykni˛eciem.
W przeprowadzonych eksperymentach wykorzystano możliwość modyfikacji procesu
translacji binarnej. Podobnie jak w przypadku profilowania kodu przed każda˛ instrukcja˛
skoku w przestrzeni jadra
˛ wykonywana jest specjalna procedura. Niemniej zamiast zbierania
informacji o adresie docelowym skoku przed wykonaniem instrukcji wywołania procedury call
zaburzana jest pami˛eć stosu w zakresie n bajtów poczawszy
˛
od wierzchołka stosu (czyli od
adresu zawartego w rejestrze ESP19 . Moment wstrzykni˛ecia jest wybierany warunkowo według
zadanego prawdopodobieństwa (patrz 3.4.5).
Zaburzanie danych alokowanych
Wyznaczenie adresów danych alokowanych w przestrzeni jadra
˛
systemu operacyjnego jest
zadaniem wymagajacym
˛
dogł˛ebnej znajomości badanego systemu operacyjnego.
System
GNU/Linux dysponuje kilkoma mechanizmami przydziału pami˛eci (patrz 2.1.2).
mi˛edzy innymi kmalloc, kmem_cache oraz vmalloc.
Sa˛ to
Każdy z tych mechanizmów
jest zoptymalizowany do innego scenariusza użycia: kmalloc służy do alokacji małych
porcji pami˛eci ogólnego przeznaczenia (najefektywniej buforów o rozmiarze mniejszym
niż pojedyncza strona pami˛eci, czyli 4096 bajtów), kmem_cache wyspecjalizowany
jest w przechowywaniu obiektów jednego typu o tym samym rozmiarze (np. w˛ezłów
struktur drzewiastych), natomiast vmalloc pozwala alokować duże i w miar˛e możliwości
ciagłe
˛
(w sensie fizycznej przestrzeni adresowej) obszary pami˛eci. W przeprowadzonych
eksperymentach skupiono si˛e na zaburzaniu pami˛eci alokowanej z użyciem mechanizmu
kmalloc, ponieważ jest to najbardziej ogólny z wymienionych mechanizmów alokacji.
Zaproponowana˛ metod˛e można rozszerzyć na pozostałe strategie alokacji.
Procedura wstrzykni˛ecia bł˛edu w pami˛eć alokowana˛ wymaga dynamicznego śledzenia,
gdzie w przestrzeni adresowej znajduje si˛e ten typ pami˛eci.
Dodatkowo bardzo istotne
jest również monitorowanie dost˛epu do wyznaczonych rejonów, ponieważ wstrzykni˛ecie w
19
Ang. Extended Stack Pointer – rejestr zawierajacy
˛ wskaźnik stosu w architekturach z rodziny x86.
106
momencie alokacji powoduje zaburzenie pami˛eci, która jeszcze nie została wypełniona danymi
do przetworzenia, co czyni taka˛ operacj˛e bezcelowa.˛
W celu zbierania informacji o alokowanej pami˛eci zastosowano strategi˛e zbliżona˛ do
sposobu działania przedstawionego przy zaburzaniu stosu. W odróżnieniu od wspomnianego
mechanizmu punktem zastosowania wstrzykni˛etej procedury nie sa˛ instrukcje wywołań
wszystkich funkcji wykonywanych w przestrzeni jadra,
˛
a jedynie instrukcje wywołań funkcji
trace_kmalloc oraz kfree. Funkcja trace_kmalock jest wywoływana zawsze na
końcu działania procedury przydziału pami˛eci (funkcja kmalloc) w celu poinformowania
wewn˛etrznych mechanizmów jadra
˛
GNU/Linux o fakcie przydziału pami˛eci (m.in. w celu
zbierania statystyk o fragmentacji). Funkcja ta została wybrana, ponieważ jej argumentami
sa˛ zarówno parametry wywołania kmalloc (rozmiar alokowanego bufora) oraz jej rezultat
(adres przydzielonego bufora). W analogiczny sposób monitorowana jest funkcja kfree, która
odpowiedzialna jest za zwolnienie poprzednio przydzielonej pami˛eci. Dzi˛eki informacjom
zebranym w ten sposób możliwe jest przechowywanie w środowisku emulatora pełnej
informacji o pami˛eci przydzielonej wewnatrz
˛
emulowanego systemu operacyjnego bez
ingerencji w jego działanie.
W celu zapewnienia, że zaburzone dane sa˛ wykorzystywane przez system operacyjny,
moment wstrzykni˛ecia został ściśle powiazany
˛
z odczytem tych danych. Zrealizowane to
zostało poprzez zmodyfikowanie wewn˛etrznych procedur QEMU odpowiedzialnych za odczyt
emulowanej pami˛eci w ten sposób, aby przed dost˛epem do danych wykonane było sprawdzenie,
czy odczytywany adres znajduje si˛e w puli pami˛eci wyznaczonej przez mechanizm śledzenia.
Jeżeli adres należy do puli, to nast˛epuje zaburzenie odczytywanych danych z zadanym
prawdopodobieństwem (patrz 3.4.5).
Konfiguracje eksperymentów
W ramach przeprowadzonych eksperymentów wykorzystano scenariusz 4.1 (patrz 4.2)
oraz scenariusz 4.3.
Pozostałe parametry konfiguracji eksperymentów były identyczne z
konfiguracja˛ zastosowana˛ w eksperymencie opisanym w 4.2 z wyjatkiem
˛
zastosowania systemu
operacyjnego Debian Squeeze opartego o jadro
˛
GNU/Linux w wersji 2.6.32 oraz konfiguracja˛
momentu wstrzykni˛ecia bł˛edu charakterystyczna˛ dla zaburzanych danych.
Scenariusz 4.3 imituje wystapienie
˛
bł˛edu w systemie realizujacym
˛
usług˛e serwera HTTP,
gdzie po próbie pobrania dokumentu z serwera emulowany administrator loguje si˛e do systemu
protokołem SSH20 w celu zbadania logów serwera oraz systemu operacyjnego. W przypadku
scenariusza 4.3 wynik uznany jest za prawidłowy, jeżeli udało si˛e poprawnie pobrać dokument
z serwera HTTP (krok 5). Jeżeli odpowiedź serwera jest prawidłowa, to test jest przerywany.
W przeciwnym przypadku symulowane jest podj˛ecie akcji diagnostycznej przez administratora
20
Ang. Secure Shell. Popularna usługa realizujaca
˛ zdalny, szyfrowany dost˛ep do konsoli systemu.
107
1
2
3
4
5
6
7
8
9
[QEMU] Uruchomienie SUT.
[ SUT] Zalogowanie si˛
e do systemu administratora przez konsol˛
e dost˛
epna˛
,→ przez port szeregowy.
[ SUT] Wypisanie zawartości pliku /proc/kallsyms na konsol˛
e.
[QEMU] Wstrzykni˛
ecie pojedynczego bł˛
edu typu bit-flip w kod systemu
,→ operacyjnego lub konfiguracja warunkowego wstrzykni˛
ecia bł˛
edu.
[ SUT] Nawiazanie
˛
połaczenia
˛
TCP/IP przez Nadzorc˛
e na port 80 SUT i
,→ wysłanie żadania
˛
HTTP z zastosowaniem programu wget.
[ SUT] Jeżeli odpowiedź serwera jest różna od referencyjnej, to
,→ nawiazanie
˛
połaczenia
˛
TCP/IP przez Nadzorc˛
e na port 22 SUT i
,→ zalogowanie si˛
e protokołem SSH do SUT na konto administratora.
[ SUT] W ramach sesji SSH wylistowanie zawartości logów serwera HTTP.
[ SUT] W ramach sesji SSH wylistowanie zawartości logów systemu
,→ operacyjnego.
[QEMU] Wyłaczenie
˛
SUT.
Scenariusz QEFI 4.3: Zaburzanie pami˛eci RAM przy realizowaniu usługi serwera HTTP
systemu (linie 7-9). System uznany jest za dost˛epny, jeżeli udało si˛e nawiazać
˛ połaczenie
˛
SSH
oraz wypisać zawartość plików z logami (linie 8 i 9).
Kod był zaburzany w stałym momencie eksperymentu wykorzystujac
˛ informacje z
profilowania oraz działań przygotowawczych (linia 3) pozwalajacych
˛
określić miejsce
załadowania poszczególnych funkcji systemu operacyjnego.
Wstrzykiwanie w stos było
wyzwalane warunkowo poprzez wykonanie przez emulowany procesor instrukcji ret21 ,
a bład
˛ był wstrzykni˛ety z prawdopodobieństwem 1:10 000 w zakresie 64 bajtów od
wartości przechowywanej w rejestrze ESP. W przypadku danych alokowanych informacje
o alokacjach były zbierane od momentu zalogowania si˛e administratora systemu, natomiast
symulacja bł˛edu sterowana była warunkiem odczytu tej pami˛eci – wstrzykni˛ecie bł˛edu
nast˛epowało z prawdopodobieństwem 1:1 000. Dla każdego typu zaburzanych danych zostało
przeprowadzone 10 000 iteracji eksperymentu.
Wyniki
Dla obu serii eksperymentów (oznaczonych cyframi rzymskimi:
I – scenariusz 4.1;
II – scenariusz 4.3) przygotowane zostało zestawienie wartości współczynnika Fs
zamanifestowanych bł˛edów (rysunek 4.21), typów zamanifestowanych bł˛edów (rysunek 4.22),
dost˛epności systemu dla testów zakończonych nieprawidłowym wynikiem (rysunek 4.23)
oraz rozkładu typów komunikatów jadra
˛
systemu operacyjnego (tabela 4.6).
Tak jak w
przypadku zaburzania danych systemu operacyjnego z 4.5.2 zostało przygotowane graficzne
przedstawienie lokalizacji zaburzanych danych dla scenariusza 4.1 (rysunek 4.24).
Sporzadzone
˛
eksperymentów.
zostały
wykresy
obrazujace
˛
dodatkowe
cechy
przeprowadzonych
Na rysunku 4.25 przedstawiono rozkład procentowy testów z
zamanifestowanym bł˛edem w zależności od liczby ile razy wykonana została zaburzona
21
Instrukcja powrotu z wywołania procedury.
108
80
60
40
0
20
Testy %
PU + PS
NU + NS
Kod I
Stos I
Dane I
Kod II
Stos II
Dane II
60
20
40
PU
PS
NU
NS
0
Testy %
80
100
Rysunek 4.21: Wartość współczynnika Fs dla różnych typów danych
Kod I
Stos I
Dane I
Kod II
Stos II
Dane II
Rysunek 4.22: Rozkład typów bł˛edów dla różnych typów danych
109
100
80
60
40
0
20
Testy %
DU
DS
NDU
NDS
Kod I
Stos I
Dane I
Kod II
Stos II
Dane II
Rysunek 4.23: Dost˛epność systemu operacyjnego przy bł˛edach w różnych typach danych
Komunikat %
Bad page state
Bad PC value
Null dereference
Null dereference 0
Paging request failed
Sched while atomic
Double fault
EXT FS error
General protection
I/O error
Page alocation failure
Panic in interrupt
Panic - kill init
Segfault
Stack protector
Undefined instruction
Unclassified
Kod I
0,41
14,92
29,42
11,56
50,03
3,34
0
0
17,71
0
0,03
19,37
8,49
0,85
0,42
9,03
2,31
Stos I
0,49
23,5
23,84
10,43
52,7
0,3
0,6
0
21,99
0
0,04
28,86
0,04
1,17
0
7,74
6,16
Dane I
0
7,27
12,57
4,94
43,26
0,09
0
0
1,46
0
0
4,44
0
10,11
0
8,55
30
Kod II
0,31
13,73
29,12
11,18
49,51
4,33
0
0,68
24,74
0,35
0,02
40,45
4,55
0,88
0,42
8,96
3,87
Stos II
0,17
16,1
22,26
8,94
57
3,88
0
0,25
17,37
0,08
0,08
70,32
0
0,17
0,42
7,08
2,95
Dane II
0
9,41
19,91
3,33
55,61
0,07
0
0
20,49
0
0
93,63
0
0
0
15,93
5,79
Tabela 4.6: Komunikaty o bł˛edach zgłaszane przy zaburzaniu różnych typów danych systemu
Dane alokowane
Stos
Kod
0
4
8
12
16
20
24
28
32
36
40
Pamięć fizyczna MB
Rysunek 4.24: Lokalizacja w pami˛eci fizycznej zaburzanych danych
110
44
10 20 30 40 50
Kod II
0
Testy %
Kod I
1
2
3
4
5
6
7
8
9
10 11 12 13 14 15 16
Liczba wykonań
wykonan
Rysunek 4.25: Liczba wykonań zaburzonego kodu
instrukcja kodu (tj. instrukcja, która na skutek wstrzykni˛ecia bł˛edu zmieniła swoja˛ semantyk˛e
lub parametry). Przykładowo można na nim odczytać, że spośród testów, w których bład
˛
został zamanifestowany, w 45% przypadków zaburzona instrukcja została wykonana tylko
jeden raz dla eksperymentu I. Na rysunku 4.26 przedstawiono zależność pomi˛edzy lokalizacja˛
wstrzykni˛ecia bł˛edu a miejscem wystapienia
˛
awarii wykrytej przez system operacyjny –
miejsce zamanifestowania bł˛edu wyznaczone zostało na podstawie analizy komunikatów
systemu operacyjnego zawierajacych
˛
stack-trace awarii (patrz 2.1.2, 3.4.5, 4.2).
Wykres
opracowano na podstawie odpowiednio 58% i 89% testów eksperymentów zaburzania kodu
I i II z zamanifestowanym bł˛edem – dzienniki wykonania tych testów zawierały komunikaty
zawierajace
˛ stack-trace, w którym wyst˛epowała zaburzana funkcja. Na wykresie uwzgl˛edniono
również informacje o liczbie wykonań zaburzonej instrukcji. Przykładowo można z niego
odczytać, że w 13% przypadków dla scenariusza 4.1 zaburzony bajt był pierwszym bajtem
instrukcji, która spowodowała wygenerowanie raportu o awarii (odległość 0), z czego w 7%
przypadków zaburzona instrukcja była wykonana tylko raz.
Rysunek 4.27 przedstawia zależność pomi˛edzy zaburzeniem konkretnego bitu w bajcie, a
spowodowaniem zamanifestowania bł˛edu. Na rysunku 4.28 zobrazowana jest relacja mi˛edzy
odległościa˛ zaburzonego bajtu od wartości rejestru ESP, a spowodowaniem zamanifestowania
bł˛edu.
Z analizy artefaktów eksperymentów zaburzenia kodu wynika, że współczynnik naturalnej
odporności na bł˛edy dla eksperymentów zaburzania kodu I i II wynosi odpowiednio I = 31% i
I = 42%. Wartości te wyznaczaja˛ współczynnik naturalnej odporności na bł˛edy dla bł˛edu typu
bit-flip w kodzie systemu operacyjnego dla zbadanych scenariuszy.
111
Liczba=wykonanń=>=1
−4
2
4
6
8
10
2
4
6
8
10
10
0
5
Testy=%
Kod II
15
Liczba=wykonanń===1
−10
−8
−6
−2
0
10
0
5
Testy=%
Kod I
15
Odlegl
−10
−8
−6
−4
−2
0
Odlegl
[B]
Rysunek 4.26: Odległość mi˛edzy zaburzana˛ instrukcja,˛ a miejscem manifestacji bł˛edu
Kod II
40
20
0
Testy %
60
Kod I
1
2
4
8
10
20
40
Maska
Rysunek 4.27: Maska zaburzonego bitu, a manifestacja bł˛edu
112
80
Stos II
50
0
25
Testy %
75
100
Stos I
−56
−48
−40
−32
−24
−16
−8
0
[B]
Rysunek 4.28: Wstrzykiwanie bł˛edu w stos, a manifestacja bł˛edu
Wnioski
Zastosowanie technik śledzenia wykonania spowodowało znaczny wzrost efektywności
eksperymentów testowych – od 5% zamanifestowanych bł˛edów dla statycznego wyznaczenia
kodu jadra
˛
systemu operacyjnego (patrz 4.5.2) do 70% zamanifestowanych bł˛edów dla
zaburzania kodu wyznaczonego metoda˛ profilowania.
Dodatkowo dzi˛eki zastosowanym
technikom analizowane sa˛ jedynie aktywowane bł˛edy.
Sporzadzone
˛
zestawienie lokalizacji zaburzanych danych w pami˛eci fizycznej (rysunek
4.24) pozwala stwierdzić, że dane alokowane, stosy oraz kod ładowanych modułów znajduja˛ si˛e
w losowych miejscach pami˛eci fizycznej. Wyniki te pozwalaja˛ zinterpretować w pełni wykres
podatności na bład
˛ w przestrzeni adresów fizycznych (rysunek 4.9). Zwi˛ekszona wrażliwość na
bł˛edy w niskich adresach przestrzeni fizycznej spowodowana jest faktem, że alokacja pami˛eci
przez jadro
˛ systemu cz˛esto wykorzystuje ten region. Podatność w zakresach 16-18MB pami˛eci
fizycznej wynika z zaburzania kodu jadra
˛
systemu, a pozostała pami˛eć losowo zawiera dane
wykorzystywane podczas scenariusza testowego.
Przeprowadzone badania wskazuja˛ na wyraźne różnice w podatności na bł˛edy
poszczególnych typów danych (rysunek 4.21). Zaburzanie kodu powoduje zamanifestowanie
bł˛edu w najwi˛ekszej liczbie przypadków (69% i 58% testów). Warto zauważyć, że ponad
90% bł˛edów generuje niepoprawny wynik dla eksperymentu I, a w przypadku eksperymentu II
nie zaobserwowano manifestacji bł˛edu przy wygenerowaniu poprawnego wyniku scenariusza.
Brak obserwacji prawidłowych wyników dla eksperymentu II wynika z przyj˛etego scenariusza,
gdzie uznanie wyniku za prawidłowy wia˛że si˛e jedynie z analiza˛ odpowiedzi serwera HTTP
113
działajacego
˛
w SUT. Oznacza to, że przykładowo współczynnik naturalnej odporności na bł˛edy
jest ściśle zwiazany
˛
z zadaniami realizowanymi przez system i obserwowanymi wynikami
działania systemu.
Dodatkowo potwierdza to analiza dost˛epności systemu operacyjnego
(rysunek 4.23) – w przypadku eksperymentu II system w wi˛ekszości testów stawał si˛e
niedost˛epny.
Warto zwrócić uwag˛e na podobieństwo tabel 4.5/Kod statyczny (strona 103) i 4.6/Kod I
oraz rysunków 4.18/Kod statyczny (strona 102) i 4.22 Kod I, które potwierdza zachowanie
charakterystyki manifestowania bł˛edu przy uzyskaniu znacznie wi˛ekszej liczby raportów o
bł˛edach. Bardzo istotne okazało si˛e wprowadzenie mechanizmu wykrywania, czy zaburzona
instrukcja została wykonana. Pozwoliło to uzyskać współczynnik naturalnej odporności na
bł˛edy (patrz 2.5.2), który został wyznaczony na I = 31-42%. Prowadzi to do pytania, jak
zmodyfikowane zostało działanie realizowanych przez ten kod algorytmów i czy zaburzenie
ma istotny wpływ na działanie systemu operacyjnego również w przypadku realizacji innych
usług systemu operacyjnego.
Istotna˛ obserwacja˛ jest odkrycie, że w blisko 45% iteracji
eksperymentów zakończonych manifestacja˛ bł˛edu zaburzona instrukcja została wykonana
tylko raz.
Informacja ta połaczona
˛
z danymi uzyskanymi z rysunku 4.26, gdzie 55%
lokalizacji manifestacji bł˛edu było położone w bezpośrednim sasiedztwie
˛
(od -1 do 4
bajtów) zaburzanych instrukcji pozwala wnioskować o niewielkim odst˛epie czasu pomi˛edzy
wykonaniem nieprawidłowej instrukcji a zamanifestowaniem bł˛edu. Ponadto widoczna na
rysunku 4.27 tendencja, że zaburzanie wyższych bitów bajtu cz˛eściej powoduje manifestacj˛e
bł˛edu jest zgodna z wynikami prac prowadzonych w Instytucie Informatyki Politechniki
Warszawskiej (patrz [41, 42]).
Wstrzykiwanie bł˛edów w dane alokowane powoduje zamanifestowanie bł˛edu na poziomie
38% i 12%, czyniac
˛ ten rodzaj danych drugim pod wzgl˛edem wrażliwości na bł˛edy. Warto
zaznaczyć, że wprowadzenie bł˛edu odbywało si˛e zaraz przed odczytem, czyli w każdym
przypadku zmienione dane przetwarzane były przez system operacyjny.
Dane przechowywane na stosie wykazuja˛ si˛e współczynnikiem podatności na zaburzenie
wysokości około 29% i 12%.
Przedstawiona na rysunku 4.28 tendencja do znacznie
cz˛estszego manifestowania bł˛edów przy zaburzaniu adresów w odległości 4 bajtów od adresu
przechowywanego w rejestrze ESP wynika z wybranego momentu wstrzykni˛ecia – zawsze
podczas zaburzania pod tymi adresami znajduje si˛e adres powrotny wywoływania funkcji. Dane
odłożone wcześniej na stosie maja˛ zbliżony współczynnik manifestacji bł˛edu.
Wyniki uzyskane wskutek zaburzania różnych typów danych sa˛ zbieżne z wynikami
uzyskanymi w eksperymentach przeprowadzonych w [48], gdzie wstrzykiwanie bł˛edu oparte
było o ładowany moduł jadra
˛ systemu operacyjnego.
114
4.6. Podsumowanie
W niniejszym rozdziale przedstawione zostały eksperymenty b˛edace
˛ zastosowaniem
metodyki opisanej w rozdziale 3.
scenariuszy testów.
Podj˛eta została próba opracowania reprezentatywnych
Przeprowadzone eksperymenty wykazały praktyczne zastosowanie
metodyki umożliwiajac
˛ uzupełnienie stanu wiedzy o nowe informacje – porównanie
wrażliwości na bł˛edy architektur sprz˛etowych (4.3), systemów operacyjnych (4.4),
poszczególnych typów danych wykorzystywanych przez system operacyjny (4.5.2, 4.5.3) oraz
na bł˛edy wyst˛epujace
˛ w różnych urzadzeniach
˛
systemu komputerowego (4.5.1). Przedstawiono
szeroki przekrój eksperymentów i możliwe jest poszerzanie spektrum badań o dodatkowe
modele bł˛edów i zaburzane urzadzenia.
˛
Reasumujac,
˛ atuty opracowanej metodyki wzgl˛edem
rozwiazań
˛
znanych z literatury to:
— możliwość porównania wielu architektur sprz˛etowych bez konieczności opracowywania
dodatkowego oprogramowania,
— możliwość porównania implementacji wielu systemów operacyjnych bez konieczności
opracowywania dodatkowego oprogramowania,
— możliwość zbadania wrażliwości na bł˛edy obszarów pami˛eci fizycznej,
— badanie niezawodności systemu operacyjnego bez konieczności modyfikacji badanego
oprogramowania,
— opracowana technika nieinwazyjnego śledzenia wykonania,
— zaburzanie pracy urzadzeń
˛
na poziomie komunikacji z systemem operacyjnym.
Dodatkowym atutem metodyki jest możliwość przeprowadzania eksperymentów na szeroka˛
skal˛e z zastosowaniem wielu maszyn do przeprowadzania obliczeń, co jest zaleta˛ w
porównaniu do rozwiazań
˛
wykorzystujacych
˛
rzeczywiste systemy komputerowe. Pozwala to
na przeprowadzanie długookresowych testów ukierunkowanych na różne komponenty systemu
operacyjnego.
Dzi˛eki przeprowadzonym eksperymentom można stwierdzić, że zarówno wykorzystana
architektura ISA, jak i zainstalowany system operacyjny maja˛ wpływ na poziom manifestacji
bł˛edów. Badania ukierunkowane na różne komponenty systemu operacyjnego maja˛ szczególne
znaczenie, ponieważ pozwoliły określić, które z komponentów sa˛ najbardziej wrażliwe na
bł˛edy, co stanowi podstaw˛e rozważań opisanych w rozdziale 5.
115
5. Mechanizmy wykrywania i obsługi bł˛edów
Rozdział poświ˛econy jest zagadnieniu projektowania i wykorzystania mechanizmów
zwi˛ekszania niezawodności oprogramowania.
Przedstawiono w nim oryginalne metody
detekcji i obsługi bł˛edów wraz z dyskusja˛ nad ich skutecznościa.˛
Zaproponowane
zostały nast˛epujace
˛ metody zwi˛ekszania niezawodności: periodyczna weryfikacja spójności
kodu jadra
˛
systemu operacyjnego, metoda obsługi przerwań pozwalajaca
˛ na podj˛ecie
procedur naprawczych przed wystapieniem
˛
awarii, algorytm brudnych zasobów stanowiacy
˛
rozszerzenie metody obsługi przerwań oraz metod˛e ochrony danych przechowywanych na
stosie. Dodatkowo przeprowadzono dyskusj˛e nad wykorzystaniem mechanizmów ochrony
danych oraz zastosowaniem QEFI do optymalizacji niezawodności oprogramowania systemów
operacyjnych.
5.1. Mechanizmy zwi˛ekszajace
˛ niezawodność w systemie operacyjnym
Podstawowe mechanizmy zwi˛ekszania niezawodności zostały opisane w podrozdziale 2.3.
Poniżej przedstawiono opis wykorzystania mechanizmów izolacji, redundancji, detekcji i
odtwarzalności w systemie operacyjnym.
Podział zadań na procesy w systemach operacyjnych jest implementacja˛ idei izolacji.
Dzi˛eki odseparowaniu przestrzeni pami˛eci poszczególnych procesów awaria jednego procesu
nie wpływa na pozostałe procesy działajace
˛ w systemie. Awaria procesu jest wywoływana
wykonaniem niedozwolonej operacji – np.
odwołaniem do nieprawidłowego obszaru
pami˛eci, próba˛ wykonania nieprawidłowej instrukcji1 lub wykonaniem nieprawidłowej
operacji (np.
dzielenie przez 0).
Opisane sytuacje sa˛ zgłaszane jako wyjatki
˛
– w
przypadku nieprawidłowego dost˛epu do pami˛eci wyjatek
˛ zgłasza kontroler MMU, natomiast
w pozostałych przypadkach wyjatki
˛
sa˛ generowane przez sam procesor.
Zadaniem
systemu operacyjnego jest zakończenie działania procesu i udost˛epnienie informacji o
okolicznościach awarii. Wpływa to na ograniczenie propagacji bł˛edów, ponieważ proces
wykonujacy
˛
nieprawidłowe operacje zostaje zatrzymany, uniemożliwiajac
˛ generowanie
bł˛ednych wyników. Niemniej warto zaznaczyć, że w takim scenariuszu system komputerowy
przestaje spełniać swoje zadanie z uwagi na zaprzestanie wykonywania uruchomionych w
1
Np. instrukcji niezdefiniowanej dla danej architektury lub wymagajacej
˛ wyższego poziomu uprawnień niż
aktualny poziom zdefiniowany dla procesu.
117
nim programów.
Mechanizm ten został opracowany w szczególności dla ochrony przed
bł˛edami programistycznymi, niemniej wymienione typy awarii sa˛ również obserwowane
przy symulowanych bł˛edach sprz˛etowych (patrz rozdział 4). Skuteczność techniki izolacji
spowodowała, że jest ona coraz cz˛eściej wykorzystywana na gruncie aplikacji. Jednym z
najciekawszych wdrożeń tej techniki jest współczesna architektura przegladarek
˛
internetowych
(patrz [91]), gdzie poszczególne zadania przetwarzania stron internetowych (pobieranie
zasobów, renderowanie strony, obsługa wtyczek) sa˛ delegowane do dedykowanych procesów.
Przykładowo wtyczki przegladarek
˛
internetowych sa˛ dynamicznymi bibliotekami (patrz 2.1.2)
tworzonymi przez zewn˛etrznych dostawców, a twórcy przegladarki
˛
nie maja˛ wpływu na
jakość tego oprogramowania – niemniej pragna˛ zabezpieczyć si˛e przed sytuacja,˛ gdy awaria
spowodowana bł˛edem kodu wtyczki powoduje awari˛e całego programu przegladarki.
˛
Dzi˛eki
przeniesieniu wykonania kodu wtyczki do osobnego procesu, w przypadku awarii, aplikacja
przegladarki
˛
nie ulega zatrzymaniu – jedynie fragment strony obsługiwany przez wtyczk˛e nie
jest wyświetlany. Przykładem zbliżonego modelu izolacji na gruncie systemów operacyjnych
jest koncepcja mikrojadra
˛ (np. system Minix [52, 53, 54]), gdzie poszczególne usługi systemu
operacyjnego (np. implementacja systemów plików, obsługa urzadzeń)
˛
sa˛ oddelegowane do
osobnych procesów podlegajacych
˛
mechanizmowi reinkarnacji w przypadku awarii. Wdrożenie
podobnych mechanizmów do jadra
˛ monolitycznego jakim jest GNU/Linux byłoby szczególnie
trudne ze wzgl˛edu na inny model architektury i wymagałoby gruntownych zamian kodu
źródłowego.
Redundancja może być zastosowana zarówno do danych jak i do kodu programu. Polega
ona na umieszczeniu dodatkowej informacji, która ułatwia określenie czy pierwotna informacja
nie uległa przekłamaniu. W przypadku danych sa˛ to dodatkowe kopie, sumy kontrolne, kody
korekcji bł˛edów lub inne informacje specjalizowane dla danego typu danych. W przypadku
kodu może to być alternatywna implementacja tego samego algorytmu realizowanego
przez pierwotny kod lub algorytmu dajacego
˛
zbliżony wynik końcowy.
W systemach
operacyjnych redundancja jest stosowana najcz˛eściej dla danych, które sa˛ przekazywane na
zewnatrz
˛ systemu (np. obliczanie sum kontrolnych do pakietów sieciowych), jednak dane
wewn˛etrzne zazwyczaj sa˛ optymalizowane pod katem
˛
wykorzystywanego miejsca i wydajności
przetwarzania. Natomiast kod systemu operacyjnego bardzo rzadko jest redundantny – wynika
to z konieczności zapewnienia dużej wydajności systemu operacyjnego.
Mechanizmy detekcji w dużej mierze korzystaja˛ z izolacji oraz redundancji jako
podstaw wykrywania bł˛edów. Naruszenie granic izolacji lub niezgodność danych z danymi
kontrolnymi jest podstawa˛ do stwierdzenia obecności bł˛edu w systemie. Niemniej detekcja
korzysta także i z innych metod wykrywania bł˛edów.
Przykładem sa˛ asercje, czyli
niezmienniki, których naruszenie oznacza nieprawidłowe działanie systemu. Asercje moga˛ być
definiowane przez programist˛e, ale moga˛ być także odkrywane automatycznie na podstawie
118
obserwacji działajacego
˛
systemu (patrz [50]).
Inna˛ metoda˛ detekcji jest monitorowanie
cech systemu takich jak przepływ danych, czas reakcji systemu (performance monitor), lub
zgłaszane zdarzenia (event monitor) – sa˛ to najcz˛eściej rozwiazania
˛
bazujace
˛ na analizie
dzienników systemowych. Instytut Informatyki Politechniki Warszawskiej ma doświadczenie
w projektowaniu mechanizmów opartych o asercje jak i analiz˛e dzienników systemu (patrz
[71, 82, 83]). Detekcja jest szczególnie istotna w przypadku, gdy aktywacja bł˛edu nie zakończy
si˛e awaria,˛ a jedynie nieprawidłowym działaniem systemu. Sytuacja taka jest niepożadana,
˛
ponieważ bład
˛ może istnieć w systemie operacyjnym niezauważony przed dłuższy czas
zaburzajac
˛ generowane wyniki jednej lub grupy aplikacji. Zastosowanie mechanizmów detekcji
w systemach operacyjnych zazwyczaj wia˛że si˛e z detekcja˛ bł˛edów w procesach użytkownika
lub danych zewn˛etrznych, a wykrywanie bł˛edów wewn˛etrznych ograniczone jest do asercji
przygotowanych przez programistów.
Odtwarzalność jest to cecha pozwalajaca
˛ na wznowienie działania systemu po awarii
lub wykryciu bł˛edu.
Może to być osiagni˛
˛ ete poprzez podj˛ecie działań naprawczych
lub przywrócenie systemu do zapisanego poprzednio prawidłowego stanu.
Możliwość
zapami˛etywania migawek działajacego
˛
systemu operacyjnego wraz z uruchomionymi
programami jest popularna˛ funkcja˛ systemów wirtualizacji.
Obecnie wiele projektów
skupionych jest na stworzeniu analogicznych systemów dla aplikacji użytkownika2 oraz
wzbogaceniu jadra
˛
systemu GNU/Linux o mechanizmy tego typu (patrz [45]). Zadaniem
znacznie trudniejszym niż odtworzenie ostatniego prawidłowego stanu aplikacji jest podj˛ecie
próby naprawienia awarii, ponieważ nie jest wiadome jak długo bład
˛ istniał w systemie i jak
wiele wprowadził odst˛epstw od prawidłowego działania systemu.
5.2. Ogólne założenia
Celem pracy jest poprawa niezawodności istniejacego
˛
systemu operacyjnego. Mechanizmy
wykrywania i obsługi bł˛edów musza˛ spełniać szereg wymagań. Podstawowe wymagania
funkcjonalne to: detekcja bł˛edów, zapobieganie awariom, realizacja procedur naprawczych.
Poprzez detekcj˛e bł˛edów rozumiana jest funkcja pozwalajaca
˛ na określenie, czy w systemie
wystapił
˛ bład
˛ – niezależnie od tego, czy bład
˛ został już aktywowany i spowodował awari˛e, czy
został jedynie wykryty. W przypadku, gdy bład
˛ został wykryty, ale nie spowodował awarii
oczekuje si˛e od mechanizmów niezawodnościowych podj˛ecia działań zapobiegawczych zanim
bład
˛ zostanie aktywowany. Natomiast w przypadku wystapienia
˛
awarii konieczna jest próba
określenia, czy awaria została spowodowana bł˛edem sprz˛etowym i ewentualne wykonanie
procedur naprawczych majacych
˛
na celu unikni˛ecie zgłaszania awarii. Celem wymienionych
wymagań jest podtrzymanie pracy systemu oraz poinformowanie użytkownika o wykryciu
2
Np. http://criu.org/
119
ewentualnych awarii sprz˛etu.
Dopuszczalne jest czasowe generowanie nieprawidłowych
wyników – mechanizmy wyższego poziomu powinny zapewnić tolerowanie tego typu sytuacji.
Wymagania niefunkcjonalne, które zostały określone dla rozwiazań
˛
przygotowanych w
niniejszej pracy, to: akceptowalne zużycie zasobów oraz możliwość integracji z istniejacym
˛
oprogramowaniem systemu GNU/Linux.
Poziom akceptowalnego zużycia zasobów jest
indywidualnie określany dla każdego systemu i cz˛esto jest on zależny od zakładanego poziomu
niezawodności. Natomiast wymaganie minimalnego nakładu pracy potrzebnego do integracji
jest zwiazane
˛
z praktycznym aspektem wykorzystania danego mechanizmu. Rozwiazania
˛
wymagajace
˛ wielu modyfikacji istniejacego
˛
oprogramowania moga˛ zostać uznane za zbyt
ryzykowne do wdrożenia. Warto zaznaczyć, że projektant mechanizmów niezawodnościowych
ma znacznie wi˛ecej swobody podczas przygotowania nowych systemów, gdzie mechanizmy te
moga˛ zostać uwzgl˛ednione w architekturze systemu.
5.3. Identyfikacja krytycznych komponentów
W celu usystematyzowania problemu zwi˛ekszania niezawodności oprogramowania
konieczne jest zidentyfikowanie krytycznych komponentów, które sa˛ kluczowe dla
prawidłowego działania systemu.
Wskazanie i optymalizacja ich w pierwszej kolejności
pozwoli na skuteczna˛ popraw˛e poziomu niezawodności systemów komputerowych.
Zgodnie z analizami przeprowadzonymi w sekcji 4.5.3 można stwierdzić, że najistotniejsze
z punktu widzenia poprawnego działania systemu jest prawidłowe działanie kodu systemu
operacyjnego. Wynika to z dwóch faktów: jest on najbardziej wrażliwy na zaburzenia oraz
tylko prawidłowe działanie kodu umożliwia poprawna˛ obsług˛e bł˛edów danych. Dodatkowo
detekcja, czy kod został zaburzony w sposób trwały (np. poprzez uszkodzenie komórek
pami˛eci RAM) jest zadaniem stosunkowo prostym – kod systemu operacyjnego jest najcz˛eściej
ładowany z pliku i źródło to może posłużyć do weryfikacji obrazu kodu znajdujacego
˛
si˛e w
pami˛eci. Jednak w przypadku aktywowania bł˛edów kodu przeprowadzenie udanej procedury
naprawczej może być trudne lub wr˛ecz niewykonalne. Warto zaznaczyć, że przy wprowadzaniu
mechanizmów zwi˛ekszania niezawodności konieczne jest również zapewnienie spójności kodu
implementujacego
˛
te mechanizmy (zagadnienie to zostało szerzej opisane w 5.5).
Dane składowane na stosie oraz dane alokowane sa˛ mniej podatne na zaburzenia niż kod
systemu operacyjnego (patrz 4.5.3). Niemniej ochrona stosu, ze wzgl˛edu na różnorodność
i duża˛ zmienność składowanych danych jest zadaniem trudnym. Dane przechowywane na
stosie sa˛ niejednorodne – oprócz ramek stosu moga˛ tam być przechowywane tymczasowe
bufory, pośrednie wyniki obliczeń, wartości rejestrów, argumenty wywołań funkcji oraz
wartości zwracane przez funkcje.
Istotny jest fakt, że dane składowane na stosie sa˛
ważne tylko i wyłacznie
˛
przez czas wykonania bieżacej
˛
procedury. Dodatkowo brak jest
120
referencyjnego obrazu tych danych, a obliczanie sum kontrolnych stanu stosu przy wywołaniach
kolejnych procedur nie może być zastosowane ze wzgl˛edu na możliwość modyfikacji danych
znajdujacych
˛
si˛e na stosie przez wywoływana˛ procedur˛e (mechanizm ten polega na przekazaniu
do procedury parametru b˛edacego
˛
adresem bufora znajdujacego
˛
si˛e na stosie).
Natomiast dane przechowywane w pami˛eci alokowanej charakteryzuja˛ si˛e określona˛
struktura˛ – najcz˛eściej zorganizowane sa˛ one w struktury danych (np. listy, drzewa, kolejki).
Należy wyróżnić dane wewn˛etrzne i zewn˛etrzne. Dane zewn˛etrzne sa˛ to dane, których źródło
pochodzenia znajduje si˛e poza pami˛ecia˛ komputera – np. dane otrzymane przy transmisji
sieciowej, odczycie dysku twardego, czy obraz zarejestrowany zewn˛etrzna˛ kamera.˛ Natomiast
dane wewn˛etrzne sa˛ tworzone w pami˛eci systemu w celu prawidłowego działania i realizacji
usług – np. wewn˛etrzna lista procesów uruchomionych w systemie, struktury systemu plików,
robocze struktury danych wykorzystywane przy zarzadzaniu
˛
zadaniami. Dane zewn˛etrzne
sa˛ cz˛eściej poddawane sprawdzeniom pod wzgl˛edem poprawności i zaburzanie ich jest
wykrywane przez system – np. zaburzanie pakietów danych odbieranych z sieci powoduje
jedynie uruchomienie mechanizmów retransmisji (patrz [38]).
Z kolei dane wewn˛etrzne
najcz˛eściej nie sa˛ wzbogacone w dodatkowe informacje pozwalajace
˛ na weryfikacj˛e ich
poprawności w przypadku awarii.
W celu zwi˛ekszania niezawodności konieczne jest usprawnienie poprawnego wykonania
kodu. Osiagni˛
˛ ecie tego celu warunkuje prawidłowo działajacy
˛ stos. Dzi˛eki zwi˛ekszeniu
niezawodności działania tych komponentów możliwe jest skuteczne zastosowanie
mechanizmów ochrony danych.
5.4. Założenia dotyczace
˛ projektowanych mechanizmów zwi˛ekszania
niezawodności
Bł˛edy pami˛eci moga˛ być zjawiskiem przemijalnym, incydentalna˛ zmiana˛ wartości danych
lub być efektem trwałego uszkodzenia sprz˛etu (szerszy opis w rozdziale 2). Najskuteczniejsza˛
strategia˛ obsługi awarii powstałych na skutek bł˛edów pami˛eci jest odtworzenie systemu do
wcześniej zapisanego stanu (checkpointing – patrz 2.3). Niemniej rozwiazanie
˛
tego typu
powoduje utrat˛e cz˛eści obliczeń, a czas potrzebny na przeprowadzenie procedury odtwarzania
może być nieakceptowalny. Dodatkowym ograniczeniem sa˛ trudności w implementacji techniki
checkpointing dla systemu operacyjnego – najcz˛eściej wykonywana jest kopia zapasowa
systemu operacyjnego działajacego
˛
wewnatrz
˛
maszyny wirtualnej, co z kolei polega na
niezawodnym działaniu systemu b˛edacego
˛
gospodarzem maszyny wirtualnej (szerzej opisane
w 2.3).
Mechanizmy zaproponowane w podrozdziałach 5.5 oraz 5.6 pozwalaja˛ na szybsze
przeprowadzenie procedury naprawczej niż mechanizm checkpointing kosztem potencjalnego,
121
czasowego generowania przez system nieprawidłowych wyników.
Celem nadrz˛ednym
projektowanych mechanizmów jest unikni˛ecie awarii systemu powodujacych
˛
jego
niedost˛epność.
W przypadku wystapienia
˛
awarii, pomimo działań podj˛etych przez
zaproponowane przez autora mechanizmy, konieczne jest zastosowanie innych mechanizmów
niezawodnościowych – np. opisany checkpointing.
Natomiast w sytuacji generowania
niepoprawnych wyników konieczne jest zastosowanie mechanizmów umożliwiajacych
˛
ich
tolerowanie.
Rozwiazania
˛
przedstawione w podrozdziałach 5.5 i 5.6 poświ˛econe sa˛ bł˛edom, których
skutki sa˛ obserwowalne przy wi˛ecej niż pojedynczym odczycie danych, czyli bł˛edy zmiany
wartości i trwałe uszkodzenia. Bł˛edy migoczace
˛ nie sa˛ rozważane z uwagi na brak możliwości
określenia pierwotnej przyczyny ewentualnej awarii.
Przykładowo przekłamanie przy
odczycie komórki pami˛eci zawierajacej
˛ adres skoku wykonanego przez procesor uniemożliwia
przeprowadzenie analizy jaki kod został wykonany w wyniku zaburzenia.
Należy zwrócić uwag˛e na konieczność detekcji, czy zaburzona komórka pami˛eci jest
jest trwale uszkodzona.
W takim przypadku wymagane jest wyłaczenie
˛
niesprawnego
obszaru pami˛eci z użycia. Procedura wyłaczenia
˛
jest zależna od rodzaju danych, który był
przechowywany. Jeżeli był to kod systemu operacyjnego, to konieczna jest próba przeniesienia
kodu z uszkodzonego miejsca pami˛eci. Jednym z możliwych rozwiazań
˛
jest załadowanie
poprawnego kodu z referencyjnego obrazu jadra
˛ i aktualizacja instrukcji skoku w uszkodzone
miejsce, tak aby adresy skoku wskazywały nowe miejsce. W przypadku danych systemu
operacyjnego procedura odtworzenia i przeniesienia danych w inny obszar pami˛eci jest
zadaniem, które wymaga znajomości struktury odtwarzanych danych.
Dodatkowym wymaganiem jest, aby informacja o uszkodzonych rejonach pami˛eci była
zapisana i odtworzona po ponownym uruchomieniu systemu na tym samym sprz˛ecie. Warto
zaznaczyć, że jadro
˛
GNU/Linux jest wyposażone w funkcj˛e „omijania” niektórych banków
pami˛eci3 , jednak metoda ta ma pewne ograniczenia. Po pierwsze wyłaczony
˛
obszar musi
być wskazany przy ładowaniu jadra
˛ systemu. Po drugie implementacja polega na oznaczeniu
danego obszaru jako wykorzystany w mechanizmie alokacji, przez co nie zostanie on
zaalokowany ponownie – o ile metoda ta działa w wi˛ekszości przypadków, to nie może ona
posłużyć do wyłaczenia
˛
obszarów pami˛eci, gdzie ładowane jest jadro
˛
systemu operacyjnego
GNU/Linux (adres ładowania jest definiowany podczas kompilacji jadra).
˛
5.5. Zapewnienie spójności kodu wykonywalnego
W niniejszym podrozdziale przedstawiony jest sposób zapewnienia spójności kodu jadra
˛
systemu operacyjnego polegajacy
˛ na periodycznym sprawdzeniu załadowanego w pami˛eci
3
https://www.kernel.org/doc/Documentation/bad_memory.txt
122
RAM obrazu systemu. Metoda ta jest implementacja˛ idei zapobiegania awariom i uzupełnia ona
rozwiazania
˛
przedstawione w podrozdziale 5.6, które polegaja˛ na obsłudze sytuacji awaryjnych.
Zastosowanie rozwiazań
˛
okresowego sprawdzania spójności jest konieczne w celu
przeciwdziałania istnieniu w systemie nieaktywowanych bł˛edów oraz wykrywaniu bł˛edów
aktywowanych, które nie spowodowały awarii. Szczególnie istotna˛ kwestia˛ jest możliwość
akumulacji bł˛edów w kodzie, który nie jest wykonywany podczas prawidłowej pracy systemu
– np. kod obsługi sytuacji wyjatkowych
˛
lub niewykorzystywanych usług.
Możliwy jest
scenariusz, gdzie bł˛edy zakumulowane w kodzie obsługi sytuacji wyjatkowej
˛
uniemożliwiaja˛
przeprowadzenie procedury obsługi, co z kolei skutkuje awaria˛ systemu przy wystapieniu
˛
sytuacji wyjatkowej.
˛
Próba˛ przeciwdziałania takiej sytuacji jest wykorzystanie okna czasowego
od wystapienia
˛
bł˛edu do wykonania zaburzonego kodu w celu przeprowadzenia procedury
usuni˛ecia bł˛edu przed jego aktywowaniem.
Sprawdzanie spójności kodu istotne jest
również w przypadku bł˛edów, które zostały aktywowane. Jak wykazano w eksperymentach
przeprowadzonych w sekcji 4.5.3 współczynnik tolerancji dla bł˛edów typu bit-flip w kodzie
systemu operacyjnego wynosi nawet 31%.
Bł˛edy te mogły spowodować różnego typu
odst˛epstwa od prawidłowego działania systemu. Stwierdzenie ich obecności jest istotne przy
ocenie zaufania do wygenerowanych przez system wyników.
Dodatkowa˛ kwestia˛ jest zapewnienie poprawności kodu realizujacego
˛
okresowe
sprawdzanie spójności kodu jadra
˛ systemu operacyjnego, ponieważ w przypadku wystapienia
˛
bł˛edu w tym kodzie może on nie realizować swojej funkcji lub sygnalizować fałszywe
alarmy. Możliwym scenariuszem jest zastosowanie kilku oddzielnych instancji mechanizmu
okresowego sprawdzania spójności kodu uruchamianych naprzemiennie.
Dzi˛eki takiemu
rozwiazaniu
˛
zwi˛ekszane jest prawdopodobieństwo wykrycia bł˛edu przed aktywacja,˛ chociaż
prawdopodobieństwo aktywacji bł˛edu nie jest wyeliminowane.
Implementacja programowego zapewniania spójności kodu jest alternatywa˛ dla
mechanizmów sprz˛etowych – np. pami˛eci ECC (patrz 2.2.4).
Niemniej zastosowanie
pami˛eci ECC wia˛że si˛e z wi˛ekszym kosztem systemu.
Architektura
W celu realizacji okresowego sprawdzania spójności kodu jadra
˛
systemu operacyjnego
przygotowany został moduł jadra
˛
systemu GNU/Linux. Rozwiazanie
˛
to zostało wybrane w
zwiazku
˛
z założeniem minimalnego kosztu integracji mechanizmów niezawodnościowych z
istniejac
˛ a˛ implementacja˛ systemu operacyjnego (opisane w podrozdziale 5.2). Moduł jadra
˛
może być załadowany w dowolnym momencie działania systemu i realizuje on nast˛epujace
˛
funkcje:
123
— wykonanie kopii zapasowej statycznego obrazu kodu jadra
˛ 4 w momencie załadowania
modułu,
— okresowe porównywanie obrazu kodu i wykonanej kopii zapasowej,
— w przypadku wykrycia bł˛edu kod jadra
˛
systemu operacyjnego jest odtwarzany z kopii
zapasowej.
Eksperymentalna weryfikacja
Zaproponowana metoda została zweryfikowana eksperymentalnie.
Scenariusz polegał
na dwukrotnym uruchomieniu instancji QEMU emulujacej
˛
system GNU/Linux.
Przy
pierwszym uruchomieniu wprowadzono losowy bład
˛ w procedurze tcp_v4_rcv5 . Nast˛epnie
uruchomiono program wget,
który poprzez wywołanie usług sieciowych systemu
operacyjnego aktywował wprowadzony bład,
˛ co z kolei spowodowało awari˛e.
Zapis
przeprowadzonej interakcji z systemem został umieszczony na listingu 5.1.
1
2
3
4
5
6
7
8
9
10
root@debian-i386:~# wget www.pw.edu.pl
--2013-04-11 18:27:59-- http://www.pw.edu.pl/
Resolving www.pw.edu.pl... 194.29.151.5
Connecting to www.pw.edu.pl|194.29.151.5|:80...
[
87.748803] BUG: unable to handle kernel paging request at e4de8b58
[
87.749016] IP: [<c1206d9f>] tcp_v4_rcv+0x35/0x5a2
[
87.749016] *pde = 00000000
[
87.749016] Thread overran stack, or stack corrupted
[
87.749016] Oops: 0000 [#1] SMP
...
Listing 5.1: Przykład interakcji po wstrzykni˛eciu bł˛edu.
Podczas drugiego uruchomienia wstrzykni˛ecie takiego samego bł˛edu poprzedzono
załadowaniem opracowanego modułu. Zapis interakcji z systemem został umieszczony na
listingu 5.2. Zastosowanie modułu sprawdzajacego
˛
spójność kodu spowodowało wykrycie i
naprawienie bł˛edu. W liniach 2-3 widoczny jest komunikat zgłaszany przez opracowany moduł
o wykryciu bł˛edu oraz odtworzeniu obrazu kodu jadra
˛
systemu z kopii zapasowej. Dzi˛eki
przeprowadzeniu operacji odtworzenia obrazu kodu możliwe było pobranie pliku przez sieć
programem wget.
Wnioski
Przedstawiona metoda jest najprostszym mechanizmem zapewniania spójności kodu jadra
˛
systemu operacyjnego i została zaproponowana w celu sprawdzenia możliwości implementacji
tego typu mechanizmu w systemie operacyjnym GNU/Linux oraz wyznaczenia dalszych
kierunków badań. Dzi˛eki okresowemu sprawdzaniu spójności obrazu kodu jadra
˛
możliwe
4
Statyczny obraz kodu jadra
˛ systemu operacyjnego nie zawiera w sobie kodu załadowanych modułów.
Funkcja tcp_v4_rcv wykorzystywana jest przez system GNU/Linux podczas odbierania pakietów sieci
TCP/IP.
5
124
1
2
3
4
5
6
7
8
9
10
root@debian-i386:~#
[
95.439364] FixModule - found code image integrity error at c1206d7a.
[
95.439924] FixModule - restoring from backup... success.
root@debian-i386:~# wget www.pw.edu.pl
--2013-05-11 18:31:48-- http://www.pw.edu.pl/
Resolving www.pw.edu.pl... 194.29.151.5
Connecting to www.pw.edu.pl|194.29.151.5|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: "index.html"
11
12
[ <=>
] 35,790
--.-K/s
in 0.02s
13
14
2013-05-11 18:31:49 (1.77 MB/s) - "index.html" saved [35790]
Listing 5.2: Przebieg interakcji po wstrzykni˛eciu bł˛edu i sprawdzeniu spójności kodu.
jest zwi˛ekszenie wartości współczynnika detekcji bł˛edów, a także tolerancji bł˛edów – niestety
określenie czy wykryty ta˛ metoda˛ bład
˛ był aktywowany jest niemożliwe. Zagadnienie to oraz
wyznaczenie optymalnej cz˛estości przeprowadzania sprawdzenia spójności wymaga dalszych
badań.
W przypadku docelowej implementacji, w celu zwi˛ekszenia niezawodności, należałoby
rozważyć uzupełnienie kopii zapasowej danych kodami korekcji bł˛edów i sumami kontrolnymi,
co pozwoliłoby na zapewnienie spójności także danych służacych
˛
do naprawy uszkodzonego
obrazu jadra.
˛
Istotnym rozszerzeniem zaproponowanej metody byłoby również uwzgl˛ednienie
w chronionym obszarze kodu ładownych modułów jadra
˛ systemu operacyjnego, a także kodu
aplikacji użytkownika.
5.6. Procedury naprawcze
Zapewnienie spójności kodu opisane w podrozdziale 5.5 jest skuteczne jedynie w przypadku
bł˛edów nieaktywowanych lub aktywowanych, ale maskowanych. Uzupełnieniem tej metody sa˛
procedury naprawcze, które pozwalaja˛ na obsług˛e sytuacji wyjatkowych
˛
wywołanych przez
bł˛edy. W podrozdziale opisane sa˛ oryginalne metody pozwalajace
˛ na osiagni˛
˛ ecie wi˛ekszego
poziomu niezawodności systemów komputerowych.
5.6.1. Metoda obsługi przerwań procesora dla kodu systemu operacyjnego
Analiza wyników eksperymentów zaburzania kodu, stosu i danych opisanych w sekcji 4.5.3
pozwala stwierdzić, że znaczna cz˛eść wstrzykni˛etych bł˛edów powoduje awarie niedozwolonego
dost˛epu do pami˛eci („Paging request failed”). Obserwacja ta jest podstawa˛ badań nad metodami
zwi˛ekszania niezawodności przedstawionymi w niniejszym podrozdziale.
125
W celu opracowania mechanizmu obsługi awarii „Paging request failed” poddano analizie
scenariusz jej wyst˛epowania. Składa si˛e on z nast˛epujacych
˛
etapów:
— aktywacja bł˛edu poprzez wykonanie zaburzonych instrukcji,
— odwołanie do niedost˛epnej pami˛eci,
— jednostka MMU zgłasza przerwanie sygnalizujace
˛ nieprawidłowy dost˛ep do pami˛eci,
— sterowanie przekazane jest do systemu operacyjnego, którego zadaniem jest obsługa
przerwania.
System operacyjny sprawdza, czy żadany
˛
adres docelowy jest dost˛epny dla zadania b˛edacego
˛
źródłem przerwania – sytuacja taka może mieć miejsce w przypadku dost˛epności danych
na partycji wymiany pami˛eci wirtualnej. W tym przypadku dane sa˛ pobierane z partycji
wymiany do pami˛eci RAM, obsługa przerwania jest zakończona, a zadanie jest wznawiane
od instrukcji, która spowodowała przerwanie. Jeżeli dane sa˛ niedost˛epne, zadanie zostaje
zakończone w trybie awaryjnym – powoduje to zgłoszenie awarii „Paging request failed” dla
zadań wykonywanych w trybie jadra
˛
systemu oraz „Segfault” dla zadań wykonywanych w
trybie nieuprzywilejowanym (aplikacje użytkownika).
Dzi˛eki przeprowadzonym badaniom nad liczba˛ wykonań zaburzonej instrukcji kodu oraz
odległościa˛ mi˛edzy zaburzana˛ instrukcja˛ i instrukcja,˛ której wykonanie wywołuje awari˛e
(rysunki 4.25 i 4.26) można stwierdzić, że znaczna grupa wstrzykni˛etych bł˛edów powoduje
awari˛e już przy wykonaniu pierwszej zaburzonej instrukcji.
Połaczenie
˛
tego faktu z
możliwościa˛ modyfikacji procedury obsługi przerwania zgłoszonego przez MMU jest podstawa˛
opracowania oryginalnej metody zwi˛ekszania niezawodności. Metoda ta polega na wykonaniu
sprawdzenia kodu, który zgłosił przerwanie, pod katem
˛
obecności bł˛edu i ewentualne podj˛ecie
procedury naprawczej.
Architektura
Przygotowane rozwiazanie
˛
jest modułem naprawczym, który podobnie jak moduł opisany
w podrozdziale 5.5 wykonuje kopi˛e statycznego kodu jadra
˛
w celu wykorzystania jej do
odtwarzania zaburzonego obrazu. Odtwarzanie jest wykonywane w momencie zgłoszenia
przerwania, które powodowałoby awari˛e.
Podstawowa wersja zaproponowanej metody
modyfikuje kod obsługi przerwania zgłoszonego przez MMU tak, aby realizował on algorytm
zilustrowany na rysunku 5.1. W domyślnej konfiguracji jadra
˛ nie jest możliwe modyfikowanie
procedur obsługi przerwań.
W celu przechwycenia sterowania przed zgłoszeniem awarii
konieczne było zmodyfikowanie kodu jadra
˛
w ten sposób, aby zgłoszenie awarii było
uzależnione od wywołania pewnej funkcji F zwracajacej
˛ wartość logiczna.˛ W zależności od
wartości zwracanej przez funkcj˛e F procedura obsługi przerwania zgłasza awari˛e (dla wyniku
TRUE funkcji F ) lub wznawia wykonanie zadania (dla wyniku FALSE). W implementacji
umieszczonej w kodzie jadra
˛ systemu operacyjnego funkcja F zawsze zwraca wartość TRUE,
co oznacza zachowanie niezmienione wzgl˛edem domyślnej implementacji.
126
W momencie załadowania opracowanego modułu naprawczego wywołania funkcji F
sa˛ przechwytywane przez moduł naprawczy z wykorzystaniem mechanizmu kprobes6 .
Mechanizm kprobes pozwala na przechwycenie wywołań określonej funkcji poprzez
podmienienie pierwszych instrukcji funkcji na instrukcj˛e skoku do procedur zdefiniowanych
przez użytkownika kprobes. W ten sposób możliwe jest przekazanie sterowania do modułu
naprawczego zamiast wykonania funkcji F .
Dodatkowym rozszerzeniem tej metody jest przekazywanie do funkcji F parametrów
kontekstu procedury obsługi przerwania – w szczególności wskaźnika do struktury danych
opisujacych
˛
zadanie, które jest źródłem przerwania. Struktura ta zawiera wartości rejestrów
procesora w momencie zgłoszenia przerwania przez zadanie, flagi uprzywilejowania zadania
(zadanie wykonywane w przestrzeni jadra
˛ systemu operacyjnego lub przestrzeni użytkownika)
oraz informacje o pami˛eci wykorzystywanej przez zadanie. W oryginalnej implementacji
funkcji F parametr ten nie jest wykorzystywany, jednak dane te sa˛ konieczne dla prawidłowego
działania modułu naprawczego.
Moduł naprawczy działa w nast˛epujacy
˛ sposób: w oparciu o informacje o stanie zadania
wykonywane jest sprawdzenie spójności kodu wykonywanej przez zadanie funkcji wzgl˛edem
referencyjnego obrazu. W przypadku wykrycia bł˛edu, moduł odtwarza prawidłowy kod funkcji
oraz wstrzykuje wartość FALSE jako wartość zwracana˛ przez przechwycona˛ funkcj˛e F , co
powoduje zablokowanie zgłoszenia awarii i wznowienie działania zadania w miejscu zgłoszenia
przerwania. Przepływ sterowania pomi˛edzy różnymi komponentami został przedstawiony na
rysunku 5.2.
W przypadku, gdy moduł naprawczy przeprowadzi procedur˛e odtworzenia kodu funkcji,
jednak instrukcja powodujaca
˛ zgłoszenie przerwania nie jest zaburzona˛ instrukcja,˛ wznowienie
działania spowoduje ponowne zgłoszenie przerwania – w tym przypadku moduł nie wykryje
zaburzenia kodu i zwróci wartość TRUE powodujac
˛ zgłoszenie awarii. Natomiast w przypadku,
gdy zaburzona instrukcja jest źródłem przerwania, przeprowadzenie naprawy umożliwia dalsze
wykonanie kodu zadania oraz unikni˛ecie awarii.
Po przeprowadzeniu analiz pozostałych awarii zgłaszanych przez system operacyjny
opisanych na stronie 82 zaobserwowano, że wiele z nich jest również wyzwalanych nieudana˛
obsługa˛ przerwania. Wykorzystano ten fakt do przygotowania drugiej wersji modułu, która
oprócz modyfikacji przerwań zgłoszonych przez MMU modyfikowała także procedury obsługi
pozostałych przerwań.
Konfiguracja eksperymentu
W celu zweryfikowania skuteczności zaproponowanej metody przygotowano eksperyment
identyczny z eksperymentem zaburzania kodu opisanym sekcji 4.5.3 dla każdego z opisanych w
6
http://sourceware.org/systemtap/kprobes/
127
ProceduraNobsługiN
przerwaniaNMMU
Tak
DomyśnaNprocedura
obsługiNprzerwania
WznowienieNdziałania
zadania
CzyNmożnaN
obsłużyć
przerwanie?
Naprawa
koduNzadania
Nie
SprawdzenieNspójności
koduNzadania
Tak
CzyNwykryto
błąd?
Nie
AwaryjneNzakończenie
działaniaNzadania
Rysunek 5.1: Algorytm obsługi przerwania
System
operacyjny
Zadanie
zgłoszenie przerwania
procesora
Moduł
naprawczy
przechwycenie obsługi
z użyciem kprobes
rezultat procedury
naprawczej
wznowienie lub
zakończenie zadania
Rysunek 5.2: Przepływ sterowania procedury obsługi przerwania
128
80
60
40
0
20
Testy %
PU + PS
NU + NS
Kod I
RM v.1 I
RM v.2 I
Kod II
RM v.1 II
RM v.2 II
Rysunek 5.3: Porównanie manifestacji bł˛edów dla różnych wersji modułu naprawczego
nim scenariuszy. Jedyna˛ różnica˛ było załadowanie modułów naprawczych przed wykonaniem
scenariusza testowego. Uzyskane wyniki obu wersji modułów zostały porównane z wynikami
uzyskanymi w sekcji 4.5.3.
Wyniki
Na rysunkach 5.3, 5.4, 5.5 i w tabeli 5.1 przyj˛eto nast˛epujace
˛ oznaczenie eksperymentów:
„Kod I/II” sa˛ to powtórzone wyniki eksperymentów opisanych w sekcji 4.5.3, „RM v.1
I/II” sa˛ to eksperymenty wykorzystujace
˛ moduł naprawczy realizujacy
˛ obsług˛e przerwań
nieprawidłowego dost˛epu do pami˛eci, natomiast „RM v.2 I/II” sa˛ to eksperymenty
wykorzystujace
˛ moduł naprawczy obsługujacy
˛ wszystkie rodzaje przerwań.
Odsetek zamanifestowanych bł˛edów dla przeprowadzonych eksperymentów został
przedstawiony na rysunku 5.3. Na rysunku 5.4 zobrazowany jest rozkład poszczególnych typów
manifestacji, przy czym wprowadzono nast˛epujace
˛ oznaczenia nowych typów manifestacji
bł˛edów:
— PR – prawidłowy wynik działania systemu, wykryto komunikat o przeprowadzeniu
procedury naprawczej przez moduł,
— NRT – nieprawidłowy wynik działania systemu, wykryto komunikat o wyzwoleniu
procedury naprawczej przez moduł, jednak zaburzenie nie zostało wykryte w obr˛ebie
funkcji zgłaszajacej
˛ przerwanie,
— NRD – nieprawidłowy wynik działania systemu, wykryto komunikat o przeprowadzeniu
procedury naprawczej przez moduł.
129
100
80
60
40
0
20
Testy %
PU
PS
PR
NU
NRD
NRT
NS
Kod I
RM v.1 I
RM v.2 I
Kod II
RM v.1 II
RM v.2 II
60
40
DU
DS
NDU
NDS
0
20
Testy %
80
100
Rysunek 5.4: Rozkład typów bł˛edów dla różnych wersji modułu naprawczego
Kod I
RM v.1 I
RM v.2 I
Kod II
RM v.1 II
RM v.2 II
Rysunek 5.5: Dost˛epność systemu operacyjnego dla różnych wersji modułu naprawczego
130
Komunikat %
Bad page state
Bad PC value
Null dereference
Null dereference 0
Paging request failed
Sched while atomic
EXT FS error
General protection
I/O error
Page alocation failure
Panic in interrupt
Panic - kill init
Segfault
Stack protector
Undefined instruction
Recovery Done
Recovery Triggered
Unclassified
Kod I
0,41
14,92
29,42
11,56
50,03
3,34
0
17,71
0
0,03
19,37
8,49
0,85
0,42
9,03
0
0
2,31
RM v.1 I
0,36
13,52
22,68
9,58
39,53
2,5
0,6
14,77
0,24
0,06
16,78
5,31
0,68
0,32
9,22
29,82
78
4,23
RM v.2 I
0,25
13,76
23,47
9,56
37,71
2,04
0,29
12,02
0,27
0
16,58
5,37
0,86
0,61
7,95
37
89,68
5,2
Kod II
0,31
13,73
29,12
11,18
49,51
4,33
0,68
24,74
0,35
0,02
40,45
4,55
0,88
0,42
8,96
0
0
3,87
RM v.1 II
0,26
16,98
27,28
10,99
42,05
3,85
0,85
24,26
0,55
0,07
41,57
2,66
1,4
0,57
11,21
14,72
69,14
7,76
RM v.2 II
0,13
18,26
28,58
12,26
44,66
3,88
0,93
21,18
0,75
0,05
38,82
3,21
1,32
0,36
6,72
17,84
59,84
10,6
Tabela 5.1: Udział komunikatów zgłaszanych przez system operacyjny dla różnych wersji
modułu naprawczego
Rysunek 5.5 obrazuje dost˛epność systemu dla każdej z przeprowadzonych kampanii. W
tabeli 5.1 przedstawiony jest rozkład typów zgłoszonych komunikatów wraz z uwzgl˛ednieniem
komunikatów „Recovery Triggered” i „Recovery Done” oznaczajacych
˛
odpowiednio
wyzwolenie procedury naprawczej oraz przeprowadzenie odtwarzania w trakcie działania tej
procedury.
Wnioski
Dzi˛eki zastosowaniu zaproponowanej metody zwi˛ekszono liczb˛e testów, w których uzyskano
prawidłowy wynik powierzonego zadania. Z wykresu 5.3 można odczytać, że w przypadku
obsługi przerwań zgłaszanych przez MMU zwi˛ekszono liczb˛e prawidłowych wyników o około
10 p.p., a dzi˛eki obsłudze pozostałych przerwań uzyskano dodatkowe 5 p.p. w przypadku
obu badanych scenariuszy eksperymentów. Wartość współczynnika detekcji bł˛edów Fd (patrz
2.5.2) można odczytać jako suma PR + NRD z wykresu 5.4, co z kolei umożliwia wyznaczenie
wartości współczynnika naprawy bł˛edów Fr na 46% oraz 55% dla obu modułów naprawczych
w scenariuszu I. Dla scenariusza II nie było możliwe określenie ilości komunikatów PR z
uwagi na charakter tego scenariusza (szerzej w 4.5.3). Zaproponowana metoda zwi˛ekszania
niezawodności nie gwarantuje przywrócenia prawidłowego stanu systemu operacyjnego,
niemniej zmniejszone jest zagrożenie wystapienia
˛
awarii uniemożliwiajacej
˛ prac˛e systemu.
Przywrócenie prawidłowej pracy systemu jest pewne wyłacznie
˛
w przypadku, gdy pierwsze
131
wykonanie zaburzonego kodu wyzwoli awari˛e.
Dodatkowo analiza rysunku 5.5 pozwala
stwierdzić, że zastosowanie modułu naprawczego nie wpłyn˛eło znaczaco
˛ na charakterystyk˛e
dost˛epności systemu w przypadku nieprawidłowej pracy systemu – wynika z tego, że moduł
naprawczy w równym stopniu zapobiegał awariom powodujacym
˛
niedost˛epność systemu, jak i
tym, które nie powodowały takiego efektu.
Warto zwrócić uwag˛e na fakt, że około 15% testów z zamanifestowanym bł˛edem
spowodowało wykrycie zaburzenia w funkcji, która była wykonywana w trakcie zgłoszenia
przerwania (wartość NRD na rysunku 5.4). Obsługa takiej sytuacji jest rozważana w 5.6.2.
Pewnym ograniczeniem jest obsługa przez moduł naprawczy tylko statycznego kodu
systemu operacyjnego – istnieje możliwość potencjalnego zwi˛ekszenia niezawodności poprzez
napraw˛e kodu ładowanych modułów systemu operacyjnego. Warto zaznaczyć, że procedury
obsługi przerwań moga˛ być wywołane zarówno przez kod systemu operacyjnego jak i aplikacje
użytkownika. Oznacza to, że jeżeli system operacyjny dysponowałby referencyjnym obrazem
kodu aplikacji użytkownika, to możliwe byłoby rozszerzenie zastosowania zaproponowanej
metody o ten obszar.
5.6.2. Algorytm brudnych zasobów
Główna˛ cecha˛ metody obsługi przerwań jest naprawa wyłacznie
˛
bł˛edów, które
spowodowały wywołanie przerwania procesora już przy pierwszym wykonaniu zaburzonej
instrukcji.
Nie pokrywa ona przypadków, kiedy wprowadzony bład
˛ skutkuje awaria˛ po
wykonaniu kilku instrukcji od aktywacji.
W celu zbadania takich przypadków moduły opisane w sekcji 5.6.1 zostały wyposażone w
funkcj˛e zrzutu obrazu kodu zaburzonej funkcji7 i obrazu jej kopii zapasowej. Uzyskane obrazy
zostały poddane deasemblacji8 i poddane analizie – wszystkie zamieszczone w niniejszej sekcji
przykłady kodu assembler zostały uzyskane w wyniku przeprowadzonych eksperymentów.
Na listingu 5.3 zamieszczony jest przykładowy zapis porównujacy
˛ zaburzony zestaw
instrukcji z oryginalnym. Zapis ten składa si˛e z kolejnych instrukcji procesora w j˛ezyku AT&T
Assembly Language dla architektury x869 . W liniach 1-4 przedstawione sa˛ instrukcje, które
były wspólne dla obu obrazów kodu przed zaburzeniem. W liniach 5-7 po lewej stronie znaku
„|” zapisane sa˛ instrukcje zaburzonego kodu, natomiast po prawej kodu oryginalnego. Linie
8-10 zawieraja˛ instrukcje, które były wspólne dla obu obrazów, a wyst˛epuja˛ po zaburzonym
fragmencie kodu.
Znakiem „>” w linii 6 oznaczona jest instrukcja, która spowodowała
zgłoszenie przerwania.
W przypadku zaburzenia kodu przedstawionego na listingu 5.3 zmieniony był 1 bit.
Instrukcje i ich argumenty w architekturze x86 kodowane sa˛ ciagami
˛
bajtów o zmiennej
7
8
9
Funkcja rozumiana jest tutaj jako symbol wymieniony w pliku /proc/kallsyms
Proces przekształcenia kodu binarnego na odpowiadajacy
˛ mu zestaw instrukcji j˛ezyka assembler.
http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
132
1
2
3
4
5
6
7
8
9
10
mov %edx,%ecx
mov %ebx,%eax
mov %esi,%edx
call *(%edi)
mov (%ebx),%edx
| mov 0x20(%ebx),%edx
> and %dh,(%ecx)
| xor %eax,%eax
rorb $0x1,-0x3d09f3b2(%ebx) | mov 0xc(%esi),%ecx
je 0x53
test %ecx,%ecx
mov $0x41,%edi
Listing 5.3: Deasemblacja instrukcji zaburzonej i oryginalnej
długości, co spowodowało, że zaburzenie argumentu funkcji mov w linii 5 wpłyn˛eło na zmian˛e
znaczenia kolejnych instrukcji w liniach 6-7. Z analizy zamieszczonego przykładu wynika,
że tuż przed zgłoszeniem przerwania procesor wykonał tylko zaburzona˛ instrukcj˛e mov z linii
5. W wyniku jej działania do rejestru %edx została załadowana wartość pami˛eci spod adresu
(%ebx) zamiast 0x20(%ebx). Naprawa˛ takiej sytuacji byłoby przywrócenie w procedurze
obsługi przerwań oryginalnego obrazu kodu oraz cofni˛ecie licznika instrukcji procesora do
instrukcji mov. Wynika to z faktu, że jedynym zmodyfikowanym rejestrem w zaburzonym
wykonaniu był rejestr %edx. Rejestr ten przy wykonaniu oryginalnego kodu zostałby na nowo
zapisany prawidłowa˛ wartościa.˛
Zaproponowana procedura naprawcza jest problemem odtworzenia prawidłowego stanu
wykonania zadania. Opracowana została formalna definicja tego problemu:
Definicja 5.6.1. Stan wykonania Si jest to kombinacja stanu pami˛eci Mi i stanu rejestrów
procesora Ri przed wykonaniem i-tej instrukcji przez procesor P . Przebiegiem wykonania
procesora P jest uporzadkowany
˛
zbiór stanów S = (S0 , S1 , ..., Sn ). Stanem równoważnym Wi
stanowi Si jest kombinacja stanu pami˛eci Mi0 i stanu rejestrów procesora Ri0 , gdzie w przebiegu
wykonania S stan Si może być zastapiony
˛
stanem Wi , a zasoby należace
˛ do Wi majace
˛ inne
wartości niż ich odpowiedniki należace
˛ do Si w S nie sa˛ odczytywane lub sa˛ nadpisane nowymi
wartościami.
Zaburzonym przebiegiem wykonania jest uporzadkowany
˛
zbiór stanów Sf
=
(S0 , S1 , ..., Si−1 , Qi , Qi+1 , ..., Qn ) gdzie stany Sj , (0 ≤ j < i) sa˛ stanami uzyskanymi
poprzez wykonanie niezaburzonych instrukcji, natomiast stany Qj , (i ≤ j ≤ n) sa˛ stanami
uzyskanymi poprzez wykonanie zaburzonych instrukcji. Problem odtwarzania jest to znalezienie
transformacji T (Qn , Sk ) stanu Qn do stanu równoważnego stanowi Sk , gdzie 0 ≤ k < i.
Wynikiem przeprowadzenia tak zdefiniowanej operacji odtwarzania jest przepływ wykonania
składajacy
˛
si˛e ze stanów S
=
(S0 , S1 , ..., Si−1 , Wi , Wi+i , ..., Wj−1 , Sj , Sj+1 , ..., Sn .
Transformacja stanu Qn do Sk może składać si˛e z nast˛epujacych
˛
operacji: zmiana wartości
133
licznika instrukcji procesora, zapis zawartości rejestrów oraz pami˛eci, wykonanie operacji
arytmetycznych.
Zdefiniowany problem odtwarzania jest pokrewny problemowi wstecznego wykonania
znanego z literatury.
Wsteczne wykonanie polega na możliwości odtworzenia każdego
stanu poprzedzajacego
˛
stan Si w celu inspekcji stanu pami˛eci w poszukiwaniu bł˛edów w
implementacji. Jednak standardowa architektura systemów komputerowych nie wspiera takiego
zastosowania. Istnieje wiele propozycji implementacji systemów pozwalajacych
˛
na wsteczne
wykonanie – np. programistyczne (patrz [4, 74, 22]) lub wykorzystujace
˛ maszyny wirtualne
(patrz [108]).
Kluczowym problemem przy wstecznym wykonaniu sa˛ instrukcje destrukcyjne, które
powoduja˛ niemożność odtworzenia poprzedniego stanu.
Instrukcje te modyfikuja˛ stan
pami˛eci lub rejestrów w ten sposób, że nie jest możliwe zastosowanie instrukcji odwrotnej
pozwalajacej
˛ cofnać
˛ efekt wykonania pierwotnej instrukcji. Instrukcje, dla których istnieja˛
instrukcje niwelujace
˛ ich efekt, sa˛ nazywane instrukcjami odwracalnymi. Przykładem instrukcji
destrukcyjnej jest funkcja mov, która nadpisuje adres lub rejestr pami˛eci. Instrukcja˛ odwracalna˛
jest instrukcja add, dla której instrukcja˛ odwrotna˛ jest instrukcja sub.
Warto również
zaznaczyć, że instrukcje architektury x86 moga˛ być destrukcyjne lub odwracalne w zależności
od argumentów. Przykładem jest instrukcja xor, która dla wywołania xor %eax, %eax10
jest destrukcyjna, natomiast przy wywołaniu xor %ebx, %eax jest odwracalna11 . Wsteczne
wykonanie w celu umożliwienia cofni˛ecia efektu działania instrukcji destrukcyjnej najcz˛eściej
stosuje metod˛e utworzenia kopii nadpisywanych danych.
W przypadku problemu odtwarzania zastosowanie wstecznego wykonania do wyznaczenia
transformacji T (Qn , Sk ) jest niemożliwe. Wynika to z nast˛epujacych
˛
przyczyn:
— wsteczne wykonanie w rozwiazaniach
˛
programistycznych polega na instrumentacji kodu,
a w przypadku wykonania zaburzonego kodu dane zawarte w instrumentacji byłyby
nieaktualne,
— wsteczne wykonanie oparte o maszyn˛e wirtualna˛ wymaga zastosowania systemu
gospodarza, który już nie podlegałby ochronie.
Konieczne jest wi˛ec opracowanie nowej metody uzyskania transformacji T (Qn , Sk ).
Przypadek zaburzenia kodu, który może być odtworzony poprzez wykonanie prawidłowego
kodu został poprzednio przedstawiony na listingu 5.3.
Natomiast przykład możliwości
odtworzenia zasobów na podstawie stanu pami˛eci i rejestrów procesora w chwili zgłoszenia
przerwania przedstawiony jest na listingu 5.4. Jest to szczególnie ciekawy przypadek, ponieważ
odtworzenie wartości zapisanej w rejestrze %edx możliwe jest na dwa sposoby: poprzez
ponowne wykonanie instrukcji z linii 2 lub skopiowanie zawartości %eax do rejestru %edx.
10
Instrukcja taka jest generowana przez kompilatory jako sposób wyzerowania wartości rejestru ze wzgl˛edu
na krótszy wygenerowany kod binarny niż instrukcja mov $0,%eax.
11
Instrukcja˛ niwelujac
˛ a˛ jej działanie jest ona sama ze wzgl˛edu na właściwości działania xor.
134
Przykład nierozwiazywalnego
˛
zaburzenia kodu przedstawiony jest na listingu 5.5, gdzie w linii
2 stracona jest bezpowrotnie zawartość rejestru %eax potrzebna do wykonania prawidłowego
kodu.
Poniżej przedstawiony jest algorytm brudnych zasobów – podstawa˛ jego działania jest
stwierdzenie, że możliwe jest przywrócenie stanu Si , o ile zasoby zapisane podczas wykonania
zaburzonych instrukcji zostana˛ nadpisane podczas wykonania prawidłowego kodu, lub moga˛
być odtworzone na podstawie stanu pami˛eci w chwili zgłoszenia przerwania. Algorytm ten
potrafi wyliczyć rozwiazania
˛
dla przykładu z listingu 5.3 oraz przykładu z listingu 5.4 (w wersji
wykorzystujacej
˛ zmian˛e wartości licznika instrukcji).
1
2
3
4
mov %eax,%edx
xor %eax,%edx | xor %eax,%eax
> testb $0x2,(%edx)
jne 0x1a
Listing 5.4: Deasemblacja instrukcji zaburzonej i oryginalnej
1
2
3
mov 0x50(%eax),%eax
mov 0x40194(%eax),%eax | mov 0x194(%eax),%eax
> movzwl 0x260(%eax),%esi
Listing 5.5: Deasemblacja instrukcji zaburzonej i oryginalnej
Zaprojektowanie algorytmu rozwiazuj
˛ acego
˛
problem odtwarzalności wymaga bazy wiedzy
o instrukcjach procesora. Potrzebne sa˛ informacje o tym, jakie zasoby sa˛ przez instrukcje
modyfikowane.
Obecna baza instrukcji została skonstruowana z instrukcji najcz˛eściej
wyst˛epujacych
˛
w instrukcjach wykonanych po zaburzonej instrukcji12 .
Składa si˛e ona z
nast˛epujacych
˛
instrukcji: mov, lea, add, sub, xor, or, and, test, cmp. Algorytm
brudnych zasobów przedstawiony jest na stronie 136.
Zasada działania algorytmu jest
nast˛epujaca:
˛ skanowany jest zbiór zaburzonych instrukcji w zakresie od pierwszej zaburzonej
instrukcji do instrukcji, która zgłosiła przerwanie i wyznaczany jest zbiór zasobów, które
zostały zapisane w wyniku wykonania tego kodu (linie 6-12) – zbiór ten nazwany jest zbiorem
brudnych zasobów. W przypadku napotkania instrukcji, której działanie nie jest opisane w bazie
instrukcji, działanie algorytmu jest przerywane (warunek w linii 7). Nast˛epnym etapem jest
zbadanie, czy w przypadku wykonania niezaburzonych instrukcji, brudne zasoby nie zostana˛
nadpisane nowymi wartościami z wykorzystaniem niezabrudzonych zasobów (linie 15-20) –
jeżeli tak, to taki zasób jest usuwany ze zbioru brudnych zasobów (linia 17). Skanowanie
jest przeprowadzane tak długo jak analizowane sa˛ instrukcje dost˛epne w bazie instrukcji.
12
Zbiór instrukcji wyznaczono na podstawie zrzutów zaburzonego kodu dost˛epnych w dziennikach
eksperymentów przeprowadzonych w 5.6.1.
135
Algorytm 5.1 Algorytm brudnych zasobów
Input: beforeCode, faultCode, originalCode, failInstr
Output: transform
1: if failInstr 6∈ faultCode then
2:
return ∅;
3: end if
4: dirtyResources ← ∅, remainingResources ← ∅;
5: ptrInstr ← head(faultCode);
6: while ptrInstr ∈ faultCode do
7:
if is_invalid(ptrInstr) then
8:
return ∅;
9:
end if
10:
add(dirtyResources, written_resources(ptrInstr);
11:
ptrInstr ← next(ptrInstr);
12: end while
13: remainingResources ← dirtyResources,
14: ptrInstr ← head(originalCode);
15: while ptrInstr ∈ originalCode ∧ is_valid(ptrInstr) do
16:
if read_resources(ptrInstr) 6∈ dirtyResources then
17:
remove(remainingResources, read_resources(ptrInstr);
18:
end if
19:
ptrInstr ← next(ptrInstr);
20: end while
21: if remainingResources == ∅ then return transform;
22: end if
23: ptrInstr ← tail(beforeCode);
24: while ptrInstr ∈ beforeCode ∧ is_valid(ptrInstr) do
25:
if read_resources(ptrInstr) 6∈ dirtyResources then
26:
remove(remainingResources, read_resources(ptrInstr);
27:
add(transform, ptrInstr);
28:
end if
29:
if remainingResources == ∅ then return transform
30:
end if
31:
add(dirtyResources, written_resources(ptrInstr);
32:
ptrInstr ← previous(ptrInstr);
33: end while
34: return ∅
136
Jeżeli po zakończeniu tego etapu zbiór brudnych zasobów jest pusty, to rozwiazaniem
˛
problemu odtwarzania dla danego przypadku jest ustawienie wskaźnika instrukcji na poczatek
˛
niezaburzonego kodu – w wyniku jego wykonania wszystkie brudne zasoby zostana˛ nadpisane
nowymi wartościami. Jeżeli zbiór brudnych zasobów nie jest pusty, to wykonywany jest
ostatni etap polegajacy
˛ na zbadaniu instrukcji wykonywanych przed miejscem zaburzenia w
analogiczny sposób, jak w poprzednim etapie z ta˛ różnica,˛ że licznik instrukcji jest „cofany”.
Jeżeli w tym etapie uda si˛e osiagn
˛ ać
˛ pusty zbiór zasobów, to rozwiazaniem
˛
jest ustawienie
licznika instrukcji na pierwsza˛ instrukcj˛e, od której prawidłowe wykonanie pozwoli nadpisać
wszystkie brudne zasoby. Algorytm kończy si˛e niepowodzeniem, jeżeli nie uda si˛e oczyścić
zbioru brudnych zasobów.
Niestety możliwości zbadania skuteczności zaproponowanego algorytmu w praktyce sa˛
ograniczone z uwagi na fakt, że podstawowa implementacja wymaga deasemblacji kodu
binarnego. Jest to utrudnione z poziomu jadra
˛ systemu operacyjnego z uwagi na brak bibliotek
realizujacych
˛
taka˛ funkcj˛e w kodzie systemu operacyjnego GNU/Linux13 .
W zwiazku
˛
z
tym ograniczeniem przygotowane zostały dwa scenariusze sprawdzajace
˛ możliwości adaptacji
zaproponowanej metody. Jeden z nich ma na celu sprawdzenie możliwości modyfikacji stanu
zadania zgłaszajacego
˛
przerwanie. Drugi służy oszacowaniu liczby awarii, które potencjalnie
moga˛ zostać obsłużone poprzez znalezienie rozwiazania
˛
problemu odtwarzania.
Weryfikacja eksperymentalna
W celu zbadania możliwości odtworzenia poprawnego stanu zadania w module naprawczym
opisanym w sekcji 5.6.1 zaimplementowano heurystyk˛e polegajac
˛ a˛ na nast˛epujacym
˛
scenariuszu: jeżeli po wykonaniu procedury naprawczej zadanie ponownie zgłasza przerwanie
(czyli instrukcja wywołujaca
˛ przerwanie nie jest pierwsza˛ zaburzona˛ instrukcja),
˛ to sprawdzane
jest, czy w odległości 6 bajtów przed adresem zgłaszanej instrukcji wyst˛epuje kod instrukcji
mov i w tym przypadku licznik instrukcji jest ustawiany na ten adres. Heurystyka ta polega
na obserwacji, iż wiele przypadków nieobsłużonych przez moduły naprawcze z sekcji 5.6.1 jest
podobna do przypadku przedstawionego na listingu 5.3, gdzie awaria jest zgłaszana w nast˛epnej
instrukcji po załadowaniu danych spod niewłaściwego adresu pami˛eci.
W wyniku przeprowadzenia eksperymentu (składajacego
˛
si˛e z 10 000 testów) identycznego
z eksperymentem opisanym w sekcji 5.6.1 uzyskano 56 przypadków, gdzie przedstawiona
heurystyka pozwoliła na zakończenie poprawnym wynikiem zadania zgłaszajacego
˛
przerwanie
w wyniku zaburzenia pami˛eci. Dzi˛eki temu eksperymentowi zostało potwierdzone, że możliwe
jest zwi˛ekszenie skuteczności modułu naprawczego poprzez zmian˛e wartości licznika instrukcji
w procedurze naprawczej.
13
Istnieje
inicjatywa
zintegrowania
deasemblera
w
http://www.phoronix.com/scan.php?page=news_item&px=MTA4MTI
137
kodzie
jadra
˛
GNU/Linux
–
Oszacowanie potencjalnej skuteczności
Oszacowanie liczby awarii, dla których istnieje rozwiazanie
˛
problemu odtwarzania zostało
przeprowadzone poprzez implementacj˛e algorytmu brudnych zasobów operujacego
˛
na
artefaktach eksperymentów opisanych w sekcji 5.6.1 dla eksperymentu „RM v.2 I”.
Jeżeli w dziennikach eksperymentu istnieja˛ zrzuty zaburzonego i oryginalnego kodu, to
podejmowana jest próba wyznaczenia transformacji T (Qn , Si ). Zaproponowany algorytm
znalazł rozwiazanie
˛
problemu odtwarzania w 28% eksperymentów, które zakończyły si˛e awaria˛
pomimo przeprowadzenia próby naprawy metoda˛ pułapek procesora (NRD ), co pozwoliłoby na
zwi˛ekszenie liczby prawidłowych wyników o około 3 p.p. (oznacza to zwi˛ekszenie wartości
współczynnika Fr z 55% do 63%). Należy jednak założyć, że w cz˛eści przypadków znalezienie
rozwiazania
˛
problemu odtwarzania nie zapobiegnie wystapieniu
˛
awarii (np.
zaburzony
kod został wykonany wi˛ecej niż raz i algorytm brudnych zasobów z tego powodu nie
wyznaczył pełnego zbioru zasobów nadpisanych przez zaburzony kod). Dodatkowo warto
zaznaczyć, że tylko w 2% przypadków algorytm brudnych zasobów wykrył zniszczenie zasobu
uniemożliwiajace
˛ odtworzenie prawidłowego stanu.
Dla 50% przypadków nie udało si˛e
znaleźć rozwiazania
˛
z powodu wykonania zaburzonej instrukcji nieuwzgl˛ednionej w bazie
instrukcji, a dla 10% przypadków niemożliwe było stwierdzenie, że wszystkie brudne zasoby
zostana˛ nadpisane w trakcie wznowionego wykonania. Pozostałe przypadki niepowodzeń były
zwiazane
˛
z wartościa˛ licznika instrukcji, która nie pozwalała na zastosowanie algorytmu (np. w
wyniku wykonania zaburzonego kodu został wykonany skok w losowe miejsce pami˛eci i nie
jest możliwe spekulowanie jaka sekwencja instrukcji została wykonana w wyniku zaburzenia).
Wnioski
Zdefiniowanie problemu odtwarzalności pozwoliło opracować oryginalny algorytm brudnych
zasobów, który może istotnie zwi˛ekszyć skuteczność obsługi bł˛edów po stronie systemu
operacyjnego, a także aplikacji użytkownika. Ograniczeniem przedstawionej implementacji jest
stosunkowo niewielka baza instrukcji – otwiera to potencjalny obszar badań automatycznego
wyznaczenia właściwości wszystkich instrukcji danej architektury ISA. Dodatkowym obszarem
badań może być modyfikacja algorytmu brudnych zasobów o inspekcj˛e stanu stosu (jako
potencjalnego miejsca przechowywania wartości rejestrów, które zostały nadpisane w
rejestrach) oraz możliwość zastosowania instrukcji odwrotnych dla wykonanych instrukcji w
celu odwrócenia efektów wykonania zaburzonych instrukcji. Efektywność algorytmu mogłaby
być potencjalnie zwi˛ekszona dzi˛eki meta-danym dotyczacym
˛
kodu, które moga˛ być dost˛epne
na poziomie kompilatora – np. czy wynik wykonania funkcji zależy wyłacznie
˛
od parametrów
wywołania.
138
5.6.3. Ochrona stosu
W podrozdziale 5.3 przedstawiono główne trudności w projektowaniu mechanizmów
ochrony danych przechowywanych na stosie, czyli duże zróżnicowanie typów danych oraz ich
duża zmienność w trakcie wykonania programów. Projektowanie mechanizmów zwi˛ekszania
ochrony stosu wymaga zapewnienia możliwości odtworzenia prawidłowych danych oraz
detekcji wystapienia
˛
bł˛edu. Należy również uwzgl˛ednić różne typy danych przechowywanych
na stosie.
Poniżej zaproponowana jest metoda ochrony wskaźników powrotu z funkcji
przechowywanych na stosie pozwalajaca
˛ na unikni˛ecie awarii.
Architektura
Zaproponowane rozwiazanie
˛
polega na zmodyfikowaniu kodu wywoływanych funkcji o
dodatkowe instrukcje w prologu oraz epilogu funkcji.
W prologu znalazłby si˛e kod
umieszczajacy
˛ na stosie dodatkowa˛ kopi˛e adresu powrotnego z funkcji otoczona˛ stałymi
markerami oraz rezerwujacy
˛ miejsce na wartość rejestru licznika instrukcji.
Natomiast
dodatkowe instrukcje w epilogu funkcji umieszczałyby przed skokiem pod adres powrotu z
instrukcji na stosie aktualna˛ wartość rejestru licznika instrukcji.
Na rysunku 5.6 przedstawiono schemat zawartości ramki stosu po wykonaniu prologu oraz
epilogu funkcji. W przypadku przekłamania adresu powrotnego z funkcji (pozycja oznaczona
liczba˛ 1 na schemacie) wykonywany jest skok pod nieprawidłowy adres. W przypadku,
gdy adres ten powoduje niedozwolony dost˛ep do pami˛eci, sterowanie jest przekazane do
analogicznego modułu, jak ten opisany w sekcji 5.6.1.
Moduł dokonuje analizy stosu
przerwanego zadania i na podstawie wartości umieszczonych na stosie podejmowana jest
decyzja o podj˛eciu próby naprawy. Zawartość stosu sprawdzana jest według nast˛epujacych
˛
kryteriów:
— obecność markerów umieszczonych na pozycjach 3 i 5,
— zawartość pozycji 2 jest różna od 0,
— wartości na pozycjach 1 i 4 różnia˛ si˛e od siebie.
Jeżeli wszystkie powyższe kryteria sa˛ spełnione, to podejmowana jest próba naprawy
polegajaca
˛ na skopiowaniu wartości przechowywanej w pozycji 4 na pozycj˛e 1 oraz ustawienie
wartości rejestru instrukcji na wartość przechowywana˛ w pozycji 2. W ten sposób nast˛epuje
odtworzenie prawidłowej wartości wskaźnika powrotu ze stosu.
Implementacja opisanego schematu wymaga wsparcia ze strony kompilatora w celu
wygenerowania dodatkowych instrukcji prologu i epilogu funkcji oraz odpowiednim
rozmieszczeniu pozostałych wartości na stosie zwiazanych
˛
normalna˛ praca˛ systemu. Niemniej
wiele kompilatorów posiada funkcj˛e generowania kodu dla mechanizmu stack protector14 , który
podobnie jak zaproponowane rozwiazanie
˛
wymaga dodatkowego kodu w prologu i epilogu
14
http://msdn.microsoft.com/en-us/library/8dbf701c(VS.80).aspx
139
Stackgpointer
1
Returngaddress
1
Returngaddress
2
0x00000000
2
Lastginstructiongpointer
3
Constantgmarker
3
Constantgmarker
4
Returngaddressg(copy)
4
Returngaddressg(copy)
5
Constantgmarker
5
Constantgmarker
Stackgpointer
a)gStangstosugpogwykonaniugprologugfunkcji
b)gStangstosugpogwykonaniugepilogugfunkcji
Rysunek 5.6: Schemat ramki stosu z ochrona˛ wskaźnika powrotu z funkcji
funkcji oraz wymaga alokacji dodatkowej pami˛eci na stosie przed wykonaniem właściwego
kodu funkcji.
Eksperymentalna weryfikacja
W celu weryfikacji działania opracowanej metody opracowany został moduł realizujacy
˛ opisana˛
procedur˛e naprawcza˛ oraz przygotowany został kod programu, który realizuje dla wybranej
funkcji opracowany sposób odłożenia dodatkowych wartości na stosie. Dodatkowo opracowana
funkcja wprowadza zaburzenie do adresu powrotu z funkcji w celu weryfikacji skuteczności
procedury naprawczej. Kod opracowanej funkcji zamieszczony jest na listingu 5.6. W liniach
4-8 realizowany jest epilog funkcji według opisanych założeń. W liniach 9-10 nast˛epuje
nadpisanie prawidłowej wartości adresu powrotu z funkcji.
Natomiast w liniach 11-14
realizowany jest epilog funkcji.
1
2
3
void test()
{
asm(
"push $0x0"
"push $0xfefefefe"
"mov 0x8(%ebp),%eax"
"push $eax"
"push $0xfefefefe"
"mov $0x42,%eax"
"mov %eax,0x4(%ebp)"
"add $16,%esp"
"call get_eip"
"get_eip:"
"pop %eax"
4
5
6
7
8
9
10
11
12
13
14
);
15
16
}
Listing 5.6: Implementacja kodu funkcji weryfikujacej
˛
skuteczność mechanizmu ochrony
wskaźnika powrotu z instrukcji
Weryfikacja działania została przeprowadzona poprzez dwukrotne uruchomienie programu
wywołujacego
˛
funkcj˛e przedstawiona˛ na listingu 5.6 – bez zastosowania modułu naprawczego,
140
co spowodowało zakończenie działania programu z komunikatem „Segfault”. Natomiast przy
drugim uruchomieniu aplikacji w systemie załadowany był moduł naprawczy, dzi˛eki czemu
aplikacja wykonana została bez zgłoszenia awarii.
Wnioski
Zaproponowana metoda służy ochronie wskaźnika adresu powrotu z funkcji. Jej architektura
jest zbliżona do mechanizmu stack protector dost˛epnego we współczesnych kompilatorach.
Podobne rozwiazanie
˛
zostało zaprezentowane w [35], które różni si˛e nast˛epujaco
˛
od
przedstawionego rozwiazania:
˛
na stosie wskaźnik powrotu instrukcji jest odkładany trzykrotnie,
a wybranie właściwego adresu powrotu odbywa si˛e poprzez głosowanie. Rozwiazanie
˛
to
może być skuteczniejsze szczególnie w przypadku przekłamań niskich bitów w adresie
skoku (ponieważ takie przekłamanie może nie spowodować zgłoszenia przerwania), jednak
rozwiazanie
˛
zaproponowane w niniejszej rozprawie wykorzystuje możliwość inspekcji
stanu zadania w momencie pojawienia si˛e przerwania, co otwiera potencjalne nowe
obszary badań.
W szczególności ciekawym rozszerzeniem obecnego rozwiazania
˛
może
być wzbogacanie wykorzystywanych struktur danych o redundantne informacje, które sa˛
wykorzystywane jedynie w momencie wystapienia
˛
przerwania.
W takim scenariuszu
narzut czasowy jest zwiazany
˛
wyłacznie
˛
z wyliczeniem dodatkowych danych służacych
˛
zwi˛ekszeniu niezawodności, natomiast ich wykorzystanie odbywa si˛e tylko w momencie
wykrycia nieprawidłowości. Oba rozwiazania
˛
stanowia˛ interesujace
˛ podejścia, które należy
porównać pod katem
˛
narzutu czasowego oraz skuteczności, jednak przeprowadzenie takiego
eksperymentu wymaga opracowania zmian w kompilatorach i stanowi to obszar dalszych badań
planowanych przez autora.
Warto zaznaczyć, że inne typy danych przechowywanych na stosie wymagaja˛ projektowania
innego typu mechanizmów zwi˛ekszajacych
˛
niezawodność.
Przykładowo w przypadku
odkładania na stos tymczasowych wartości rejestrów możliwe jest umieszczanie na stosie
kilku kopii tych samych danych w celu późniejszego przeprowadzenia głosowania, jednak dla
parametrów wywołań funkcji takie działanie jest już nieakceptowalne. Wynika to z faktu, iż
parametr wywołania funkcji może być swobodnie modyfikowany przez wywoływana˛ funkcj˛e –
musiałaby ona podczas zapisu aktualizować wszystkie kopie zapisywanego parametru. Oznacza
to konieczność wymuszenia spójnego zachowania we wszystkich funkcjach w odróżnieniu od
zaproponowanych mechanizmów, które moga˛ być zastosowane tylko w wybranych procedurach
bez zerwania binarnej kompatybilności z pozostałymi procedurami.
5.6.4. Mechanizmy ochrony danych
W 5.3 zaznaczono, że mechanizmy ochrony danych najcz˛eściej stosowane sa˛ do
danych zewn˛etrznych, które zostały przekazane do systemu operacyjnego – ich weryfikacja
141
przeprowadzana jest na podstawie wyliczania sum kontrolnych. Oczywistym rozszerzeniem
byłoby wzbogacenie struktur danych wyst˛epujacych
˛
w jadrze
˛
systemu operacyjnego o
dodatkowe pola pozwalajace
˛ na weryfikacj˛e spójności danych. Niemniej rozwiazanie
˛
takie
rodzi nast˛epujace
˛ pytania: czy konieczne jest obj˛ecie wszystkich struktur danych mechanizmem
weryfikacji i czy narzut czasowy zwiazany
˛
z tym zastosowaniem b˛edzie akceptowalny.
Dodatkowa˛ trudnościa˛ jest adaptacja takiego podejścia do tak dużej bazy źródeł jak jadro
˛
systemu GNU/Linux.
W literaturze można znaleźć badania, które w przyszłości moga˛
pomóc rozwiazać
˛
wymienione problemy. Według autora szczególnie interesujace
˛ prace w tej
dziedzinie to [15] oraz [17].
W [15] zaprezentowana została technika polegajaca
˛ na wykorzystaniu programowania
aspektowego
do
zwi˛ekszenia
opracowanego w j˛ezyku C++.
niezawodności
wbudowanego
systemu
operacyjnego
Programowanie aspektowe jest to implementacja idei
separacji zadań realizowanych przez kod poprzez podzielenie programu na niezwiazane
˛
ze
soba˛ funkcjonalnie moduły. Przykładowo pewien program może zostać wzbogacony o funkcj˛e
pomiaru czasu wykonania wskazanych funkcji poprzez zdefiniowanie aspektu15 , który na
etapie kompilacji jest wplatany (weaved) w wynikowy kod programu. Podstawa˛ działania
mechanizmu opisanego w [15] jest wzbogacenie klas j˛ezyka C++ o dodatkowe pola zawierajace
˛
kody korekcyjne dla pól oryginalnie zdefiniowanych w klasach. Dzi˛eki zastosowaniu aspektów
dost˛ep do danych jest sprawdzany przed wywołaniem każdej z metod publicznych obiektu,
natomiast pola zawierajace
˛ kody korekcyjne sa˛ aktualizowane po zakończeniu wykonania
metody. Rozwiazanie
˛
to jest bardzo perspektywiczne z uwagi na możliwość wzbogacania tylko
cz˛eści struktur danych o funkcje niezawodnościowe stosownie do potrzeb i narzutu na czas
wykonania.
Natomiast w [17] zaprezentowano niestandardowy mechanizm służacy
˛ do ochrony przed
bł˛edami programistycznymi polegajacy
˛ na śledzeniu przez kompilator wskaźników do danych
(zarówno danych składowanych na stosie oraz danych alokowanych). Z każdym wykrytym
wskaźnikiem p powiazane
˛
sa˛ nast˛epujace
˛ informacje: a – adres przydzielonej pami˛eci;
s – rozmiar przydzielonego obszaru.
Nast˛epnie wszelkie operacje dost˛epu do danych z
użyciem p powoduja˛ wygenerowanie dodatkowego kodu wykonujacego
˛
sprawdzenie, czy
dost˛ep do danych dotyczy pami˛eci z zakresu adresów pomi˛edzy a i a + s. Jeżeli dost˛ep
odbywa si˛e w wyznaczonym zakresie, to jest to prawidłowy dost˛ep do danych, natomiast
w przeciwnym wypadku wykrywany jest bład
˛ dost˛epu do pami˛eci. Zaproponowana przez
autorów metoda obsługi takiej sytuacji polega na porzuceniu operacji dost˛epu do wskazanej
pami˛eci i wprowadzeniu dla wskaźnika p wirtualnej przestrzeni danych, gdzie nieprawidłowy
dost˛ep do pami˛eci jest przekierowany do pami˛eci przydzielonej specjalnie dla wskaźnika
15
Aspekt jest to kombinacja punktu przeci˛ecia (ang. pointcut) oraz rady (ang. advice). Punkt przeci˛ecia
definiuje okoliczności, w których ma być wykonana rada, czyli dodatkowa czynność do wykonania przez program.
142
p.
Mechanizm ten powoduje, że odczytanie pami˛eci spod nieprawidłowego adresu nie
spowoduje odczytania losowej zawartości pami˛eci (wirtualna pami˛eć jest inicjalizowana
wartościa˛ 0), a zapis nie zaburzy innych danych przechowywanych w systemie. Mechanizm
ten jest szczególnie interesujacy,
˛ ponieważ pozwala na unikni˛ecie awarii poprzez stworzenie
dla nieprawidłowego dost˛epu do pami˛eci środowiska typu sandbox. Dodatkowym atutem
tego rozwiazania
˛
jest automatyczne wykrywanie danych, które moga˛ być obj˛ete ochrona.˛
Rozwiazanie
˛
to było projektowane z myśla˛ o bł˛edach programistycznych, jednak potencjalnie
może ono również wpłynać
˛ na popraw˛e niezawodności systemu w przypadku bł˛edów sprz˛etu.
Przykładowym scenariuszem byłaby obsługa przekłamania w danych zawierajacych
˛
adresy
kolejnych elementów listowej struktury danych.
Zastosowanie opisanego mechanizmu
zapobiegłoby odwołaniu do nieprawidłowej pami˛eci, kosztem braku dost˛epu do elementów
listy znajdujacych
˛
si˛e za zaburzonym w˛ezłem – unikni˛eto by awarii, a mechanizmy wyższych
warstw mogłyby podjać
˛ decyzj˛e o ewentualnym zastosowaniu innych technik odtwarzania.
Opisane mechanizmy ochrony danych stanowia˛ interesujacy
˛ nurt w dziedzinie badań nad
niezawodnościa.˛ Według autora kierunek pozwalajacy
˛ na automatyczne wzbogacanie danych
o funkcje niezawodnościowe i zmniejszanie prawdopodobieństwa awarii systemu stanowi
podstaw˛e skuteczności mechanizmów wyższego poziomu pozwalajacych
˛
na tolerowanie
bł˛ednych danych.
5.7. Zastosowanie QEFI do optymalizacji niezawodności
Platforma QEFI przedstawiona w rozdziale 3 umożliwia optymalizacj˛e mechanizmów
zwi˛ekszania niezawodności. Wprowadzanie mechanizmów tego typu wia˛że si˛e z narzutem
na czas wykonania oraz pami˛eć. Dodatkowo każdy z mechanizmów może charakteryzować
si˛e innym poziomem skuteczności przy obsłudze bł˛edów. Zastosowanie QEFI pozwala na
przeprowadzenie badań umożliwiajacych
˛
określić parametry tych mechanizmów w wybranych
scenariuszach.
W
5.6.1
przedstawiono
eksperymenty,
które
pozwoliły
zaproponowanego przez autora mechanizmu obsługi przerwań.
ocenić
skuteczność
O ile w przypadku tego
mechanizmu koszt narzutu na czas wykonania zwiazany
˛
jest jedynie z podj˛eciem działań
naprawczych, a koszt pami˛eci to przede wszystkim zapasowy obraz kodu jadra
˛
systemu
operacyjnego, to w przypadku próby zastosowań mechanizmów opisanych w 5.6.3 i 5.6.4
trudno jest ocenić narzut tych mechanizmów bez przeprowadzenia eksperymentów. W tych
przypadkach szczególnie skuteczny może okazać si˛e mechanizm nieinwazyjnego śledzenia
wykonania opisany w 3.4.3, dzi˛eki któremu możliwe jest wyznaczenie dokładnej liczby
wykonań wskazanego kodu i na tej podstawie oszacowanie narzutu badanego mechanizmu.
Dodatkowo dzi˛eki zastosowaniu QEFI możliwe jest badanie w sposób automatyczny również
143
wpływu innych parametrów na niezawodność oprogramowania – przykładowo: flagi kompilacji
(np. poziom optymalizacji kodu wykonywalnego), czy dost˛epna ilość wolnej pami˛eci (co może
mieć wpływ na sposób działania mechanizmów alokacji).
QEFI pozwala na ewaluacj˛e nie tylko mechanizmów ukierunkowanych na kod, stos,
czy dane systemu operacyjnego, ale również na poprawność działania sterowników
w obliczu wystapienia
˛
bł˛edów w urzadzeniach
˛
wejścia/wyjścia.
Jest to szczególnie
praktyczne zastosowanie QEFI, ponieważ badanie tego typu oprogramowania jest trudne
w zwiazku
˛
z koniecznościa˛ dysponowania testowanym urzadzeniem,
˛
w którym możliwe
jest symulowanie bł˛edów lub jego emulowanym odpowiednikiem. W przypadku istnienia
emulowanych odpowiedników opracowywane sa˛ rozwiazania
˛
pozwalajace
˛ na implementacj˛e
testów jednostkowych z wykorzystaniem QEMU16 – dzi˛eki zastosowaniu mechanizmów
wstrzykiwania bł˛edów w QEFI możliwe byłoby wzbogacenie tego typu testów o weryfikacje
działania sterowników w przypadku anomalii (tak jak zostało to przedstawione w 4.5.1).
5.8. Podsumowanie
W rozdziale przedstawiono przekrój rozwiazań
˛
służacych
˛
zwi˛ekszaniu niezawodności.
Zaproponowane zostały autorskie mechanizmy: metoda obsługi przerwań, algorytm brudnych
zasobów oraz metoda ochrony stosu. Dodatkowo przeprowadzono dyskusj˛e nad zastosowaniem
QEFI do optymalizacji niezawodności.
Skuteczność opracowanej oryginalnej metody obsługi pułapek procesora (szerzej w 5.6.1)
zweryfikowano z zastosowaniem metodologi eksperymentów opisanej w rozdziale 3. Dzi˛eki
jej implementacji możliwe było zwi˛ekszenie liczby prawidłowych wyników testowanego
systemu o około 15 p.p.. Na podstawie dalszej analizy sytuacji wyjatkowych
˛
zdefiniowany
został problem odtwarzalności i przedstawiony został algorytm brudnych zasobów jako jego
rozwiazanie.
˛
Symulacja działania algorytmu pozwoliła na oszacowanie jego potencjalnej
skuteczności – algorytm znalazł rozwiazanie
˛
problemu odtwarzalności dla około 7% sytuacji
awaryjnych nieobsłużonych metoda˛ obsługi przerwań, co potencjalnie pozwoliłoby zwi˛ekszyć
udział prawidłowych wyników testów o około 3 p.p..
Warto zaznaczyć, że skuteczność
algorytmu może być zwi˛ekszona poprzez wzbogacenie bazy instrukcji oraz rozwini˛ecie technik
odtwarzania danych ze stosu oraz z zastosowaniem odwrotnych operacji arytmetycznych.
Przedstawiona technika jest odmiana˛ technik backward recovery, gdzie nast˛epuje próba
odwrócenia skutków niepożadanych
˛
zmian w systemie b˛edacych
˛
wynikiem zaburzeń.
Zastosowanie opracowanej metody ma na celu unikni˛ecie awarii, jednak wynik uzyskany po
wykonaniu naprawionego kodu powinien być opatrzony informacja˛ o potencjalnym zaburzeniu,
16
http://people.igalia.com/berto/files/qemu-linuxcon-slides.pdf
144
a także mechanizmy niezawodnościowe wyższego poziomu powinny zapewnić tolerowanie
potencjalnie wygenerowanych nieprawidłowych danych.
W 5.6.3 zaprezentowano metod˛e ochrony stosu poprzez umieszczanie dodatkowych danych
w nieaktywnej cz˛eści stosu (za wskaźnikiem wierzchołka stosu), które sa˛ wykorzystywane
w sytuacji zgłoszenia awarii spowodowanej przekłamaniem adresu powrotu z instrukcji.
Natomiast w 5.6.4 opisano dwie interesujace
˛ metody zwi˛ekszania niezawodności obsługi
danych znane z literatury.
Celem tych przykładów była ilustracja potencjalnych zysków
wynikajacych
˛
z zaangażowania kompilatora w projektowanie mechanizmów zwi˛ekszania
niezawodności.
W ostatniej cz˛eści rozdziału przedstawiono zastosowanie QEFI do optymalizacji
niezawodności poprzez możliwość badania skuteczności oraz kosztów poszczególnych
mechanizmów.
145
6. Podsumowanie
W rozprawie przedstawiono oryginalna˛ metodyk˛e oceny niezawodności systemu
komputerowego z zastosowaniem emulacji wraz z implementacja˛ specjalistycznego narz˛edzia
QEFI. Teza oraz cel rozprawy sformułowane sa˛ w rozdziale 1. Dzi˛eki opracowanej metodyce
stworzono możliwość oceny niezawodności oprogramowania systemów operacyjnych, która
jak przedstawiono w 1.1, według autora jest niedostatecznie opisana w literaturze. QEFI może
być zastosowane do optymalizacji mechanizmów detekcji i obsługi (tolerowania) bł˛edów.
W rozdziale 2 przedstawiono model rozważanego systemu komputerowego i
oprogramowania, przeglad
˛ literatury dotyczacy
˛
dziedziny badania niezawodności oraz
wprowadzono miary wykorzystywane w dalszej cz˛eści rozprawy.
Poniżej zestawiono najważniejsze osiagni˛
˛ ecia autora:
Opracowanie metodyki symulacji bł˛edów z zastosowaniem emulacji
Na podstawie analizy dost˛epnych mechanizmów emulacji systemów komputerowych
(patrz 3.2) i potencjalnych zysków, wynikajacych
˛
z ich użycia (patrz 3.3), opracowana
została oryginalna metodyka przeprowadzania eksperymentów (patrz 3.4.5) oraz szereg
algorytmów umożliwiajacych
˛
jej realizacj˛e. Metodyka została zaimplementowana w postaci
platformy QEFI wykorzystujacej
˛
emulator systemu komputerowego QEMU (patrz 3.4.6).
Zaproponowana metodyka umożliwia istotne udoskonalenia wzgl˛edem rozwiazań
˛
znanych
z literatury: możliwość badania niezawodności oprogramowania systemów operacyjnych
oraz możliwość zastosowania nowych modeli bł˛edów.
Istotna˛ funkcja˛ opracowanego
rozwiazania
˛
jest funkcja nieinwazyjnego śledzenia emulowanego systemu (patrz 3.4.3).
Metodyka została opracowana uwzgl˛edniajac
˛ możliwość rozpraszania, co znaczaco
˛ skróciło
czas przeprowadzania eksperymentów.
Opracowanie scenariuszy testowych do badania efektów bł˛edów w systemach
operacyjnych
Opracowane zostały oryginalne scenariusze testowe wykorzystane do oceny niezawodności
systemów operacyjnych w szeregu eksperymentów przeprowadzonych z użyciem QEFI.
Dzi˛eki opracowanej metodyce możliwe było przeprowadzenie eksperymentów pozwalajacych
˛
na porównanie wrażliwości na bł˛edy pami˛eci wielu architektur sprz˛etowych na poziomie
ISA (patrz 4.3), w których wykazano, że niektóre architektury w sposób naturalny sa˛
mniej podatne na bł˛edy przekłamań pami˛eci. Możliwe było również porównanie różnych
147
systemów operacyjnych (patrz 4.4), w którym stwierdzono różna˛ podatność na bł˛edy i inny
poziom szczegółowości zgłaszanych komunikatów dla każdego z systemów. Przeprowadzenie
porównania architektur sprz˛etowych oraz systemów operacyjnych, było możliwe dzi˛eki
opracowaniu symulowania bł˛edów na poziomie emulatora, co pozwoliło na unikni˛ecie
modyfikacji badanego oprogramowania. Dodatkowo mechanizmy zaprojektowane w ramach
metodyki pozwoliły na zaburzanie danych przesyłanych z emulowanych urzadzeń
˛
(patrz 4.5.1),
a także wstrzykiwanie bł˛edów w różne typy danych systemu operacyjnego (patrz 4.5.2, 4.5.3):
kod, stos, dane alokowane, dane tylko do odczytu, dane statyczne. Dzi˛eki zastosowaniu
profilowania zwi˛ekszono efektywność przeprowadzonych testów, zidentyfikowano krytyczne
komponenty, zbadano opóźnienie awarii bł˛edów w kodzie systemu operacyjnego oraz
wyznaczono wartości współczynnika naturalnej odporności na bł˛edy.
Opracowanie oryginalnych mechanizmów zwi˛ekszania niezawodności
Na podstawie wyników uzyskanych w przeprowadzonych eksperymentach opracowane zostały
oryginalne mechanizmy zwi˛ekszania niezawodności: metoda obsługi przerwań (patrz 5.6.1)
oraz algorytm brudnych zasobów (patrz 5.6.2), który stanowi rozwiazanie
˛
zdefiniowanego
problemu odtwarzalności. Metoda obsługi przerwań została zweryfikowana wykorzystujac
˛
QEFI, natomiast algorytm brudnych zasobów został zweryfikowany poprzez symulacj˛e
(z uwagi na trudności w implementacji deasemblera w jadrze
˛
systemu operacyjnego).
W przeprowadzonym eksperymencie zaproponowane mechanizmy moga˛ zwi˛ekszyć udział
prawidłowych wyników o około 15 p.p.
(metoda obsługi przerwań) oraz potencjalnie o
dodatkowe 3 p.p. (algorytm brudnych zasobów). Opracowana został również metoda ochrony
stosu (patrz 5.6.3) poprzez umieszczanie dodatkowych danych w nieaktywnej cz˛eści stosu.
Opracowane mechanizmy wymagaja˛ minimalnych zmian w jadrze
˛
systemu operacyjnego
GNU/Linux i wykorzystuja˛ mechanizm kprobes do wzbogacenia systemu o dodatkowe funkcje
obsługi bł˛edów.
Całość przeprowadzonych badań służy możliwości wykorzystania symulacji bł˛edów
w środowisku emulatora w celu zwi˛ekszania niezawodności urzadzeń
˛
konsumenckich.
Szczególnie istotnym zagadnieniem jest opracowanie scenariuszy testowych adekwatnych
do przyszłych zastosowań badanego oprogramowania.
Autor przedstawił możliwie
szeroki aspekt wykorzystania QEFI od porównywania różnych konfiguracji systemów
komputerowych po szczegółowa˛ analiz˛e wybranego systemu komputerowego.
Przyj˛ete
podejście pozwoliło na opracowanie mechanizmów zwi˛ekszania niezawodności dedykowanych
badanej platformie.
QEFI umożliwiło również weryfikacj˛e opracowanych mechanizmów
oraz ocen˛e ich skuteczności – oznacza to, że QEFI może być zastosowane do optymalizacji
mechanizmów niezawodności, gdy ich zastosowanie wia˛że si˛e z kosztem czasu wykonania
lub dodatkowej pami˛eci.
Przeprowadzone badania przedstawiaja˛ użyteczność emulacji
148
systemu komputerowych w badaniu niezawodności oprogramowania systemów operacyjnych,
co stanowi dowód tezy sformułowanej w 1.3.
6.1. Spostrzeżenia i wnioski
QEFI jest elastycznym środowiskiem symulacji bł˛edów. Dzi˛eki zastosowaniu emulacji
możliwe jest badanie efektów nowych modeli bł˛edów oraz porównanie podatności na bł˛edy
różnych konfiguracji systemów komputerowych, co pozwoliło na uzupełnienie stanu wiedzy o
nowe fakty podsumowane poniżej.
Badania nad różnymi architekturami sprz˛etowymi pozwoliły określić, że architektury różnia˛
si˛e podatnościa˛ na bł˛edy.
Niemniej dla wszystkich architektur istnieja˛ rejony pami˛eci o
wyższym stopniu podatności na przekłamania pami˛eci. Oznacza to, że niezawodność systemu
może być zwi˛ekszona poprzez zastosowanie pami˛eci ECC tylko dla cz˛eści dost˛epnej pami˛eci.
Niemniej oprogramowanie systemu operacyjnego w pierwszej kolejności powinno umieszczać
w tych rejonach pami˛eci dane wrażliwe – w szczególności kod systemu operacyjnego, stos, czy
dane krytyczne aplikacji użytkownika.
Porównanie systemów operacyjnych pozwoliło wykryć, że systemy operacyjne działajace
˛
na tej samej platformie sprz˛etowej cechuje inny poziom manifestacji bł˛edów oraz
szczegółowości komunikatów. W przypadku systemu Minix zebranie informacji o skuteczności
mechanizmów zwi˛ekszania niezawodności wbudowanych w ten system było niemożliwe z
uwagi na trudności konfiguracyjne (brak wypisywania na konsol˛e operatora informacji jadra
˛
systemu o podj˛etych działaniach naprawczych – np. restart usług systemu). System oparty
na jadrze
˛
kFreeBSD okazał si˛e najbardziej podatny na bł˛edy, jednak poziom szczegółowości
komunikatów był najmniejszy – oznacza to, że jakość implementacji mechanizmów obsługi
sytuacji wyjatkowych
˛
w systemie operacyjnym potrafi si˛e zasadniczo różnić.
Eksperymenty ukierunkowane na zaburzanie pracy działania urzadzeń
˛
wejścia/wyjścia
na różnych poziomach abstrakcji stanowia˛ ilustracj˛e elastyczności QEFI. Pozwoliły określić
poziom podatności na bł˛edy różnych scenariuszy wykorzystywania urzadzeń.
˛
Istotne cechy
QEFI wzgl˛edem rozwiazań
˛
znanych z literatury to brak konieczności modyfikacji badanego
oprogramowania oraz możliwość symulowania bł˛edów zwiazanych
˛
ze zgłaszaniem przerwań
przez urzadzenia.
˛
Metoda nieinwazyjnego śledzenia zaimplementowana w QEFI umożliwiła profilowanie
wykonywanego oprogramowania – dzi˛eki temu opracowane zostały eksperymenty zaburzania
wyłacznie
˛
wykonywanego kodu, danych przechowywanych na stosie oraz danych alokowanych
w systemie operacyjnym. Zastosowanie tej techniki skutkowało zwi˛ekszeniem efektywności
przeprowadzanych eksperymentów. Badania pozwoliły stwierdzić, że najbardziej podatny na
bł˛edy jest kod oprogramowania systemu operacyjnego, a 31-42% symulowanych bł˛edów nie
149
spowodowało manifestacji pomimo aktywacji bł˛edu. Niemniej poziom manifestacji bł˛edów
jest specyficzny dla każdego z badanych scenariuszy testowych. Dodatkowo stwierdzono, że
najcz˛eściej zgłaszanym komunikatem na skutek symulacji bł˛edów jest informacja o awarii
wywołanej nieprawidłowym dost˛epem do pami˛eci, a także przy symulowaniu bł˛edów w
przestrzeni kodu awarie zgłaszane sa˛ już po jednokrotnym wykonaniu zaburzonych instrukcji.
Na podstawie zaobserwowanych faktów opracowane zostały mechanizmy zwi˛ekszania
niezawodności: okresowa weryfikacja spójności kodu systemu operacyjnego, służaca
˛ detekcji
bł˛edów przed ich aktywowaniem, metoda obsługi przerwań wraz z algorytmem brudnych
zasobów oraz metoda ochrony wskaźników powrotu z funkcji przechowywanych na stosie.
Zastosowanie mechanizmów opisanych w rozprawie pozwala na zwi˛ekszenie niezawodności
systemu bez zwi˛ekszania kosztu sprz˛etu. Metoda obsługi przerwań wykorzystuje fakt cz˛estego
wyst˛epowania awarii nieprawidłowego dost˛epu do pami˛eci do weryfikacji spójności kodu
generujacego
˛
przerwanie oraz podj˛ecia procedur naprawczych: rekonstrukcja zaburzonego
kodu oraz ewentualne dodatkowe działania – np. wyznaczenie przez algorytm brudnych
zasobów modyfikacji stanu zadania.
Pewnym problemem implementacyjnym algorytmu brudnych zasobów jest brak
deassemblera w przestrzeni jadra
˛
systemu operacyjnego (przeprowadzono symulacyjna˛
weryfikacj˛e efektywności jego działania), niemniej prace nad tym rozwiazaniem
˛
sa˛ już
prowadzone. Warto zaznaczyć, że w przeprowadzonych badaniach nie był uwzgl˛edniony
kod ładowanych modułów (patrz 5.6.1), a obj˛ecie go ochrona˛ pozwoliłoby na zwi˛ekszenie
efektywności przedstawionych mechanizmów. Dodatkowo sprawność algorytmu brudnych
zasobów może być zwi˛ekszona przez rozszerzenie bazy instrukcji oraz opracowywanie nowych
mechanizmów unieważniania zmian b˛edacych
˛
wynikiem działania zaburzonego kodu (patrz
5.6.2).
Mechanizm ochrony stosu polega na umieszczaniu w nieaktywnej cz˛eści stosu dodatkowych
danych umożliwiajacych
˛
rekonstrukcj˛e poprawnej wartości wskaźników powrotów z funkcji w
przypadku ich zaburzeń (patrz 5.6.3). Niemniej wykorzystanie tego mechanizmu na szeroka˛
skal˛e wymaga wsparcia ze strony kompilatora w celu wygenerowania odpowiedniego kodu.
Szczególnie interesujac
˛ a˛ cecha˛ mechanizmów projektowanych dla jadra
˛
systemu
operacyjnego jest możliwość stosunkowo łatwego przeniesienia ich na grunt aplikacji
użytkowania. Przykładowo zarysowanie metody obsługi przerwań w aplikacji użytkownika
wymaga jedynie opracowania metody dost˛epu do referencyjnego obrazu kodu.
6.2. Zastosowania
Opracowana metodyka przeprowadzania eksperymentów oceny niezawodności może
stanowić cenne narz˛edzie dla projektantów systemów operacyjnych dzi˛eki możliwości
150
wstrzykiwania bł˛edów zarówno w komponenty wewn˛etrzne systemu operacyjnego, jak i
zewn˛etrzne urzadzenia.
˛
Techniki zwi˛ekszania niezawodności przygotowane w niniejszej
rozprawie moga˛ znaleźć zastosowanie w nowoczesnych urzadzeniach
˛
konsumenckich i
specjalistycznych, zwi˛ekszajac
˛ ich niezawodność oraz dostarczajac
˛ informacji o stanie
urzadzenia
˛
poprzez prób˛e wykrycia źródła bł˛edu. W szczególności techniki te zmniejszaja˛
prawdopodobieństwo wystapienia
˛
awarii, co może być kluczowym aspektem w pewnych
zastosowaniach, gdzie koszt uzyskania nieprawidłowego wyniku wraz z informacja˛ o
przeprowadzeniu procedury naprawczej w trakcie jego obliczania jest mniejszy niż awaria
skutkujaca
˛ koniecznościa˛ ponownego uruchomienia systemu.
6.3. Kierunki dalszych badań
Zaprezentowana metodyka oceny niezawodności może być rozszerzona o nowe modele
bł˛edów w celu gł˛ebszej analizy wpływu bł˛edów na działanie systemu operacyjnego.
Interesujacym
˛
zagadnieniem jest również zbadanie efektów bł˛edów w zależności od
przeznaczenia systemu komputerowego (np. serwer plików, serwer WWW, stacja robocza,
telefon komórkowy, terminal POS), a także zwi˛ekszenie ziarnistości badania efektów bł˛edów
o informacje o podatności na bł˛edy poszczególnych modułów funkcjonalnych systemu
(sterowniki, systemy plików, planner, itd.).
Mechanizmy zwi˛ekszania niezawodności przedstawione w rozdziale 5 moga˛ zostać
przeniesione na grunt aplikacji użytkownika, co może być rozwiazaniem
˛
znaczaco
˛ redukujacym
˛
wyst˛epowanie awarii.
Dodatkowym zagadnieniem jest rozszerzenie algorytmu brudnych
zasobów o mechanizmy, które pozwoliły na zwi˛ekszenie skuteczności przy obliczaniu
rozwiazań
˛
problemu odtwarzalności.
Według autora bardzo obiecujacym
˛
kierunkiem
dalszych badań jest wykorzystanie kompilatorów do automatycznego dodawania mechanizmów
zwi˛ekszania niezawodności do istniejacego
˛
oprogramowania oraz generacji dodatkowych
danych ułatwiajacych
˛
przeprowadzanie procedur naprawczych.
151
Bibliografia
[1] IEEE standard for reduced-pin and enhanced-functionality test access port and boundary-scan
architecture. IEEE Std 1149.7-2009, pages c1–985, 2010.
[2] K. Adams and O. Agesen.
A comparison of software and hardware techniques for x86
virtualization. In Proceedings of the 12th international conference on Architectural support for
programming languages and operating systems, ASPLOS-XII, pages 2–13, New York, NY, USA,
2006. ACM.
[3] A. V. Aho, M. S. Lam, R. Sethi, and J. D. Ullman. Compilers: Principles, Techniques, and Tools
(2nd Edition). Addison Wesley, 2006.
[4] T. Akgul and V. J. Mooney. Instruction-level reverse execution for debugging. Technical report,
School of Electrical and Computer Engineering, Georgia Institute of Technology, Atlanta, 2002.
[5] A. Albinet, J. Arlat, and J. C. Fabre. Characterization of the impact of faulty drivers on the
robustness of the linux kernel. In International Conference on Dependable Systems and Networks,
pages 867–876, 2004.
[6] H. Alemzadeh, Z. Kalbarczyk, R. Iyer, and J. Raman. Analysis of safety-critical computer failures
in medical devices. Security Privacy, IEEE, PP(99):1–1, 2013.
[7] B. Alexander, S. Donnellan, A. Jeffries, T. Olds, and N. Sizer. Boosting instruction set simulator
performance with parallel block optimisation and replacement. In Proceedings of the Thirty-fifth
Australasian Computer Science Conference - Volume 122, ACSC ’12, pages 11–20. Australian
Computer Society, Inc., 2012.
[8] J. Arlat, Y. Crouzet, J. Karlsson, P. Folkesson, E. Fuchs, and G. H. Leber. Comparison of
physical and software-implemented fault injection techniques. IEEE Transactions on Computers,
52(9):1115–1133, 2003.
[9] R. Barbosa, N. Silva, J. Duraes, and H. Madeira. Verification and validation of (real time)
COTS products using fault injection techniques. In Sixth International IEEE Conference on
Commercial-off-the-Shelf (COTS)-Based Software Systems, ICCBSS ’07, pages 233–242, 2007.
[10] B. L. Belasco. High stability Windows programming for real time control. In International
Conference on Security Technology (ICCST), IEEE, pages 127–133, 2010.
[11] J. R. Bell. Threaded code. Communications of the ACM, 16(6):370–372, 1973.
[12] F. Bellard. QEMU, a fast and portable dynamic translator. In Proceedings of the USENIX Annual
Technical Conference, ATEC ’05, pages 41–41, Berkeley, CA, USA, 2005. USENIX Association.
[13] M. Berndl, B. Vitale, M. Zaleski, and A. D. Brown. Context threading: a flexible and efficient
dispatch technique for virtual machine interpreters.
Generation and Optimization, pages 15–26, 2005.
153
In International Symposium on Code
[14] A. Binu and G. S. Kumar. Virtualization techniques: A methodical review of XEN and KVM. In
Advances in Computing and Communications, volume 190 of Communications in Computer and
Information Science, pages 399–410. Springer Berlin Heidelberg, 2011.
[15] C. Borchert, H. Schirmeier, and O. Spinczyk. Generative software-based memory error detection
and correction for operating system data structures. In International Conference on Dependable
Systems and Networks, pages 1–12, 2013.
[16] S. Borkar. Designing reliable systems from unreliable components: the challenges of transistor
variability and degradation. Micro, IEEE, 25(6):10–16, 2005.
[17] M. Brunink, M. Susskraut, and C. Fetzer. Boundless memory allocations for memory safety and
high availability. In International Conference on Dependable Systems Networks, pages 13–24,
2011.
[18] K. Buchacker and V. Sieh. Framework for testing the fault-tolerance of systems including
os and network aspects. In Sixth IEEE International Symposium on High Assurance Systems
Engineering, pages 95–105, 2001.
[19] J. Carreira, H. Madeira, and J. G. Silva.
Xception: a technique for the experimental
evaluation of dependability in modern computers. IEEE Transactions on Software Engineering,
24(2):125–136, 1998.
[20] N. Chandra Shekar and W. Bhukya. Forensic analysis on QEMU. In Computational Intelligence
and Information Technology, volume 250 of Communications in Computer and Information
Science, pages 777–781. Springer Berlin Heidelberg, 2011.
[21] D. Chen, G. Jacques-Silva, Z. Kalbarczyk, R. K. Iyer, and B. Mealey. Error behavior comparison
of multiple computing systems: A case study using Linux on Pentium, Solaris on SPARC, and
AIX on POWER. In 14th IEEE Pacific Rim International Symposium on Dependable Computing,
PRDC ’08, pages 339 –346, 2008.
[22] Shyh-Kwei Chen, W. K. Fuchs, and Jen-Yao Chung. Reversible debugging using program
instrumentation. IEEE Transactions on Software Engineering, 27; 27(8):715–727, 2001.
[23] S. Chyłek. Collecting program execution statistics with qemu processor emulator. In International
Multiconference on Computer Science and Information Technology, IMCSIT ’09, pages 555–558,
2009.
[24] S. Chyłek. QEMU CPU Tracer – an exact profiling tool. Metody Informatyki Stosowanej,
5/2011(30):167–172, 2011.
[25] S. Chyłek and M. Goliszewski. QEMU-Based Fault Injection Framework. Studia Informatica,
33(4(109)):25–42, 2011.
[26] S. Chyłek and M. Goliszewski. Wstrzykiwanie bł˛edów oparte na modelach - zastosowania
QEMU w analizie niezawodności urzadzeń
˛
mobilnych. Zeszyty Naukowe Wydziału Elektroniki,
Telekomunikacji i Informatyki Politechniki Gdańskiej, 1(9):489–494, 2011.
[27] C. Constantinescu. Impact of deep submicron technology on dependability of VLSI circuits. In
International Conference on Dependable Systems and Networks, pages 205–209, 2002.
[28] C. Constantinescu. Trends and challenges in VLSI circuit reliability. Micro, IEEE, 23(4):14–19,
2003.
154
[29] J. Cornwell and A. Kongmunvattana. Efficient system-level remote checkpointing technique
for BLCR. In Eighth International Conference on Information Technology: New Generations
(ITNG), pages 1002–1007, 2011.
[30] D. Cotroneo, R. Natella, and S. Russo. Assessment and improvement of hang detection in the
Linux operating system. In 28th IEEE International Symposium on Reliable Distributed Systems,
SRDS ’09, pages 288–294, 2009.
[31] A. da Silva, J. F. Martinez, L. Lopez, A. B. Garcia, and V. Hernandez. XML schema based faultset
definition to improve faults injection tools interoperability, 2008.
[32] R. Dewar. Indirect threaded code. Communications of the ACM, 18(6):330–331, 1975.
[33] R. J. Drebes and T. Nanya. Limitations of the Linux fault injection framework to test direct
memory access address errors. In 14th IEEE Pacific Rim International Symposium on Dependable
Computing, PRDC ’08, pages 146–152, 2008.
[34] J. C. Fabre, M. Rodriguez, J. Arlat, and J. M. Sizun.
microkernel-based systems using MAFALDA.
Building dependable COTS
In Pacific Rim International Symposium on
Dependable Computing, 2000.
[35] P. Gawkowski. Analysing and enhancing fault immunity of programs in systems with COTS
elements. PhD thesis, Warsaw University of Technology, 2005.
[36] P. Gawkowski and K. Grochowski. Inscript - a fault injection scripting language for system
dependability evaluation. In Information Systems Architecture and Technology, Web Information
System Engineering, Knowledge Discovery and Hybrid Computing, pages 245–254. Wrocław
University of Technology, 2011.
[37] P. Gawkowski, M. Kuczyńska, and A. Komorowska. Fault effects analysis and reporting system
for dependability evaluation. In Rough Sets and Current Trends in Computing, volume 6086 of
Lecture Notes in Computer Science, pages 524–533. Springer Berlin Heidelberg, 2010.
[38] P. Gawkowski, P. Pawelczyk, J. Sosnowski, K. Cabaj, and M. Gajda. LRFI - fault injection tool
for testing mobile software. In ISMIS Industrial Session, pages 269–282, 2011.
[39] P. Gawkowski, T. Rutkowski, and J. Sosnowski. Improving fault handling software techniques. In
IEEE 16th International On-Line Testing Symposium (IOLTS), IOLTS ’10, pages 197–199, 2010.
[40] P. Gawkowski and J. Sosnowski. Analyzing fault effects in fault insertion experiments. Seventh
International On-Line Testing Workshop, pages 21–24, 2001.
[41] P. Gawkowski and J. Sosnowski. Using software implemented fault inserter in dependability
analysis. Pacific Rim International Symposium on Dependable Computing, pages 81–88, 2002.
[42] P. Gawkowski and J. Sosnowski.
experiments.
Developing fault injection environment for complex
In 14th IEEE International On-Line Testing Symposium, IOLTS ’08, pages
179–181, 2008.
[43] D. Gil, J. Gracia, J. C. Baraza, and P. J. Gil. Analysis of the influence of processor hidden
registers on the accuracy of fault injection techniques. In Ninth IEEE International High-Level
Design Validation and Test Workshop, pages 173–178, 2004.
155
[44] D. Gil, L. Saiz, J. Gracia, J. C. Baraza, and P. Gil.
Injecting intermittent faults for the
dependability validation of commercial microcontrollers. In IEEE International High Level
Design Validation and Test Workshop, HLDVT ’08, pages 177–184, 2008.
[45] R. Gioiosa, J. C. Sancho, S. Jiang, F. Petrini, and K. Davis.
Transparent, incremental
checkpointing at kernel level: a foundation for fault tolerance for parallel computers.
In
Proceedings of the 2005 ACM/IEEE conference on Supercomputing, SC ’05, pages 9–,
Washington, DC, USA, 2005. IEEE Computer Society.
[46] I. Gnaedig, M. Kaczmarek, D. Reynaud, and S. Wloka. Unconditional self-modifying code
elimination with dynamic compiler optimizations. In 5th International Conference on Malicious
and Unwanted Software (MALWARE), pages 47–54, 2010.
[47] J. Gracia, L. Saiz, J. C. Baraza, D. Gil, and P. Gil. Analysis of the influence of intermittent faults
in a microcontroller. In 11th IEEE Workshop on Design and Diagnostics of Electronic Circuits
and Systems, DDECS 2008, pages 1–6, 2008.
[48] Weining Gu, Z. Kalbarczyk, and R. K. Iyer. Error sensitivity of the Linux kernel executing on
PowerPC G4 and Pentium 4 processors. In International Conference on Dependable Systems and
Networks, pages 887–896, 2004.
[49] A. H. Han, Young-Si Hwang, Young-Ho An, So-Jin Lee, and Ki-Seok Chung. Virtual ARM
platform for embedded system developers. International Conference on Audio, Language and
Image Processing, pages 586–592, 2008.
[50] S. Hangal and M. S. Lam. Tracking down software bugs using automatic anomaly detection.
In Proceedings of the 24th International Conference on Software Engineering, ICSE ’02, pages
291–301, New York, NY, USA, 2002. ACM.
[51] J. L. Hennessy and D. A. Patterson. Computer Architecture, Fourth Edition: A Quantitative
Approach. Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 2006.
[52] J. N. Herder, H. Bos, B. Gras, P. Homburg, and A. S. Tanenbaum. Minix 3: a highly reliable,
self-repairing operating system. SIGOPS Oper. Syst. Rev., 40(3):80–89, 2006.
[53] J.N. Herder, H. Bos, B. Gras, P. Homburg, and A.S. Tanenbaum. Construction of a highly
dependable operating system. In Sixth European Dependable Computing Conference, pages
3–12, 2006.
[54] J.N. Herder, H. Bos, B. Gras, P. Homburg, and A.S. Tanenbaum. Fault isolation for device drivers.
In International Conference on Dependable Systems Networks, pages 33–42, 2009.
[55] Bing Huang, M. Rodriguez, Ming Li, and C. Smidts. On the development of fault injection
profiles. In Annual Reliability and Maintainability Symposium, RAMS ’07, pages 226–231, 2007.
[56] Intel Corporation. Intel 64 and IA-32 Architectures Software Developer’s Manual, 2013.
[57] B. Jacob, S. Ng, and D. Wang. Memory Systems: Cache, DRAM, Disk. Morgan Kaufmann
Publishers Inc., San Francisco, CA, USA, 2007.
[58] G. Jacques-Silva, R. J. Drebes, J. Gerchman, J. M. F. Trindade, T. S. Weber, and I. Jansch-Porto.
A network-level distributed fault injector for experimental validation of dependable distributed
systems. 30th Annual International Computer Software and Applications Conference, 1:421–428,
2006.
156
[59] S. Jagannathan, Z. Diggins, N. Mahatme, T.D. Loveless, B. L. Bhuva, S-J Wen, R. Wong,
and L.W. Massengill. Temperature dependence of soft error rate in flip-flop designs. In IEEE
International Reliability Physics Symposium (IRPS), pages SE.2.1–SE.2.6, 2012.
[60] M. Jakovljevic and A. Ademaj.
Ethernet protocol services for critical embedded systems
applications. In Digital Avionics Systems Conference (DASC), IEEE, pages 5.B.3–1–5.B.3–10,
2010.
[61] T. Jarboui, J. Arlat, Y. Crouzet, and K. Kanoun. Experimental analysis of the errors induced into
Linux by three fault injection techniques. In International Conference on Dependable Systems
and Networks, pages 331–336, 2002.
[62] T. Jarboui, J. Arlat, Y. Crouzet, K. Kanoun, and T. Marteau. Analysis of the effects of real
and injected software faults: Linux as a case study. In Pacific Rim International Symposium on
Dependable Computing, pages 51–58, 2002.
[63] E. Jenn, J. Arlat, M. Rimen, J. Ohlsson, and J. Karlsson. Fault injection into VHDL models: the
MEFISTO tool. Twenty-Fourth International Symposium on Fault-Tolerant Computing, pages
66–75, 1994.
[64] Xun Jian and R. Kumar. Adaptive Reliability Chipkill Correct (ARCC). In 19th International
Symposium on High Performance Computer Architecture, HPCA ’13, pages 270–281, 2013.
[65] Seongwoo Kim and A.K. Somani. Soft error sensitivity characterization for microprocessor
dependability enhancement strategy. In International Conference on Dependable Systems and
Networks, pages 416–425, 2002.
[66] W. Klonecki. Statystyka dla inżynierów. Wydawnictwo Naukowe PWN, 1999.
[67] P. M. Kogge. An architectural trail to threaded-code systems. Computer, pages 22–32, 1982.
[68] J. Korczyc and A. Kraśniewski. Evaluation of susceptibility of fpga-based circuits to fault
injection attacks based on clock glitching. In IEEE 15th International Symposium on Design
and Diagnostics of Electronic Circuits Systems, DDECS, pages 171–174, 2012.
[69] M. Kubacki and J. Sosnowski. Analysing event log profiles in Linux systems. In Information
Systems Architecture and Technology, Web Information System Engineering, Knowledge
Discovery and Hybrid Computing, pages 135–144. Wrocław University of Technology, 2011.
[70] M. Kubacki and J. Sosnowski. Enhanced instrumentation of system monitoring. In Information
Systems in Management XVI: Modern ICT for Evaluation of Business Information Systems, pages
29–40. SGGW, 2012.
[71] P. Latosiński and J. Sosnowski.
Monitoring dependability of a mail server.
Przeglad
˛
Elektrotechniczny, (10b):223–226, 2012.
[72] A. Lesiak, P. Gawkowski, and J. Sosnowski. Error recovery problems. In 2nd International
Conference on Dependability of Computer Systems, DepCoS-RELCOMEX ’07, pages 270–277,
2007.
[73] Xiaofei Liao, Xiao Xie, and Hai Jin. Sharing virtual USB device in virtualized desktop. In Fourth
International Symposium on Parallel Architectures, Algorithms and Programming (PAAP), pages
156–160, 2011.
157
[74] Xiyang Liu, Tao Liu, Zhiwen Bai, Yan Wang, Haoying Mu, and Chunxiang Li.
a reversible debugging tool using dynamic binary translation.
PORD:
14th Asia-Pacific Software
Engineering Conference, pages 570–570, 2007.
[75] H. Madeira, D. Costa, and M. Vieira. On the emulation of software faults by software fault
injection. Proceedings International Conference on Dependable Systems and Networks, pages
417–426, 2000.
[76] P. D. Marinescu and G. Candea. LFI: A practical and general library-level fault injector. In
International Conference on Dependable Systems and Networks, pages 379–388, 2009.
[77] D. Mihocka and S. Shwartsman. Virtualization without direct execution or jitting: Designing a
portable virtual machine infrastructure. In 1st Workshop on Architectural and Microarchitectural
Support for Binary Translation in ISCA-35, 2008.
[78] J. S. Monson, M. Wirthlin, and B. Hutchings. A fault injection analysis of Linux operating on an
FPGA-embedded platform. Int. J. Reconfig. Comput., 2012:7:7–7:7, 2012.
[79] S. S. Mukherjee, M. Kontz, and S. K. Reinhardt. Detailed design and evaluation of redundant
multi-threading alternatives. In 29th Annual International Symposium on Computer Architecture,
pages 99–110, 2002.
[80] M. Murciano and M. Violante. Validating the dependability of embedded systems through fault
injection by means of loadable kernel modules. In High Level Design Validation and Test
Workshop, IEEE International, pages 179–186, 2007.
[81] A. B. Nagarajan, F. Mueller, C. Engelmann, and S. L. Scott. Proactive fault tolerance for
HPC with Xen virtualization. In Proceedings of the 21st annual international conference on
Supercomputing, ICS ’07, pages 23–32, New York, NY, USA, 2007. ACM.
[82] P. Nazimek. Wykrywanie, ocena skuteczności i optymalizacja asercji w programach. Zeszyty
Naukowe Wydziału ETI Politechniki Gdańskiej, 6:281–286, 2008.
[83] P. Nazimek. Wykrywanie i zastosowanie asercji ze śladem. Zeszyty Naukowe Wydziału ETI
Politechniki Gdańskiej, 19(8):379–384, 2010.
[84] E. B. Nightingale, J. R. Douceur, and V. Orgovan. Cycles, cells and platters: An empirical
analysisof hardware failures on a million consumer PCs. In Proceedings of the Sixth Conference
on Computer Systems, EuroSys ’11, pages 343–356, New York, NY, USA, 2011. ACM.
[85] D. K. Nilsson, Lei Sun, and T. Nakajima. A framework for self-verification of firmware updates
over the air in vehicle ECUs. In GLOBECOM Workshops, pages 1–5, 2008.
[86] K. Onoue, Y. Oyama, and A. Yonezawa. A virtual machine migration system based on a CPU
emulator. First International Workshop on Virtualization Technology in Distributed Computing,
pages 3–3, 2006.
[87] E. Park, B. Egger, and J. Lee. Fast and space-efficient virtual machine checkpointing. In
Proceedings of the 7th ACM SIGPLAN/SIGOPS international conference on Virtual execution
environments, VEE ’11, pages 75–86, New York, NY, USA, 2011. ACM.
[88] P. Popov and L. Strigini.
Assessing asymmetric fault-tolerant software.
Symposium on Software Reliability Engineering, pages 41–50, 2010.
158
In International
[89] R. Radhakrishnan, N. Vijaykrishnan, L. K. John, Anand Sivasubramaniam, J. Rubio, and
J. Sabarinathan. Java runtime systems: characterization and architectural implications. IEEE
Transactions on Computers, 50(2):131–146, 2001.
[90] L. Rashid, K. Pattabiraman, and S. Gopalakrishnan. Modeling the propagation of intermittent
hardware faults in programs. In 16th Pacific Rim International Symposium on Dependable
Computing, pages 19–26, 2010.
[91] C. Reis and S. D. Gribble.
Isolating web programs in modern browser architectures.
In
Proceedings of the 4th ACM European conference on Computer systems, EuroSys ’09, pages
219–232, New York, NY, USA, 2009. ACM.
[92] C. Roscian, A. Sarafianos, J. M. Dutertre, and A. Tria. Fault model analysis of laser-induced
faults in SRAM memory cells. In Workshop on Fault Diagnosis and Tolerance in Cryptography
(FDTC), pages 89–98, 2013.
[93] M. Sand, S. Potyra, and V. Sieh. Deterministic high-speed simulation of complex systems
including fault-injection. In International Conference on Dependable Systems and Networks,
pages 211–216, 2009.
[94] B. Schroeder, E. Pinheiro, and W. Weber. DRAM errors in the wild: a large-scale field study.
In Proceedings of the eleventh international joint conference on Measurement and modeling of
computer systems, SIGMETRICS ’09, pages 193–204, New York, NY, USA, 2009. ACM.
[95] Ningfang Song, Jiaomei Qin, Xiong Pan, and Yan Deng. Fault injection methodology and tools.
In International Conference on Electronics and Optoelectronics, volume 1, pages V1–47–V1–50,
2011.
[96] J. Sosnowski. Testowanie i niezawodność systemów komputerowych. Akademicka Oficyna
Wydawnicza Exit, 2005.
[97] J. Sosnowski, M. Kubacki, and H. Krawczyk. Monitoring event logs within a cluster system.
In Complex Systems and Dependability, Advances in Intelligent and Soft Computing, pages
259–271. Springer, 2012.
[98] J. Sosnowski and L. Tupaj. CPU testability in embedded systems. In Fifth IEEE International
Symposium on Electronic Design, Test and Application, DELTA ’10, pages 108 –112, 2010.
[99] J. Sosnowski, A. Tymoczko, and P. Gawkowski. An approach to distributed fault injection
experiments. Parallel Processing and Applied Mathematics, pages 361–370, 2008.
[100] J. Sosnowski, A. Tymoczko, and P. Gawkowski. Developing distributed system for simulation
experiments.
Information Systems Architecture and Technology, Information Systems and
Computer Communication Networks, pages 263–274, 2008.
[101] J. Sosnowski, P. Zygulski, and P. Gawkowski.
Developing data warehouse for simulation
experiments. In Rough Sets and Intelligent Systems Paradigms, volume 4585 of Lecture Notes in
Computer Science, pages 543–552. Springer Berlin Heidelberg, 2007.
[102] R. Svenningsson, H. Eriksson, J. Vinter, and M. Törngren. Model-implemented fault injection
for hardware fault simulation. In Workshop on Model-Driven Engineering, Verification, and
Validation, pages 31–36, 2010.
159
[103] A. S. Tanenbaum. Modern Operating Systems. Prentice Hall Press, Upper Saddle River, NJ,
USA, 3rd edition, 2007.
[104] D. Trawczyński, J. Sosnowski, and P. Gawkowski. Testing distributed ABS system with fault
injection. In Innovations in Computing Sciences and Software Engineering, pages 201–206.
Springer, 2010.
[105] P. Tröger, F. Salfner, and S. Tschirpke. Software-implemented fault injection at firmware level.
In Third International Conference on Dependability, DEPEND, pages 13–16, 2010.
[106] T. Tsai, N. Theera-Ampornpunt, and S. Bagchi. A study of soft error consequences in hard disk
drives. In International Conference on Dependable Systems and Networks, pages 1–8, 2012.
[107] K. Vaswani and Y. N. Srikant. Dynamic recompilation and profile-guided optimisations for a
.NET JIT compiler. Software, IEE Proceedings, 150(5):296–302, 2003.
[108] Liming Wang, Xiyang Liu, Ailong Song, Lin Xu, and Tao Liu. An effective reversible debugger
of cross platform based on virtualization. International Conference on Embedded Software and
Systems, pages 448–453, 2009.
[109] Long Wang, Z. Kalbarczyk, R.K. Iyer, and A. Iyengar. Checkpointing virtual machines against
transient errors. In IEEE 16th International On-Line Testing Symposium, pages 97–102, 2010.
[110] Jiesheng Wei, L. Rashid, K. Pattabiraman, and S. Gopalakrishnan. Comparing the effects of
intermittent and transient hardware faults on programs. In 41st International Conference on
Dependable Systems and Networks Workshops, pages 53–58, 2011.
[111] P. M. Wells, K. Chakraborty, and G. S. Sohi. Adapting to intermittent faults in future multicore
systems. In 16th International Conference on Parallel Architecture and Compilation Techniques,
PACT 2007, pages 431–431, 2007.
[112] S. Winter, C. Sarbu, B. Murphy, and N. Suri. The impact of fault models on software robustness
evaluations. In 33rd International Conference on Software Engineering (ICSE), pages 51–60,
2011.
[113] Jun Xu, Z. Kalbarczyk, and R. K. Iyer. Networked Windows NT system field failure data analysis.
In Pacific Rim International Symposium on Dependable Computing, pages 178–185, 1999.
[114] Yang Yang and LingLing Hua. Research and improvement of Linux real-time performance.
In Advanced Technology in Teaching - Proceedings of the 2009 3rd International Conference
on Teaching and Computational Science, volume 116 of WTCS 2009, pages 555–559. Springer
Berlin Heidelberg, 2012.
[115] Keun Soo Yim, Z. Kalbarczyk, and R.vK. Iyer. Measurement-based analysis of fault and error
sensitivities of dynamic memory. In International Conference on Dependable Systems and
Networks, pages 431–436, 2010.
[116] FanPing Zeng, Juan Li, Ling Li, and Xufa Wang. Fault injection technology for software
vulnerability testing based on Xen. In World Congress on Software Engineering, volume 4 of
WCSE ’09, pages 206 –210, 2009.
A. Dodatek – specyfikacja opracowanego
oprogramowania
Kody źródłowe QEFI oraz dodatkowe zasoby można znaleźć w repozytorium projektu
znajdujacym
˛
si˛e pod adresem http://chylek.name/qefi/.
A.1. QEFI
Narz˛edzie QEFI składa si˛e z kilku współpracujacych
˛
ze soba˛ programów w celu realizacji
eksperymentów symulowania bł˛edów w systemie komputerowym.
A.1.1. QEMU
Podstawowym komponentem QEFI jest emulator systemu komputerowego QEMU. W
QEFI wykorzystano oprogramowanie QEMU w wersji 1.1.2. W celu realizacji metodyki
symulowania bł˛edów zmodyfikowane zostały nast˛epujace
˛ moduły QEMU:
Moduł Fault Injection – Opracowano nowy moduł realizujacy
˛ zaburzanie pami˛eci
oraz kontrolujacy
˛ wyzwalanie warunkowego wstrzykiwania bł˛edu.
Moduł śledzenia wykonania – Opracowano nowy moduł realizujacy
˛ nieinwazyjne
śledzenie wykonania poprzez rejestrowanie wykonania instrukcji skoków przez emulowany
procesor.
Moduł konsoli sterowania – Modyfikacja modułu konsoli sterowania umożliwiajaca
˛
wykonywanie komend sterujacych
˛
procesem symulacji bł˛edów oraz profilowania.
Moduł translacji binarnej – Modyfikacje polegajace
˛
na wplataniu w kod
wygenerowany w procesie binarnej translacji dodatkowych funkcji realizujacych
˛
zarówno
symulowanie bł˛edów, jak i profilowanie.
Moduł dost˛
epu do pami˛
eci – Modyfikacje umożliwiajace
˛
symulowanie bł˛edów
danych przy odczycie, wykorzystane w procesie zaburzania pami˛eci alokowanej przez
system operacyjny.
Moduł emulujacy
˛
urzadzenie
˛
USB MSD –
Modyfikacje
umożliwiajace
˛
symulowanie bł˛edów w pakietach wysyłanych z urzadzenia
˛
USB MSD.
Moduł emulujacy
˛
urzadzenie
˛
USB UHCI –
Modyfikacje
symulowanie bł˛edów w rejestrach kontrolera USB UHCI.
161
umożliwiajace
˛
Moduł emulujacy
˛
urzadzenie
˛
e1000 – Modyfikacje umożliwiajace
˛ symulowanie
bł˛edów w deskryptorach pakietów pochodzacych
˛
z urzadzenia
˛
sieciowego e1000.
Poniżej zamieszczony jest listing nowych komend konsoli sterowania QEMU:
fi_enable – Komenda powoduje właczenie
˛
funkcji zwiazanych
˛
ze wstrzykiwaniem bł˛edów.
fi_disable – Komenda powoduje wyłaczenie
˛
funkcji zwiazanych
˛
ze wstrzykiwaniem
bł˛edów.
fi_write_pmem – Parametry: adres fizyczny, nowa wartość bajtu. Komenda pozwala
zapisać dowolny bajt w pami˛eci operacyjnej wskazany adresem fizycznym.
fi_write_vmem – Parametry: adres pami˛eci wirtualny, nowa wartość bajtu. Komenda
pozwala zapisać dowolny bajt w pami˛eci operacyjnej wskazany adresem pami˛eci wirtualnej.
Komenda może być wykonana wyłacznie
˛
po wstrzymaniu procesu emulacji, a zaburzana
pami˛eć wirtualna jest pami˛ecia˛ procesu wykonywanego przed wstrzymaniem.
fi_random_bit_vmem_range – Parametry: poczatek
˛ zakresu pami˛eci wirtualnej, koniec
zakresu pami˛eci wirtualnej. Komenda powoduje wprowadzenie pojedynczego bł˛edu typu
bit-flip w losowo wybrana˛ komórk˛e pami˛eci spośród zadanego zakresu. Komenda może
być wykonana wyłacznie
˛
po wstrzymaniu procesu emulacji, a zaburzana pami˛eć wirtualna
jest pami˛ecia˛ procesu wykonywanego przed wstrzymaniem.
fi_disturb_usb_msd – Parametry: prawdopodobieństwo zaburzenia pakietu. Komenda
powoduje wprowadzenie pojedynczego bł˛edu typu bit-flip w losowo wybrany bit pakietu
danych wysyłanych z urzadzenia
˛
USB MSD. Wybór zaburzanego pakietu jest warunkowy,
sterowany prawdopodobieństwem – tzn. przy każdej operacji wysyłania pakietu z
urzadzenia
˛
USB MSD wybierana jest losowa liczba z zakresu [0−1]; jeżeli jest ona mniejsza
niż zadane prawdopodobieństwo, to do pakietu wprowadzany jest bład.
˛
fi_disturb_usb_uhci – Parametry: prawdopodobieństwo wprowadzenia bł˛edu przy
aktualizacji stanu rejestrów USB UHCI. Komenda powoduje wprowadzenie pojedynczego
bł˛edu typu bit-flip w losowo wybrany bit w losowo wybranym rejestrze kontrolera
USB UHCI – wybór momentu wprowadzenia bł˛edu jest warunkowy, sterowany
prawdopodobieństwem – tzn. przy każdej operacji aktualizacji stanu rejestrów USB UHCI
wybierana jest losowa liczba z zakresu [0 − 1]; jeżeli jest ona mniejsza niż zadane
prawdopodobieństwo, to do losowego rejestru wprowadzany jest bład.
˛
fi_disturb_e1000 – Parametry: prawdopodobieństwo zaburzenia deskryptora pakietu.
Komenda powoduje wprowadzenie pojedynczego bł˛edu typu bit-flip w losowo wybrany
bit deskryptora pakietu danych pochodzacych
˛
z urzadzenia
˛
sieciowego e1000. Wybór
zaburzanego deskryptora pakietu jest warunkowy, sterowany prawdopodobieństwem –
tzn. przy każdej operacji wysyłania deskryptora pakietu z urzadzenia
˛
e1000 wybierana jest
losowa liczba z zakresu [0 − 1]; jeżeli jest ona mniejsza niż zadane prawdopodobieństwo,
to do pakietu wprowadzany jest bład.
˛
162
fi_disturb_stack – Parametry:
zaburzanej przestrzeni stosu.
prawdopodobieństwo wprowadzenia bł˛edu, zakres
Komenda powoduje wprowadzenie pojedynczego bł˛edu
typu bit-flip w losowo wybrany bit danych w określonym zakresie liczonym od
wierzchołka stosu.
Wybór momentu wprowadzenia bł˛edu jest warunkowy, sterowany
prawdopodobieństwem – tzn. przy każdym wykonaniu przez emulowany procesor instrukcji
call, wybierana jest losowa liczba z zakresu [0 − 1]; jeżeli jest ona mniejsza niż zadane
prawdopodobieństwo, to w określonym zakresie danych wprowadzany jest bład.
˛
fi_disturb_allocked_mem – Parametry: prawdopodobieństwo wprowadzenia bł˛edu,
adres funkcji trace_kmalloc, adres funkcji kfree. Komenda powoduje wprowadzenie
pojedynczego bł˛edu typu bit-flip w losowo wybrany bit danych spośród danych
zaalokowanych przez system operacyjny od momentu wydania komendy. Zbiór danych
jest wyznaczany dynamicznie poprzez śledzenie wywołań funkcji kmalloc oraz kfree.
Wybór momentu wprowadzenia bł˛edu jest warunkowy, sterowany prawdopodobieństwem –
tzn. przy każdej operacji odczytu danych przez emulowany procesor z wyznaczonego zbioru
danych alokowanych, wybierana jest losowa liczba z zakresu [0−1]; jeżeli jest ona mniejsza
niż zadane prawdopodobieństwo, to w odczytywanych zakresie danych wprowadzany jest
bład.
˛
fi_enable_trace – Komenda powoduje właczenie
˛
trybu śledzenia wykonania.
W
katalogu roboczym QEMU tworzony jest plik zawierajacy
˛ skompresowana˛ algorytmem
GZIP histori˛e skoków wykonanych przez procesor.
fi_disable_trace – Komenda powoduje wyłaczenie
˛
trybu śledzenia wykonania.
A.1.2. Nadzorca
Nadzorca jest programem kontrolujacym
˛
przebieg wykonania testu.
Jego głównym
zadaniem jest uruchomienie instancji QEMU i wykonanie kroków scenariusza testowego.
Oprogramowanie nadzorcy nawiazuje
˛
połaczenia
˛
konsola˛ sterowania QEMU oraz emulowanym
portem szeregowym emulowanego systemu. Opcjonalnie Nadzorca uruchamia dodatkowe
programy przeprowadzajace
˛ interakcj˛e z emulowanym systemem (np. skrypty programu expect
realizujace
˛ szyfrowane połaczenia
˛
ssh). Predefiniowane jest kilka typów scenariuszy testowych
(dokładny wykaz poniżej), a nowe scenariusze moga˛ być dodawane według potrzeb poprzez
rozszerzenie programu Nadzorcy. Możliwe jest uruchomienie scenariusza testowego w trybie
profilowania, gdzie bład
˛ nie jest wstrzykiwany, natomiast zbierane sa˛ dane z nieinwazyjnego
śledzenia wykonania. Dla niektórych scenariuszy konieczne może być dostarczenie danych z
profilowania.
Flagi uruchamiania programu Nadzorcy:
trace – Wykonanie scenariusza bez symulacji bł˛edu, natomiast zbierane sa˛ dane z
nieinwazyjnego śledzenia wykonania.
163
fault – Typ bł˛edu spośród typów bł˛edów zdefiniowanych dla danego scenariusza testowego.
port_control – Numer portu, na którym ma być prowadzona komunikacja Nadzorcy z
konsola˛ sterowania QEMU.
port_serial – Numer portu, na którym ma być prowadzona komunikacja Nadzorcy z
emulowanym portem szeregowym SUT.
scenario – Uruchomiony scenariusz testowy. Dost˛epne scenariusze:
— wget – Scenariusz realizujacy
˛ kroki opisane w Scenariuszu 4.1 (strona 75). Dost˛epne
typy bł˛edów: zaburzanie pami˛eci fizycznej, zaburzanie danych pami˛eci wirtualnej,
zaburzanie kodu wyznaczonego z profilowania, zaburzanie danych alokowanych,
zaburzanie danych na stosie.
— curl – Scenariusz analogiczny do scenariusza wget wykorzystujacy
˛ program curl
zamiast wget. Dost˛epne typy bł˛edów: zaburzanie pami˛eci fizycznej.
— pendrive – Scenariusz realizujacy
˛ kroki opisane w Scenariuszu (strona 4.2).
Dost˛epne typy bł˛edów: zaburzanie pakietów wysyłanych z urzadzenia
˛
USB MSD,
zaburzanie wartości zawartości rejestrów urzadzenia
˛
USB UHCI.
— srv – Scenariusz realizujacy
˛ kroki opisane w Scenariuszu 4.3 (strona 108).Dost˛epne
typy bł˛edów: zaburzanie kodu wyznaczonego z profilowania, zaburzanie danych
alokowanych, zaburzanie danych na stosie.
W wyniku działania programu Nadzorcy wytworzone sa˛ nast˛epujace
˛ artefakty:
appxLogFile.log – Dziennik programu Nadzorcy.
login.txt – Zapis interakcji programu Nadzorcy z SUT na kanale konsoli szeregowej od
momentu uruchomienia SUT do uruchomienia systemu operacyjnego działajacego
˛
w SUT.
experiment.txt – Zapis interakcji programu Nadzorcy z SUT na kanale konsoli
szeregowej od momentu uruchomienia systemu operacyjnego działajacego
˛
w SUT.
monitor.txt – Zapis interakcji programu Nadzorcy z konsola˛ sterowania QEMU.
serr.txt, sout.txt – Zrzut danych wypisanych przez program QEMU na standardowy
strumień wyjścia oraz standardowy strumień bł˛edów.
run.log – Dziennik wykonania scenariusza przez program Nadzorcy.
output.gz – Opcjonalny plik zawierajacy
˛ skompresowane dane z profilowania.
kallsyms.txt – Opcjonalny plik (zależny od scenariusza) zawierajacy
˛
zrzut pliku
/proc/kallsyms systemu operacyjnego działajacego
˛
w SUT.
sshout.txt, sshserr.txt, wgetserr.txt, wgetsout.txt, ... – Opcjonalne
pliki zawierajace
˛ zrzut danych wypisanych przez dodatkowe programy uruchomione przez
program Nadzorcy na standardowy strumień wyjścia oraz standardowy strumień bł˛edów.
164
A.1.3. Ekstraktor
Program Ekstraktor jest programem pomocniczym realizujacym
˛
dekodowanie pliku z
zapisanymi informacjami z profilowania – adresy skoków wykonanych przez procesor
tłumaczone sa˛ na nazwy funkcji jadra
˛
systemu operacyjnego. Program działa na podstawie
plików output.gz i kallsyms.txt, które sa˛ artefaktami wykonania scenariusza
testowego przez program Nadzorcy w trybie trace. Szczegółowy schemat działania programu
jest opisany w [24].
A.1.4. Eksperyment
Eksperyment jest to skrypt realizujacy
˛ uruchomienie wielu instancji par programów
Nadzorca-QEMU w celu wykonania zadanej liczby testów. Parametry skryptu to:
rootdir – Główny katalog, w którym tworzone sa˛ podkatalogi b˛edace
˛ katalogami roboczymi
par programów Nadzorca-QEMU (w podkatalogach składowane sa˛ artefakty każdej
instancji programu Nadzorcy).
port_range_control_start –
jest
parametr
liczba,
na
programu
port_control
podstawie
Nadzorcy
której
wyliczany
(port_control
=
port_range_control_start + identyfikator instancji programu Nadzorcy nadany
przez skrypt Eksperyment z zakresu 1..jobs).
port_range_serial_start –
jest
parametr
liczba,
port_serial
na
programu
podstawie
Nadzorcy
której
wyliczany
(port_serial
=
port_range_serial_start + identyfikator instancji programu Nadzorcy nadany
przez skrypt Eksperyment z zakresu 1..jobs).
jobs – Liczba jednocześnie uruchomionych instancji par programów Nadzorca-QEMU. W
momencie zakończenia działania jednej z instancji uruchamiana jest nowa instancja, której
przydzielany jest nowy katalog roboczy.
tests – Liczba testów do wykonania.
A.1.5. Analizator
Program Analizator dokonuje podsumowania wyników wygenerowanych z użyciem
skryptu Eksperyment. Wyposażony jest on w baz˛e komunikatów, których obecność sprawdza
w artefaktach programu Nadzorca. Posiada on też wbudowane referencyjne dane scenariuszy –
w szczególności funkcje oceny pozwalajace
˛ określić, czy dany test zakończył si˛e wynikiem
prawidłowym.
Wynikiem działania programu jest plik CSV zawierajacy
˛ podsumowanie
wykrytych cech dla każdego z przeprowadzonych testów. Parametry wywołania programu to:
rootdir – Główny katalog, w którym znajduja˛ si˛e katalogi z artefaktami przeznaczonymi do
analizy.
workers – Liczba watków
˛
równocześnie analizujacych
˛
artefakty.
165
scenario – Referencyjny scenariusz. Dost˛epne scenariusze: wget, curl, pendrive,
srv.
csv – Nazwa pliku stanowiacego
˛
wynik działania programu.
viewerrors – Przełacznik
˛
umożliwiajacy
˛
przeglad
˛ dzienników wykonania testów z
zamanifestowanym bł˛edem.
performance – Przełacznik
˛
powodujacy
˛ zbieranie dodatkowych danych dotyczacych
˛
czasu
wykonania testów.
A.2. Zmiany w jadrze
˛
systemu GNU/Linux
W celu implementacji mechanizmów zwi˛ekszania niezawodności wprowadzono
nast˛epujace
˛ zmiany w jadrze
˛
systemu GNU/Linux (wersja 2.6.32):
arch/x86/mm/fault.c –
Zmodyfikowana
została
funkcja
no_context_fail
odpowiedzialna za zgłoszenie awarii wykonywanego zadania w przypadku zgłoszenia
przerwania nieprawidłowego odwołania do pami˛eci.
Wykonanie tej funkcji zostało
uzależnione od wartości zwracanej przez nowa˛ funkcj˛e no_context_fail_check,
która działa zgodnie z opisem funkcji F opisanej w 5.6.1 (strona 126) i jej
działanie może być zmodyfikowane z użyciem mechanizmu kprobes.
Jeżeli funkcja
no_context_fail_check zwróci wartość TRUE, to zgłoszenie awarii jest zaniechane,
a działanie zadania zgłaszajacego
˛
przerwanie jest wznowione.
arch/x86/kernel/traps.c – Zmodyfikowana została funkcja fixup_exception
odpowiedzialna za podj˛ecie próby naprawy przerwania general protection fault. Jeżeli
domyślne działanie funkcji nie przyniosło efektu, wywoływana jest dodatkowa funkcja
fixup_exception_check, która działa zgodnie z opisem funkcji F opisanej w 5.6.1
(strona 126) i jej działanie może być zmodyfikowane z użyciem mechanizmu kprobes.
Jeżeli funkcja fixup_exception_check zwróci wartość TRUE, to sygnalizowane jest
naprawienie bł˛edu i działanie zadania zgłaszajacego
˛
przerwanie jest wznowione.
166

Podobne dokumenty