Combining Static and Dynamic Program Analysis Techniques for Checking Relational Properties
Total Page:16
File Type:pdf, Size:1020Kb
Combining Static and Dynamic Program Analysis Techniques for Checking Relational Properties zur Erlangung des akademischen Grades eines Doktors der Naturwissenschaften von der KIT-Fakultät für Informatik des Karlsruher Instituts für Technologie (KIT) genehmigte Dissertation von Mihai Herda aus Bras, ov, Rumänien Tag der mündlichen Prüfung: 13.12.2019 Erster Gutachter: Prof. Dr. Bernhard Beckert Zweiter Gutachter: Prof. Dr. Shmuel Tyszberowicz Combining Static and Dynamic Program Analysis Techniques for Checking Relational Properties Mihai Herda Ich versichere wahrheitsgemäß, die Dissertation bis auf die dort angegebe- nen Hilfen selbständig angefertigt, alle benutzten Hilfsmittel vollständig und genau angegeben und alles kenntlich gemacht zu haben, was aus Arbeiten anderer und eigenen Veröffentlichungen unverändert oder mit Änderungen entnommen wurde. Karlsruhe, Mihai Herda Acknowledgements I thank Prof. Bernhard Beckert for giving me the opportunity to pursue a PhD in his research group and for his useful advice throughout my time as a PhD student. I thank Prof. Shmuel Tyszberowicz for the great collaboration that we had, for his feedback, and for agreeing to be the second reviewer of this thesis. I thank my current and former colleagues, Aboubakr Achraf El Ghazi, Thorsten Bormer, Stephan Falke, David Farago, Christoph Gladisch, Da- niel Grahl, Sarah Grebing, Markus Iser, Michael Kirsten, Jonas Klamroth, Vladimir Klebanov, Marko Kleine Büning, Tianhai Liu, Simone Meinhart, Florian Merz, Jonas Schiffl, Christoph Scheben, Prof. Peter Schmitt, Prof. Carsten Sinz, Mattias Ulbrich, and Alexander Weigl, for the great collabora- tion and for the great discussions that we had during this time. Working with you is and has been a pleasure. I thank the students Etienne Brunner, Stephan Gocht, Holger Klein, Daniel Lentzsch, Joachim Müssig, Joana Plewnia, Ulla Scheler, Chiara Staudenmaier, Benedikt Wagner, and Pascal Zwick, for their work that I had the pleasure to supervise. I thank the researchers form the groups of Prof. Wolfgang Ahrendt, Prof. Reiner Hähnle, Prof. Heiko Mantel, Prof. Ralf Reussner, and Prof. Gregor Snelting with whom I had the pleasure to cooperate. I thank the German Israeli Foundation (GIF), the German Research Foundation (DFG), and the Federal Ministry of Education and Research (BMBF) for financing my work. Last but not least, I thank my family and friends for their continuous moral support. vii Abstract The topic of this thesis belongs to the research area of formal software verification. It deals with checking relational properties of computer programs (i.e., properties that consider two or more program executions). The thesis focuses on two specific relational properties: (1) noninterference and (2) whether a program is a correct slice of another. The noninterference property states that running a program with the same public input values will always produce the same public outputs, regardless of the secret inputs (e.g., a password). This means that the secret inputs do not influence public outputs. Program slicing is a technique to reduce a program by removing statements from it while preserving a specified part of its behavior, such as the value of a variable at a program location. The thesis provides frameworks that allow the user to analyze the two properties for a given program. The thesis advances the state of the art in the area of formal verification of relational properties by providing novel approaches for the analysis on the one hand and by combining existing approaches on the other hand. The thesis contains two parts, each handling one of the two relational properties. Noninterference. The framework for checking noninterference provides new approaches both for automatic test generation and program debugging, and it combines these new approaches with approaches based on deductive verification and dependency graphs. The first new approach provided by this framework allows for the automatic generation of noninterference tests. It allows the user to search for violations of the noninterference property, and it also provides a coverage criterion for the generated test suites that is appropriate for relational properties. The second new approach provided by the framework is a relational debugger for analyzing noninterference coun- terexamples. It employs well-known concepts from program debugging, and it ix Abstract extends them for relational program analysis. To support the user in proving a noninterference property, the framework combines an approach based on dependency graphs with a logic-based approach that uses a theorem prover. Dependency-graph-based approaches compute the dependencies between various program parts and check whether the public output depends on the secure input. Compared with logic-based approaches, dependency-graph- based approaches scale better. However, because they over-approximate the dependencies in a program, they may report false alarms. Two further contributions of the framework are thus represented by two combinations of the logic-based and dependency-graph-based approaches: (1) the dependency- graph-based approach simplifies the program that is checked by logic-based approach, and (2) the logic-based approach proves that certain dependencies computed by the dependency-graph-based approach are over-approximations and can be discarded from the analysis. Program slicing. The second part of the thesis discusses a framework for automatic program slicing. Whereas most state-of-the-art slicing approaches only perform a syntactical analysis of the program, this framework also considers the semantics of the program and can remove more statements from a program. The first contribution of the slicing framework consists of a relational verification approach that was adapted to check whether a slice is valid, (i.e., whether it preserves the specified behavior of the original program). The advantage of using relational verification is that it works automatically for two similar programs—which is the case when considering a slice candidate and an original program. Thus, unlike the few state-of-the-art slicing approaches that consider the semantics of the program, our approach is automatic. The second contribution of this framework is a new strategy for generating slice candidates by refining dynamic slices (i.e., slices which are valid for a single input) by using the counterexamples provided by the relational verifier. x Zusammenfassung Die vorliegende Dissertation ist im Bereich der formalen Verifikation von Software angesiedelt. Sie behandelt die Überprüfung relationaler Eigenschaf- ten von Computerprogrammen, d.h. solche Eigenschaften, die zwei oder mehr Programmausführungen betrachten. Die Dissertation konzentriert sich auf zwei spezifische relationale Eigenschaften: (1) Nichtinterferenz und (2) ob ein Programm ein Slice eines anderen Programms ist. Die Nichtinterferenz- Eigenschaft besagt, dass die Ausführung eines Programms mit den gleichen öffentlichen Eingaben die gleichen öffentlichen Ausgaben produziert und dies unabhängig von den geheimen Eingaben (z.B. eines Passworts) ist. Das bedeutet, dass die geheimen Eingaben die öffentlichen Ausgaben nicht beein- flussen. Programm-Slicing ist eine Technik zur Reduzierung eines Programms durch das Entfernen von Programmbefehlen, sodass ein spezifizierter Teil des Programmverhaltens erhalten bleibt, z.B. der Wert einer Variablen in einer Instruktion in dem Programm. Die Dissertation stellt Frameworks zur Verfügung, die es dem Nutzer ermöglichen, die obigen zwei Eigenschaften für ein gegebenes Programm zu analysieren. Die Dissertation erweitert den Stand der Technik in dem Bereich der Verifikation relationaler Eigenschaften, indem sie einerseits neue Ansätze zur Verfügung stellt und andererseits bereits existierende Ansätze miteinander kombiniert. Die Dissertation enthält jeweils einen Teil für die behandelten zwei relationalen Eigenschaften. Nichtinterferenz. Das Framework zur Überprüfung der Nichtinterferenz stellt neue Ansätze für die automatische Testgenerierung und für das De- buggen des Programms zur Verfügung und kombiniert diese mit Ansätzen, die auf deduktiver Verifikation und Programmabhängigkeitsgraphen basie- ren. Der erste neue Ansatz ermöglicht die automatische Generierung von Nichtinterferenz-Tests. Er ermöglicht dem Nutzer, nach Verletzungen der xi Zusammenfassung Nichtinterferenz-Eigenschaft im Programm zu suchen und stellt zudem ein für relationale Eigenschaften passendes Abdeckungskriterium für die gene- rierten Test-Suites zur Verfügung. Der zweite neue Ansatz ist ein relationaler Debugger zur Analyse von Nichtinterferenz-Gegenbeispielen. Er verwen- det bekannte Konzepte des Programm-Debuggens und erweitert diese für die Analyse relationaler Eigenschaften. Um den Nutzer beim Beweisen der Nichtinterferenz-Eigenschaft zu unterstützen, kombiniert das Framework einen auf Programmabhängigkeitsgraphen basierenden Ansatz mit einem auf Logik basierenden Ansatz, der einen Theorembeweiser verwendet. Auf Programmabhängigkeitsgraphen basierende Ansätze berechnen die Abhän- gigkeiten zwischen den unterschiedlichen Programmteilen und überprüfen, ob die öffentliche Ausgabe von der geheimen Eingabe abhängt. Im Vergleich zu logik-basierten Ansätzen skalieren programmabhängigkeitsgraphen-basierte Ansätze besser. Allerdings, können sie Fehlalarme melden, da sie die Pro- grammabhängigkeiten überapproximieren. Somit bestehen zwei weitere Bei- träge des Frameworks in Kombinationen von programmabhängigkeitsgraphen- und logik basierten Ansätzen: (1) der programmabhängigkeitsgraphen