19 research outputs found

    On Effect Analysis for Programs with Callbacks

    Get PDF
    We introduce a precise interprocedural effect analysis for programs with mutable state, dynamic object allocation, and dynamic dispatch. Our analysis is precise even in the presence of dynamic dispatch where the context-insensitive estimate on the number of targets is very large. This feature makes our analysis appropriate for programs that manipulate first-class functions (callbacks). We first present a framework in which programs are enriched with special effect statements, and define the semantics of both program and effect statements as relations on states. Our framework defines a program composition operator that is sound with respect to relation composition. Computing the summary of a procedure then consists of composing all its program statements to produce a single effect statement. We propose a strategy for applying the composition operator in a way that balances precision and efficiency. We instantiate this framework with a domain for tracking read and write effects, where relations on program states are abstracted as graphs. We implemented the analysis as a plugin for the Scala compiler. We analyzed the Scala standard library containing 58K methods and classified them into several categories according to their effects. Our analysis proves that over one half of all methods are pure. We also analyze how context sensitivity and composition operator application strategies impact the analysis precision and performance

    Effective Detection of Sleep-in-Atomic-Context Bugs in the Linux Kernel

    Get PDF
    International audienceAtomic context is an execution state of the Linux kernel, in which kernel code monopolizes a CPU core. In this state, the Linux kernel may only perform operations that cannot sleep, as otherwise a system hang or crash may occur. We refer to this kind of concurrency bug as a sleep-in-atomic-context (SAC) bug. In practice, SAC bugs are hard to find, as they do not cause problems in all executions. In this paper, we propose a practical static approach named DSAC, to effectively detect SAC bugs in the Linux kernel. DSAC uses three key techniques: (1) a summary-based analysis to identify the code that may be executed in atomic context, (2) a connection-based alias analysis to identify the set of functions referenced by a function pointer, and (3) a path-check method to filter out repeated reports and false bugs. We evaluate DSAC on Linux 4.17, and find 1159 SAC bugs. We manually check all the bugs, and find that 1068 bugs are real. We have randomly selected 300 of the real bugs and sent them to kernel developers. 220 of these bugs have been confirmed, and 51 of our patches fixing 115 bugs have been applied

    Improving systems software security through program analysis and instrumentation

    Get PDF
    Security and reliability bugs are prevalent in systems software. Systems code is often written in low-level languages like C/C++, which offer many benefits but also delegate memory management and type safety to programmers. This invites bugs that cause crashes or can be exploited by attackers to take control of the program. This thesis presents techniques to detect and fix security and reliability issues in systems software without burdening the software developers. First, we present code-pointer integrity (CPI), a technique that combines static analysis with compile-time instrumentation to guarantee the integrity of all code pointers in a program and thereby prevent all control-flow hijack attacks. We also present code-pointer separation (CPS), a relaxation of CPI with better performance properties. CPI and CPS offer substantially better security-to-overhead ratios than the state of the art in control flow hijack defense mechanisms, they are practical (we protect a complete FreeBSD system and over 100 packages like apache and postgresql), effective (prevent all attacks in the RIPE benchmark), and efficient: on SPEC CPU2006, CPS averages 1.2% overhead for C and 1.9% for C/C++, while CPIĂąs overhead is 2.9% for C and 8.4% for C/C++. Second, we present DDT, a tool for testing closed-source device drivers to automatically find bugs like memory errors or race conditions. DDT showcases a combination of a form of program analysis called selective symbolic execution with virtualization to thoroughly exercise tested drivers and produce detailed, executable traces for every path that leads to a failure. We applied DDT to several closed-source Microsoft-certified Windows device drivers and discovered 14 serious new bugs that can cause crashes or compromise security of the entire system. Third, we present a technique for increasing the scalability of symbolic execution by merging states obtained on different execution paths. State merging reduces the number of states to analyze, but the merged states can be more complex and harder to analyze than their individual components. We introduce query count estimation, a technique to reason about the analysis time of merged states and decide which states to merge in order to achieve optimal net performance of symbolic execution. We also introduce dynamic state merging, a technique for merging states that interacts favorably with search strategies employed by practical bug finding tools, such as DDT and KLEE. Experiments on the 96 GNU Coreutils show that our approach consistently achieves several orders of magnitude speedup over previously published results

    Effective Bug Finding

    Get PDF

    A trusted infrastructure for symbolic analysis of event-based web APIs

    Get PDF
    JavaScript has been widely adopted for the development of Web applications, being used for both client and server-side code. Client-side JavaScript programs commonly interact with Web APIs, for instance, to capture the user interaction with the Web page via events. The use of such APIs increases the complexity of JavaScript programs. In fact, most errors in these programs are caused by the misuse of Web APIs. There are several approaches for detecting errors in client-side JavaScript programs, but they either assume the use of a single API or do not model APIs faithfully, giving rise to inconsistent behaviour and lack of trust. We address the problem by developing a trustworthy infrastructure for the static analysis of Web APIs. We focus on two aspects of JavaScript programs: event-driven and message-passing programming, as these paradigms are common sources of confusion among developers. We choose to target the DOM event model and the JavaScript Promises and JavaScript async/await, which facilitate event-driven programming. Additionally, we target the message-passing model of the WebMessaging and WebWorkers APIs. We design formal semantics for events and message-passing to capture fundamental operations required by those APIs, and API reference implementations which are trustworthy in that they follow the respective standards and have been thoroughly tested against their official test suites. Using our formal semantics and reference implementations, we develop JaVerT.Click, the first static symbolic execution tool for JavaScript supporting both event-based and message-passing APIs. We evaluated both the reference implementations and the symbolic execution engine of JaVerT.Click. By testing the reference implementations against their official test suites, we found coverage gaps and issues in the test suites, most of which have been since fixed. By testing the symbolic execution engine against three open-source libraries, we established the bounded correctness of functional properties and found real bugs.Open Acces

    Software Tracing Comparison Using Data Mining Techniques

    Get PDF
    La performance est devenue une question cruciale sur le dĂ©veloppement, le test et la maintenance des logiciels. Pour rĂ©pondre Ă  cette prĂ©occupation, les dĂ©veloppeurs et les testeurs utilisent plusieurs outils pour amĂ©liorer les performances ou suivre les bogues liĂ©s Ă  la performance. L’utilisation de mĂ©thodologies comparatives telles que Flame Graphs fournit un moyen formel de vĂ©rifier les causes des rĂ©gressions et des problĂšmes de performance. L’outil de comparaison fournit des informations pour l’analyse qui peuvent ĂȘtre utilisĂ©es pour les amĂ©liorer par un mĂ©canisme de profilage profond, comparant habituellement une donnĂ©e normale avec un profil anormal. D’autre part, le mĂ©canisme de traçage est un mĂ©canisme de tendance visant Ă  enregistrer des Ă©vĂ©nements dans le systĂšme et Ă  rĂ©duire les frais gĂ©nĂ©raux de son utilisation. Le registre de cette information peut ĂȘtre utilisĂ© pour fournir aux dĂ©veloppeurs des donnĂ©es pour l’analyse de performance. Cependant, la quantitĂ© de donnĂ©es fournies et les connaissances requises Ă  comprendre peuvent constituer un dĂ©fi pour les mĂ©thodes et les outils d’analyse actuels. La combinaison des deux mĂ©thodologies, un mĂ©canisme comparatif de profilage et un systĂšme de traçabilitĂ© peu Ă©levĂ© peut permettre d’évaluer les causes des problĂšmes rĂ©pondant Ă©galement Ă  des exigences de performance strictes en mĂȘme temps. La prochaine Ă©tape consiste Ă  utiliser ces donnĂ©es pour dĂ©velopper des mĂ©thodes d’analyse des causes profondes et d’identification des goulets d’étranglement. L’objectif de ce recherche est d’automatiser le processus d’analyse des traces et d’identifier automatiquement les diffĂ©rences entre les groupes d’exĂ©cutions. La solution prĂ©sentĂ©e souligne les diffĂ©rences dans les groupes prĂ©sentant une cause possible de cette diffĂ©rence, l’utilisateur peut alors bĂ©nĂ©ficier de cette revendication pour amĂ©liorer les exĂ©cutions. Nous prĂ©sentons une sĂ©rie de techniques automatisĂ©es qui peuvent ĂȘtre utilisĂ©es pour trouver les causes profondes des variations de performance et nĂ©cessitant des interfĂ©rences mineures ou non humaines. L’approche principale est capable d’indiquer la performance en utilisant une mĂ©thodologie de regroupement comparative sur les exĂ©cutions et a Ă©tĂ© appliquĂ©e sur des cas d’utilisation rĂ©elle. La solution proposĂ©e a Ă©tĂ© mise en oeuvre sur un cadre d’analyse pour aider les dĂ©veloppeurs Ă  rĂ©soudre des problĂšmes similaires avec un outil diffĂ©rentiel de flamme. À notre connaissance, il s’agit de la premiĂšre tentative de corrĂ©ler les mĂ©canismes de regroupement automatique avec l’analyse des causes racines Ă  l’aide des donnĂ©es de suivi. Dans ce projet, la plupart des donnĂ©es utilisĂ©es pour les Ă©valuations et les expĂ©riences ont Ă©tĂ© effectuĂ©es dans le systĂšme d’exploitation Linux et ont Ă©tĂ© menĂ©es Ă  l’aide de Linux Trace Toolkit Next Generation (LTTng) qui est un outil trĂšs flexible avec de faibles coĂ»ts gĂ©nĂ©raux.----------ABSTRACT: Performance has become a crucial matter in software development, testing and maintenance. To address this concern, developers and testers use several tools to improve the performance or track performance related bugs. The use of comparative methodologies such as Flame Graphs provides a formal way to verify causes of regressions and performance issues. The comparison tool provides information for analysis that can be used to improve the study by a deep profiling mechanism, usually comparing normal with abnormal profiling data. On the other hand, Tracing is a popular mechanism, targeting to record events in the system and to reduce the overhead associated with its utilization. The record of this information can be used to supply developers with data for performance analysis. However, the amount of data provided, and the required knowledge to understand it, may present a challenge for the current analysis methods and tools. Combining both methodologies, a comparative mechanism for profiling and a low overhead trace system, can enable the easier evaluation of issues and underlying causes, also meeting stringent performance requirements at the same time. The next step is to use this data to develop methods for root cause analysis and bottleneck identification. The objective of this research project is to automate the process of trace analysis and automatic identification of differences among groups of executions. The presented solution highlights differences in the groups, presenting a possible cause for any difference. The user can then benefit from this claim to improve the executions. We present a series of automated techniques that can be used to find the root causes of performance variations, while requiring small or no human intervention. The main approach is capable to identify the performance difference cause using a comparative grouping methodology on the executions, and was applied to real use cases. The proposed solution was implemented on an analysis framework to help developers with similar problems, together with a differential flame graph tool. To our knowledge, this is the first attempt to correlate automatic grouping mechanisms with root cause analysis using tracing data. In this project, most of the data used for evaluations and experiments were done with the Linux Operating System and were conducted using the Linux Trace Toolkit Next Generation (LTTng), which is a very flexible tool with low overhead

    Deductive Synthesis and Repair

    Get PDF
    In this thesis, we explore techniques for the development of recursive functional programs over unbounded domains that are proved correct according to their high-level specifications. We present algorithms for automatically synthesizing executable code, starting from the speci- fication alone. We implement these algorithms in the Leon system. We augment relational specifications with a concise notation for symbolic tests, which are are helpful to characterize fragments of the functionsĂą behavior. We build on our synthesis procedure to automatically repair invalid functions by generating alternative implementations. Our approach therefore formulates program repair in the framework of deductive synthesis and uses the existing program structure as a hint to guide synthesis. We rely on user-specified tests as well as automatically generated ones to localize the fault. This localization enables our procedure to repair functions that would otherwise be out of reach of our synthesizer, and ensures that most of the original behavior is preserved. We also investigate multiple ways of enabling Leon programs to interact with external, un- trusted code. For that purpose, we introduce a precise inter-procedural effect analysis for arbitrary Scala programs with mutable state, dynamic object allocation, and dynamic dispatch. We analyzed the Scala standard library containing 58000 methods and classified them into sev- eral categories according to their effects. Our analysis proves that over one half of all methods are pure, identifies a number of conditionally pure methods, and computes summary graphs and regular expressions describing the side effects of non-pure methods. We implement the synthesis and repair algorithms within the Leon system and deploy them as part of a novel interactive development environment available as a web interface. Our implementation is able to synthesize, within seconds, a number of useful recursive functions that manipulate unbounded numbers and data structures. Our repair procedure automatically locates various kinds of errors in recursive functions and fixes them by synthesizing alternative implementations

    Human-centric verification for software safety and security

    Get PDF
    Software forms a critical part of our lives today. Verifying software to avoid violations of safety and security properties is a necessary task. It is also imperative to have an assurance that the verification process was correct. We propose a human-centric approach to software verification. This involves enabling human-machine collaboration to detect vulnerabilities and to prove the correctness of the verification. We discuss two classes of vulnerabilities. The first class is Algorithmic Complexity Vulnerabilities (ACV). ACVs are a class of software security vulnerabilities that cause denial-of-service attacks. The description of an ACV is not known a priori. The problem is equivalent to searching for a needle in the haystack when we don\u27t know what the needle looks like. We present a novel approach to detect ACVs in web applications. We present a case study audit from DARPA\u27s Space/Time Analysis for Cybersecurity (STAC) program to illustrate our approach. The second class of vulnerabilities is Memory Leaks. Although the description of the Memory Leak (ML) problem is known, a proof of the correctness of the verification is needed to establish trust in the results. We present an approach inspired by the works of Alan Perlis to compute evidence of the verification which can be scrutinized by a human to prove the correctness of the verification. We present a novel abstraction, the Evidence Graph, that succinctly captures the verification evidence and show how to compute the evidence. We evaluate our approach against ML instances in the Linux kernel and report improvement over the state-of-the-art results. We also present two case studies to illustrate how the Evidence Graph can be used to prove the correctness of the verification

    Programming Languages and Systems

    Get PDF
    This open access book constitutes the proceedings of the 29th European Symposium on Programming, ESOP 2020, which was planned to take place in Dublin, Ireland, in April 2020, as Part of the European Joint Conferences on Theory and Practice of Software, ETAPS 2020. The actual ETAPS 2020 meeting was postponed due to the Corona pandemic. The papers deal with fundamental issues in the specification, design, analysis, and implementation of programming languages and systems

    Techniques for Detection, Root Cause Diagnosis, and Classification of In-Production Concurrency Bugs

    Get PDF
    Concurrency bugs are at the heart of some of the worst bugs that plague software. Concurrency bugs slow down software development because it can take weeks or even months before developers can identify and fix them. In-production detection, root cause diagnosis, and classification of concurrency bugs is challenging. This is because these activities require heavyweight analyses such as exploring program paths and determining failing program inputs and schedules, all of which are not suited for software running in production. This dissertation develops practical techniques for the detection, root cause diagnosis, and classification of concurrency bugs for inproduction software. Furthermore, we develop ways for developers to better reason about concurrent programs. This dissertation builds upon the following principles: — The approach in this dissertation spans multiple layers of the system stack, because concurrency spans many layers of the system stack. — It performs most of the heavyweight analyses in-house and resorts to minimal in-production analysis in order to move the heavy lifting to where it is least disruptive. — It eschews custom hardware solutions that may be infeasible to implement in the real world. Relying on the aforementioned principles, this dissertation introduces: 1. Techniques to automatically detect concurrency bugs (data races and atomicity violations) in-production by combining in-house static analysis and in-production dynamic analysis. 2. A technique to automatically identify the root causes of in-production failures, with a particular emphasis on failures caused by concurrency bugs. 3. A technique that given a data race, automatically classifies it based on its potential consequence, allowing developers to answer questions such as “can the data race cause a crash or a hang?”, or “does the data race have any observable effect?”. We build a toolchain that implements all the aforementioned techniques. We show that the tools we develop in this dissertation are effective, incur low runtime performance overhead, and have high accuracy and precision
    corecore