Correct Audit Logging: Theory and Practice

. Retrospective security has become increasingly important to the theory and practice of cyber security, with auditing a crucial component of it. However, in systems where auditing is used, programs are typically instrumented to generate audit logs using manual, ad-hoc strategies. This is a potential source of error even if log analysis techniques are formal, since the relation of the log itself to program execution is unclear. This paper focuses on provably correct program rewriting algorithms for instrumenting formal logging speciﬁcations. Correctness guarantees that the execution of an instrumented program produces sound and complete audit logs, properties deﬁned by an information containment relation between logs and the program’s logging semantics. We also propose a program rewriting approach to instrumentation for audit log generation, in a manner that guarantees correct log generation even for untrusted programs. As a case study, we develop such a tool for OpenMRS, a popular medical records management system, and consider instrumentation of break the glass policies.


Introduction
Retrospective security is the enforcement of security, or detection of security violations, after program execution [33,36,40].Many real-world systems use retrospective security.For example, the financial industry corrects errors and fraudulent transactions not by proactively preventing suspicious transactions, but by retrospectively correcting or undoing these problematic translations.Another example is a hospital whose employees are trusted to access confidential patient records, but who might (rarely) violate this trust [17].Upon detection of such violations, security is enforced retrospectively by holding responsible employees accountable [41].
Retrospective security cannot be achieved entirely by traditional computer security mechanisms, such as access control, or information-flow control.Reasons include that detection of violations may be external to the computer system (such as consumer reports of fraudulent transactions, or confidential patient information appearing in news media), the high cost of access denial (e.g., preventing emergency-room physicians from accessing medical records) coupled with high trust of systems users (e.g., users are trusted employees that rarely violate this trust) [42].In addition, remediation actions to address violations may also be external to the computer system, such as reprimanding employees, prosecuting law suits, or otherwise holding users accountable for their actions [41].
Auditing underlies retrospective security frameworks and has become increasingly important to the theory and practice of cyber security.By maintaining a record of appropriate aspects of a computer system's execution, an audit log (and subsequent examination of the audit log) can enable detection of violations, provide sufficient evidence to hold users accountable for their actions, and support other remediation actions.For example, an audit log can be used to determine post facto which users performed dangerous operations, and can provide evidence for use in litigation.
However, despite the importance of auditing to real-world security, relatively little work has focused on the formal foundations of auditing, particularly with respect to defining and ensuring the correctness of audit log generation.Indeed, correct and efficient audit log generation poses at least two significant challenges.First, it is necessary to record sufficient and correct information in the audit log.If a program is manually instrumented, it is possible for developers to fail to record relevant events.Recent work showed that major health informatics systems do not log sufficient information to determine compliance with HIPAA policies [30].Second, an audit log should ideally not contain more information than needed.While it is straightforward to collect sufficient information by recording essentially all events in a computer system, this can cause performance issues, both slowing down the system due to generating massive audit logs, and requiring the handling of extremely large audit logs.Excessive data collection is a key challenge for auditing [23,14,29], and is a critical factor in the design of tools that generate and employ audit logs (e.g., spam filters [15]).
A main goal of this paper is to establish formal conditions for audit logs, that can be used to establish correctness conditions for logging instrumentation.We define a general semantics of audit logs using the theory of information algebra [32], and interpret both program execution traces and audit logs as information elements.A logging specification defines the intended relation between the information in traces and in audit logs.An audit log is correct if it satisfies this relation.A benefit of this formulation is that it separates logging specifications from programs, rather than burying them in code and implementation details.
Separating logging specifications from programs allows a clean declaration of what instrumentation should accomplish, and enables algorithms for implementing general classes of logging specifications that are provably correct.As we will show, correct instrumentation of logging specifications is a safety property, hence enforceable by security automata [38].Inspired by related approaches to security automata implementation [21], we focus on program rewriting to automatically enforce correct audit instrumentation.Program rewriting has a number of practical benefits versus, for example, program monitors, such as lower OS process management overhead.
We consider a case study of our approach, a program rewriting algorithm for correct instrumentation of logging specifications in OpenMRS (openmrs.org),a popular open source medical records software system.Our tool allows system administrators to define logging specifications which are automatically instrumented in OpenMRS legacy code.Implementation details and optimizations are handled transparently by the general program rewriting algorithm, not the logging specification.Formal foundations ensure that logging specifications are implemented correctly by the algorithm.In particular, we show how our system can implement "break the glass" auditing policies.

A Motivating Example from Practice
Although audit logs contain information about program execution, they are not just a straightforward selection of program events.Illustrative examples from practice in-clude so-called "break the glass policies" used in electronic medical record systems [35].These policies use access control to disallow care providers from performing sensitive operations such as viewing patient records, however care providers can "break the glass" in an emergency situation to temporarily raise their authority and access patient records, with the understanding that subsequent sensitive operations will be logged and potentially audited.One potential accountability goal is the following: In the event that a patient's sensitive information is inappropriately leaked, determine who accessed a given patient's files due to "breaking the glass." Since it cannot be predicted a priori whose information may leak, this goal can be supported by using an audit log that records all reads of sensitive files following glass breaking.To generate correct audit logs, programs must be instrumented for logging appropriately, i.e., to implement the following logging specification that we call LS H : LS H : Record in the log all patient information file reads following a break the glass event, along with the identity of the user that broke the glass.
If at some point in time in the future it is determined that a specific patient P's information was leaked, logs thus generated can be analyzed with the following query that we call LQ H : LQ H : Retrieve the identity of all users that read P's information files.
The specification LS H and the query LQ H together constitute an auditing policy that directly supports the above-stated accountability goal.Their separation is useful since at the time of execution the information leak is unknown, hence P is not known.Thus while it is possible to implement LS H as part of program execution, LQ H must be implemented retrospectively.
It is crucial to the enforcement of the above accountability goal that LS H is implemented correctly.If logging is incomplete then some potential recipients may be missed.If logging is overzealous then bloat is possible and audit logs become "write only".These types of errors are common in practice [30].To establish formal correctness of instrumentation for audit logs, it is necessary to define a formal language of logging specifications, and establish techniques to guarantee that instrumented programs satisfy logging specifications.That is the focus of this paper.Other work has focused on formalisms for querying logs [39,18], however these works presuppose correctness of audit logs for true accountability.

Threat Model
With respect to program rewriting (i.e., automatic techniques to instrument existing programs to satisfy a logging specification), we regard the program undergoing instrumentation as untrusted.That is, the program source code may have been written to avoid, confuse, or subvert the automatic instrumentation techniques.We do, however, assume that the source code is well-formed (valid syntax, well-typed, etc.).Moreover, we trust the compiler, the program rewriting algorithm, and the runtime environment in which the instrumented program will ultimately be executed.Confidentiality and nonmalleability of generated audit logs, while important, is beyond the scope of this paper.

A Semantics of Audit Logging
Our goal in this Section is to formally characterize logging specifications and correctness conditions for audit logs.To obtain a general model, we leverage ideas from the theory of information algebra [32], which is an abstract mathematical framework for information systems.In short, we interpret program traces as information, and logging specifications as functions from traces to information.This separates logging specifications from their implementation in code, and defines exactly the information that should be in an audit log.This in turn establishes correctness conditions for audit logging implementations.
Following [38], an execution trace τ = κ 0 κ 1 κ 2 . . . is a possibly infinite sequence of configurations κ that describe the state of an executing program.We deliberately leave configurations abstract, but examples abound and we explore a specific instantiation for a λ-calculus in Section 4. Note that an execution trace τ may represent the partial execution of a program, i.e. the trace τ may be extended with additional configurations as the program continues execution.We use metavariables τ and σ to range over traces.
An information algebra contains information elements X (e.g. a set of logical assertions) taken from a set Φ (the algebra).A partial ordering is induced on Φ by the so-called information ordering relation ≤, where intuitively for X, Y ∈ Φ we have X ≤ Y iff Y contains at least as much information as X, though its precise meaning depends on the particular algebra.We say that X and Y are information equivalent, and write X = Y , iff X ≤ Y and Y ≤ X.We assume given a function • that is an injective mapping from traces to Φ.This mapping interprets a given trace as information, where the injective requirement ensures that information is not lost in the interpretation.For example, if σ is a proper prefix of τ and thus contains strictly less information, then formally σ ≤ τ .We intentionally leave both Φ and • underspecified for generality, though application of our formalism to a particular logging implementation requires instantiation of them.We discuss an example in Section 3.
We let LS range over logging specifications, which are functions from traces to Φ.As for Φ and • , we intentionally leave the language of specifications abstract, but consider a particular instantiation in Section 3. Intuitively, LS (τ ) denotes the information that should be recorded in an audit log during the execution of τ given specification LS , regardless of whether τ actually records any log information, correctly or incorrectly.We call this the semantics of the logging specification LS .
We assume that auditing is implementable, requiring at least that all conditions for logging any piece of information must be met in a finite amount of time.As we will show, this restriction implies that correct logging instrumentation is a safety property [38].Definition 1.We require of any logging specification LS that for all traces τ and information X ≤ LS (τ ), there exists a finite prefix σ of τ such that X ≤ LS (σ).
It is crucial to observe that some logging specifications may add information not contained in traces to the auditing process.Security information not relevant to program execution (such as ACLs), interpretation of event data (statistical or otherwise), etc., may be added by the logging specification.For example, in the OpenMRS system, logging of sensitive operations includes a human-understandable "type" designation which is not used by any other code.Thus, given a trace τ and logging specification LS , it is not necessarily the case that LS (τ ) ≤ τ .Audit logging is not just a filtering of program events.

Correctness Conditions for Audit Logs
A logging specification defines what information should be contained in an audit log.In this section we develop formal notions of soundness and completeness as audit log correctness conditions.We use metavariable L to range over audit logs.Again, we intentionally leave the language of audit logs unspecified, but assume that the function • is extended to audit logs, i.e. • is an injective mapping from audit logs to Φ. Intuitively, L denotes the information in L, interpreted as an element of Φ.
An audit log L is sound with respect to a logging specification LS and trace τ if the log information is contained in LS (τ ).Similarly, an audit log is complete with respect to a logging specification if it contains all of the information in the logging specification's semantics.Crucially, both definitions are independent of the implementation details that generate L. Definition 2. Audit log L is sound with respect to logging specification LS and execution trace τ iff L ≤ LS (τ ).Similarly, audit log L is complete with respect to logging specification LS and execution trace τ iff LS (τ ) ≤ L .
The relation to log queries.As discussed in Section 1.1, we make a distinction between logging specifications such as LS H which define how to record logs, and log queries such as LQ H which ask questions of logs, and our notions of soundness and completeness apply strictly to logging specifications.However, any logging query must assume a logging specification semantics, hence a log that is demonstrably sound and complete provides the same answers on a given query that an "ideal" log would.This is an important property that is discussed in previous work, e.g. as "sufficiency" in [6].

Correct Logging Instrumentation is a Safety Property
In case program executions generate audit logs, we write τ L to mean that a finite trace τ generates L, i.e. τ = κ 0 . . .κ n and logof (κ n ) = L where logof (κ) denotes the audit log in configuration κ, i.e. the residual log after execution of the full trace.Ideally, information that should be added to an audit log, is added to an audit log, immediately as it becomes available.This ideal is formalized as follows.
Definition 3.For all logging specifications LS , the trace τ is ideally instrumented for LS iff for all finite prefixes σ of τ we have σ L where L is sound and complete with respect to LS and σ.
We observe that the restriction imposed on logging specifications by Definition 1, implies that ideal instrumentation of any logging specification is a safety property in the sense defined by Schneider [38] 1 .
Theorem 1.For all logging specifications LS , the set of ideally instrumented traces is a safety property.
This result implies that e.g.edit automata can be used to enforce instrumentation of logging specifications (see our Technical Report [3]).However, theory related to safety properties and their enforcement by execution monitors [38,4] do not provide an adequate semantic foundation for audit log generation, nor an account of soundness and completeness of audit logs.

Implementing Logging Specifications with Program Rewriting
The above-defined correctness conditions for audit logs provide a foundation on which to establish correctness of logging implementations.Here we consider program rewriting approaches.Since rewriting concerns specific languages, we introduce an abstract notion of programs p with an operational semantics that can produce a trace τ .We write p ⇓ σ iff program p can produce execution trace τ , either deterministically or non-deterministically, and σ is a finite prefix of τ .
A rewriting algorithm R is a (partial) function that takes a program p in a source language and a logging specification LS and produces a new program, R(p, LS ), in a target language. 2The intent is that the target program is the result of instrumenting p to produce an audit log appropriate for the logging specification LS .A rewriting algorithm may be partial, in particular because it may only be intended to work for a specific set of logging specifications.
Ideally, a rewriting algorithm should preserve the semantics of the program it instruments.That is, R is semantics-preserving if the rewritten program simulates the semantics of the source code, modulo logging steps.We assume given a correspondence relation :≈ on execution traces.A coherent definition of correspondence should be similar to a bisimulation, but it is not necessarily symmetric nor a bisimulation, since the instrumented target program may be in a different language than the source program.We deliberately leave the correspondence relation underspecified, as its definition will depend on the instantiation of the model.We provide an explicit definition of correspondence for λ-calculus source and target languages in Section 4. Definition 4. Rewriting algorithm R is semantics preserving iff for all programs p and logging specifications LS such that R(p, LS ) is defined, all of the following hold: 1.For all traces τ such that p ⇓ τ there exists τ with τ :≈ τ and R(p, LS ) ⇓ τ .2. For all traces τ such that R(p, LS ) ⇓ τ there exists a trace τ such that τ :≈ τ and p ⇓ τ .
In addition to preserving program semantics, a correctly rewritten program constructs a log in accordance with the given logging specification.More precisely, if LS is a given logging specification and a trace τ describes execution of a source program, rewriting should produce a program with a trace τ that corresponds to τ (i.e., τ :≈ τ ), where the log L generated by τ contains the same information as LS (τ ), or at least a sound approximation.Some definitions of :≈ may allow several target-language traces to correspond to source-language traces (as for example in Section 4, Definition 10).In any case, we expect that at least one simulation exists.Hence we write simlogs(p, τ ) to denote a nonempty set of logs L such that, given a finite source language trace τ and target program p, there exists some trace τ where p ⇓ τ and τ :≈ τ and τ L. The name simlogs evokes the relation to logs resulting from simulating executions in the target language.
The following definitions then establish correctness conditions for rewriting algorithms.Note that satisfaction of either of these conditions only implies condition (1) of Definition 4, not condition (2), so semantics preservation is an independent condition.Definition 5. Rewriting algorithm R is sound/complete iff for all programs p, logging specifications LS , and finite traces τ where p ⇓ τ , for all L ∈ simlogs(R(p, LS ), τ ) it is the case that L is sound/complete with respect to LS and τ .

Languages for Logging Specifications
Now we go into more detail about information algebra and why it is a good foundation for logging specifications and semantics.We use the formalism of information algebras to characterize and compare the information contained in an audit log with the information contained in an actual execution.For a detailed account of information algebra, the reader is referred to a definitive survey paper [32]-available space disallows a detailed account here.In short, in addition to a definition of the elements of Φ, any information algebra Φ includes two basic operators: -Combination: The operation X ⊗ Y combines the information in elements X, Y ∈ Φ. -Focusing: The operation X ⇒S isolates the elements of X ∈ Φ that are relevant to a sublanguage S, i.e. the subpart of X specified by S.
Focusing and combination must additionally satisfy certain properties (see our Technical Report [3]).The definitions of elements X ∈ Φ, sublanguages S, combination, and focusing constitute the definition of the algebra.In all cases, the relation X ≤ Y holds iff X ⊗ Y = Y .Proving that ⊗ has been correctly defined for an algebra implies that ≤ is a partial order [32].

Support for Various Approaches
Various approaches are taken to audit log generation and representation, including logical [18], database [1], and probabilistic approaches [43].Information algebra is sufficiently general to contain relevant systems as instances, so our notions of soundness and completeness can apply broadly.Here we discuss logical and database approaches.
First Order Logic (FOL) Logics have been used in several well-developed auditing systems [24,10], for the encoding of both audit logs and queries.FOL in particular is attractive due to readily available implementation support, e.g.Datalog and Prolog.Let Greek letters φ and ψ range over FOL formulas and let capital letters X, Y, Z range over sets of formulas.We posit a sound and complete proof theory supporting judgements of the form X φ.
In this text we assume without loss of generality a natural deduction proof theory.
Elements of our algebra are sets of formulas closed under logical entailment.Intuitively, given a set of formulas X, the closure of X is the set of formulas that are logically entailed by X, and thus represents all the information contained in X.In spirit, we follow the treatment of sentential logic as an information algebra explored in related foundational work [32], however our definition of closure is syntactic, not semantic.Definition 6.We define a closure operation C, and a set Φ FOL of closed sets of formulas: Note in particular that C(∅) is the set of logical tautologies.
Let Preds be the set of all predicate symbols, and let S ⊆ Preds be a set of predicate symbols.We define sublanguage L S to be the set of well-formed formulas over predicate symbols in S (and including boolean atoms T and F , and closed under the usual first-order connectives and binders).We will use sublanguages to define refinement operations in our information algebra.Subset containment induces a lattice structure, denoted S, on the set of all sublanguages, with F = L Preds as the top element.Now we can define the focus and combination operators, which are the fundamental operators of an information algebra.Focusing isolates the component of a closed set of formulas that is in a given sublanguage.Combination closes the union of closed sets of formulas.Intuitively, the focus of a closed set of formulas X to sublanguage L is the refinement of the information in X to the formulas in L. The combination of closed sets of formulas X and Y combines the information of each set.Definition 7. Define: These definitions of focusing and combination enjoy a number of properties within the algebra, as stated in the following Theorem, establishing that the construction is a domain-free information algebra [31].FOL has been treated as an information algebra before, but our definitions of combination and focusing and hence the result are novel.
Theorem 2. Structure (Φ FOL , S) with focus operation X ⇒S and combination operation X ⊗ Y forms a domain-free information algebra.
In addition, to interpret traces and logs as elements of this algebra, i.e. to define the function • , we assume existence of a function toFOL(•) that injectively maps traces and logs to sets of FOL formulas, and then take • = C(toFOL(•)).To define the range of toFOL(•), that is, to specify how trace information will be represented in FOL, we assume the existence of configuration description predicates P which are each at least unary.Each configuration description predicate fully describes some element of a configuration κ, and the first argument is always a natural number t, indicating the time at which the configuration occurred.A set of configuration description predicates with the same timestamp describes a configuration, and traces are described by the union of sets describing each configuration in the trace.In particular, the configuration description predicates include predicate Call(t, f, x), which indicates that function f is called at time t with argument x.We will fully define toFOL(•) when we discuss particular source and target languages for program rewriting.
Example 1.We return to the example described in Section 1.1 to show how FOL can express break the glass logging specifications.Adapting a logic programming style, the trace of a program can be viewed as a fact base, and the logging specification LS H performs resolution of a LoggedCall predicate, defined via the following Horn clause we call ψ H : Here we imagine that breakGlass is a break the glass function where u identifies the current user and PatientInfo is a predicate specifying which files contain patient information.The log contains only valid instances of LoggedCall given a particular trace, which specify the user and sensitive information accessed following glass breaking, which otherwise would be disallowed by a separate access control policy.
Formally, we define logging specifications in a logic programming style by using combination and focusing.Any logging specification is parameterized by a sublanguage S that identifies the predicate(s) to be resolved and Horn clauses X that define it/them, hence we define a functional spec from pairs (X, S) to specifications LS , where we use λ as a binder for function definitions in the usual manner: Definition 8.The function spec is given a pair (X, S) and returns a FOL logging specification, i.e. a function from traces to elements of Φ FOL : spec(X, S) = λτ.(τ ⊗ C(X)) ⇒S .
In any logging specification spec(X, S), we call X the guidelines.
The above example LS H would then be formally defined as spec(ψ H , {LoggedCall}).
Relational Database Relational algebra is a canonical example of an information algebra, though we provide a different formulation than the standard one [32] since the latter is not suited to our purpose here.We define databases D as sets of relations, where a relation X is a set of tuples.We write ((a 1 : x 1 ), ..., (a n : x 1 )) to denote an n-ary tuple with attributes (aka label) a i associated with values x i .Databases are elements of the information algebra, and sublanguages S are collections of sets of attributes.Each set of attributes corresponds to a specific relation.We define focusing as the restriction to particular relations in a database, and combination as the union of databases.
Hence, letting ≤ RA denote the relational algebra information ordering, We refer to this algebra as Φ RA .The details of our formulation and the proof that it satisfies the required properties is given in our Technical Report [3].
Relational databases are heavily used for storing and querying audit logs, so this formulation is crucial for practical application of our correctness properties, as discussed in Section 5.

Transforming and Combining Audit Logs
Multiple audit logs from different sources are often combined in practice.Also, logging information is often transformed for storage and communication.For example, log data may be generated in common event format (CEF), which is parsed and stored in relational database tables, and subsequently exported and communicated via JSON.In all cases, it is necessary to characterize the effect of transformation (if any) on log information, and relate queries on various representations to the logging specification semantics.Otherwise, it is unclear what is the relation of log queries to log-generating programs.
To address this, information algebra provides a useful concept called monotone mapping.Given two information algebras Ψ 1 and Ψ 2 with ordering relations ≤ 1 and ≤ 2 respectively, a mapping µ from elements X, Y of For example, assuming that Ψ 1 is our FOL information algebra while Ψ 2 is relational algebra, we can define a monotone mapping using a least Herbrand interpretation [11], denoted H, and by positing a function attrs from n-ary predicate symbols to functions mapping numbers 1, ..., n to labels.That is, attrs(P)(n) is the label associated with the nth argument of predicate P. We require that if P = Q then attrs(P)(j) = attrs(Q)(k) for all j, k.To map predicates to tuples we have: tuple(P(x 1 , . . ., x n )) = ((attrs(P)(1) : x 1 ), . . ., (attrs(P)(n) : Then to obtain a relation from all valid instances of a particular predicate P given formulas X we define: R P (X) = {tuple(P(x 1 , . . ., x n )) | P(x 1 , . . ., x n ) ∈ H(X)} Now we define the function rel which is collection of all relations obtained from X, where P 1 , ..., P n are the predicate symbols occurring in X: Thus, if we wish to generate an audit log L as a set of FOL formulas, but ultimately store the data in a relational database, we are still able to maintain a formal relation between stored logs and the semantics of a given trace τ and specification LS .E.g., if a log L is sound with respect to τ and LS , then rel ( L ) ≤ RA rel (LS (τ )).While the data in rel ( L ) may very well be broken up into multiple relations in practice, e.g. to compress data and/or for query optimization, the formalism also establishes correctness conditions for the transformation that relate resulting information to the logging semantics LS (τ ) by way of the mapping.We reify this idea in our OpenMRS implementation as discussed in Section 5.2.

Rewriting Programs with Logging Specifications
Since correct logging instrumentation is a safety property (2.2), there are several possible implementation strategies.For example, one could define an edit automata that enforces the property (see our Technical Report [3]), that could be implemented either as a separate program monitor or using IRM techniques [21].But since we are interested in program rewriting for a particular class of logging specifications, the approach we discuss here is more simply stated and proven correct than a general IRM methodology.
We specify a class of logging specifications of interest, along with a program rewriting algorithm that is sound and complete for it.We consider a basic λ-calculus that serves as formal setting to establish correctness of a program rewriting approach to correct instrumentation of logging specification.We use this same approach to implement an auditing tool for OpenMRS, described in the next Section.The supported class of logging specifications is predicated on temporal properties of function calls and characteristics of their arguments.This class has practical potential since security-sensitive operations are often packaged as functions or methods (e.g. in medical records software [37]), and the supported class allows complex policies such as break the glass to be expressed.The language of logging specifications is FOL, and we use Φ FOL to define the semantics of logging and prove correctness of the algorithm.

Source Language
We first define a source language Λ call , including the definitions of configurations, execution traces, and function toFOL(•) that shows how we concretely model execution traces in FOL.
Language Λ call is a simple call-by-value λ-calculus with named functions.A Λ call program is a pair (e, C) where e is an expression, and C is a codebase which maps function names to function definitions.A Λ call configuration is a triple (e, n, C), where e is the expression remaining to be evaluated, n is a timestamp (a natural number) that indicates how many steps have been taken since program execution began, and C is a codebase.The codebase does not change during program execution.
The syntax of Λ call is as follows.The small-step semantics of Λ call is defined as follows. β An execution trace τ is a sequence of configurations, and for a program p = (e, C) and execution trace τ = κ 0 . . .κ n we define p ⇓ τ if and only if κ 0 = (e, 0, C) and for all i ∈ 1..n we have κ i−1 → κ i .

Specifications Based on Function Call Properties
We define a class Calls of logging specifications that capture temporal properties of function calls, such as those reflected in break the glass policies.We restrict specification definitions to safe Horn clauses to ensure applicability of well-known results and total algorithms such as Datalog [11].Specifications in Calls support logging of calls to a specific function f that happen after functions g 1 , . . ., g n are called.Conditions on all function arguments, and times of their invocation, can be defined via a predicate φ.Hence more precise requirements can be imposed, e.g. a linear ordering on function calls, particular values of functions arguments, etc. Definition 9. Calls is the set of all logging specifications spec(X, {LoggedCall}) where X contains a safe Horn clause of the following form: While set X may contain other safe Horn clauses, in particular definitions of predicates occurring in φ, no other Horn clause in X uses the predicate symbols LoggedCall, Value, Context, Call, App, or Codebase.For convenience in the following, we define Logevent(LS ) = f and Triggers(LS ) = {g 1 , ..., g n }.
We note that specifications in Calls clearly satisfy Definition 1, since preconditions for logging a particular call to f must be satisfied at the time of that call.

Target Language
The syntax of target language Λ log extends Λ call syntax with a command to track logging preconditions (callEvent(f , v)), i.e. calls to logging triggers, and a command to emit log entries (emit(f , v)).Configurations are extended to include a set X of logging preconditions, and an audit log L. The semantics of Λ log extends the semantics of Λ call with new rules for commands callEvent(f , v) and emit(f , v), which update the set of logging preconditions and audit log respectively.An instrumented program uses the set of logging preconditions to determine when it should emit events to the audit log.The semantics is parameterized by a guideline X Guidelines , typically taken from a logging specification.Given the definition of Calls, these semantics would be easy to implement using e.g. a Datalog proof engine.
Precondition X, n, L, C) → (e, X, n, L, C) Note that to ensure that these instrumentation commands do not change execution behavior, the configuration's time is not incremented when callEvent(f , v) and emit(f , v) are evaluated.That is, the configuration time counts the number of source language computation steps.
To establish correctness of program rewriting, we need to define a correspondence relation :≈.Source language execution traces and target language execution traces correspond if they represent the same expression evaluated to the same point.We make special cases for when the source execution is about to perform a function application that the target execution will track or log via an callEvent(f , v) or emit(f , v) command.In these cases, the target execution may be ahead by one or two steps, allowing time for addition of information to the log.Definition 10.Given source language execution trace τ = κ 0 . . .κ m and target language execution trace τ = κ 0 . . .κ n , where κ i = (e i , t i , C i ) and κ i = (e i , X i , t i , L i , C i ), τ :≈ τ iff e 0 = e 0 and either 1. e m = e n (taking = to mean syntactic equivalence); or 2. e m = e n−1 and e n = callEvent(f , v); e for some expressions f , v, and e ; or 3. e m = e n−2 and e n = emit(f , v); e for some expressions f , v, and e .
Finally, we need to define toFOL(L) for audit logs L produced by an instrumented program.Since our audit logs are just sets of formulas of the form LoggedCall(t, f , v), we define toFOL(L) = L.

Program Rewriting Algorithm
Our program rewriting algorithm R Λ call takes a Λ call program p = (e, C), a logging specification LS = spec(X Guidelines , {LoggedCall}) ∈ Calls, and produces a Λ log program p = (e , C ) such that e and e are identical, and C is identical to C except for the addition of callEvent(h, v) and emit(h, v) commands.The algorithm is straightforward: we modify the codebase to add callEvent(h, v) to the definition of any function h ∈ Triggers(LS ) ∪ {Logevent(LS )} and add emit(f , v) to the definition of function f = Logevent(LS ).where

C(f ) otherwise
This algorithm obeys the required properties, i.e. it is both semantics preserving and sound and complete for a given logging specification.

Case Study on a Medical Records System
As a case study, we have developed a tool [2] that enables automatic instrumentation of logging specifications for the OpenMRS system.The implementation is based on the formal model developed in Section 4 which enjoys a correctness guarantee.The logging information is stored in a SQL database consisting of multiple tables, and the correctness of this scheme is established via the monotone mapping defined in Section 3.2.We have also considered how to reduce memory overhead as a central optimization challenge.
OpenMRS is a Java-based open-source web application for medical records, built on the Spring Framework.Previous efforts in auditing for OpenMRS include recording any modification to the database records as part of the OpenMRS core implementation, and logging every function call to a set of predefined records.The latter illustrates the relevance of function invocations as a key factor in logging.Furthermore, function calls define the fundamental unit of "secure operations" in OpenMRS access control [37].This highlights the relevance of our Calls logging specification class, particularly as it pertains to specification of break the glass policies, which are sensitive to authorization.
In contrast to previous auditing solutions for OpenMRS, ours allows security administrators to define logging specifications separately from code.Our tool automatically instruments code to correctly support these specifications.This is more convenient, declarative, and less error prone than direct ad hoc instrumentation of code.
System Architecture Summary To clarify the following discussion, we briefly summarize the architecture of our system.Logging specifications are made in the style of Calls (Definition 9), which can be parsed into JSON objects with a standard form recognized by our system.Instrumentation of legacy code is then accomplished using aspect oriented programming.Parsed specifications are used to identify join points, where the system weaves aspects supporting audit logging into OpenMRS bytecode.These aspects communicate with a proof engine at the joint points to reason about audit log generation, implementing the semantics developed for Λ log in Section 4.3.In our deployment logs are recorded in a SQL database, but our architecture supports other approaches via the use of listeners.

Break the Glass Policies for OpenMRS
Break the glass policies for auditing are intended to retrospectively manage the same security that is proactively managed by access control (before the glass is broken).Thus it is important that we focus on the same resources in auditing as those focused on by access control.The data model of OpenMRS consists of several domains, e.g."Patient" and "User" domains contain information about the patients and system users respectively, and the "Encounter" domain includes information regarding the interventions of healthcare providers with patients.In order to access and modify the information in different domains, corresponding service-layer functionalities are defined that are accessible through a web interface.These functionalities provide security sensitive operations through which data assets are handled.Thus, OpenMRS authorization mechanism checks user eligibility to perform these operations [37].Likewise, we identify these functionalities in logging specifications, i.e. triggers and logging events are servicelayer methods that provide access to data domains, e.g., the patient and user data.
We adapt the logical language of logging specifications developed above (Definition 9), with the minor extension that we allow logging of methods with more than one argument.We note that logging specifications can include other information specified as safe Horn clauses, e.g.ACLs.Here is a simple example of a break the glass auditing policy specified in this form, which states that if the glass is broken by some low-level user, and subsequently patient information is accessed by that user, the access should be logged.The variable U refers to the user, and the variable P refers to the patient.This specification also defines security levels for two users, alice and admin.The predicate @< defines the usual total ordering on integers.loggedCall(T, getPatient, U, P) :call(T, getPatient, U, P), call(S, breakTheGlass, U), @<(S, T), hasSecurityLevel(U, low).
To enable these policies in practice, we have added a "break the glass" button to a user menu in the OpenMRS GUI that can be manually activated on demand.Activation invokes the breakTheGlass method parameterized by the user id.We note that breaking the glass does not turn off access control in our current implementation, which we consider a separate engineering concern that is out of scope for this paper.

Code Instrumentation
To instrument code for log generation, we leverage the Spring Framework that supports aspect-oriented programming (AOP).AOP is used to rewrite code where necessary with "advice", which in our case is before certain method invocations (so-called "before advice").Our advice checks the invoked method names and implements the semantics given in Section 4.3, establishing correctness of audit logging.Join points are automatically extracted from logging specifications, and defined with service-level granularity in a configuration file.Weaving into bytecode is also performed automatically by our system.For example, in the following excerpt of a configuration file, every interface method of the service PatientService is a join point so before invoking each of those methods the advice in RetroSecurityAdvice will be woven into the control flow.The RetroSecurityAdvice is automatically generated by our system based on the logging specification, but essentially determines whether a method call is a trigger or a logging event and interacts with the proof engine appropriately in each case.<advice> <point>org.openmrs.api.PatientService</point> <class> org.openmrs.module.retrosecurity.advice.RetroSecurityAdvice </class> </advice> add only the first invocation of g to the set of logging preconditions to infer the relevant logging information.
Intuitively, our general approach is to rewrite the body of a given logging specification in a form consisting of different conjuncts, such that the truth valuation of each conjunct is independent of the others.This way, the required information to derive each conjunct is independent of the information required for other conjuncts.Then, if the inference of a LoggedCall predicate needs a conjunct to be derived only once during the program execution, following derivation of that conjunct, triggers in the conjunct are "turned off", i.e. no longer added to logging preconditions when encountered during execution.Otherwise, the triggers are never turned off.This way, we ensure that none of the invocations of the logging event is missed.
where each Q k is a conjunct of literals with independent truth valuation resting on disjointness of predicated variables.In what follows, a formal description of the technique is given.Consider the Definition 9. We define Ψ to be the set of all positive literals in the body of LoggedCall excluding literals t i < t 0 for all i ∈ {1, • • • , n}.Moreover, let's denote the set of free variables of a formula φ as F V (φ), and abuse this notation to represent the set of free variables that exist in a set of formulas.Next, we define the relation F V over free variables of positive literals in Ψ , which represents whether they are free variables of the same literal, and extend this transitively in the relation T F V .Definition 12. Let F V ⊆ F V (Ψ ) × F V (Ψ ) be a relation where α F V β iff there exists some literal φ ∈ Ψ such that α, β ∈ F V (φ).Then, the transitive closure of F V is denoted by T F V .

Note that
Intuitively, each equivalence class [α] T F V represents a set of free variables in Ψ that are free in a subset of literals of Ψ , transitively.To be explicit about these subsets of literals, we have the following definition (Definition 13).Note that rather than representing an equivalence class using a representative α (i.e., the notation [α] T F V ), we may employ an enumeration of these classes and denote each class as C k , where k ∈ 1 • • • L. L represents the number of equivalence classes that have partitioned F V (Ψ ).In order to map these two notations, we consider a mapping ω : Definition 13.Let C be an equivalence class induced by T F V .The predicate class P C is a subset of literals of Ψ defined as P C {φ ∈ Ψ | F V (φ) ⊆ C}.We define the independent conjuncts as Q C φ∈P C φ.We also denote Q The above described techniques are used to implement memory overhead mitigation in our OpenMRS retrospective security module-the same mechanism used to perform a loggedCall query is used to check whether the independent conjunct Q C containing a trigger method is satisfiable whenever the trigger is invoked, in which case all triggers in the conjunct are turned off, i.e. no longer added to preconditions when called.In order to prove the correctness of our approach, we have formalized a new calculus Λ log with memory overhead mitigation capabilities, and shown that the generated log is the same as the log generated in Λ log for the same programs.The reader is referred to our Technical Report [3] for this formalization.

Related Work
Previous work by DeYoung et al. has studied audit policy specification for medical (HIPAA) and business (GLBA) processes [20,19].This work illustrates the effectiveness and generality of a temporal logic foundation for audit policy specification, which is well-founded in a general theory of privacy [18].Their auditing system has also been implemented in a tool similar to an interactive theorem prover [24].Their specification language inspired our approach to logging specification semantics.However, this previous work assumes that audit logs are given, and does not consider the correctness of logs.Some work does consider trustworthiness of logs [7], but only in terms of tampering (malleability).In contrast, our work provides formal foundations for the correctness of audit logs, and considers algorithms to automatically instrument programs to generate correct logs.
Other work applies formal methods (including predicate logics [16,10], process calculi and game theory [28]) to model, specify, and enforce auditing and accountability requirements in distributed systems.In that work, audit logs serve as evidence of resource access rights, an idea also explored in Aura [39] and the APPLE system [22].In Aura, audit logs record machine-checkable proofs of compliance in the Aura policy language.APPLE proposes a framework based on trust management and audit logic with log generation functionality for a limited set of operations, in order to check user compliance.
In contrast, we provide a formal foundation to support a broad class of logging specifications and relevant correctness conditions.In this respect our proposed system is closely related to PQL [34], which supports program rewriting with instrumentation to answer queries about program execution.From a technical perspective, our approach is also related to trace matching in AspectJ [1], especially in the use of logic to specify trace patterns.However, the concern in that work is aspect pointcut specification, not logging correctness, and their method call patterns are restricted to be regular expressions with no conditions on arguments, whereas the latter is needed for the specifications in Calls.
Logging specifications are related to safety properties [38] and are enforceable by security automata, as we have shown.Hence IRM rewriting techniques could be used to implement them [21].However, the theory of safety properties does not address correctness of audit logs as we do, and our approach can be viewed as a logging-specific IRM strategy.Guts et al. [25] develop a static technique to guarantee that programs are properly instrumented to generate audit logs with sufficient evidence for auditing purposes.As in our research, this is accomplished by first defining a formal semantics of auditing.However, they are interested in evidence-based auditing for specific distributed protocols.
Other recent work [23] has proposed log filters as a required improvement to the current logging practices in the industry due to costly resource consumption and the loss of necessary log information among the collected redundant data.This work is purely empirical, not foundational, but provides practical evidence of the relevance of our efforts since logging filters could be defined as logging specifications.
Audit logs can be considered a form of provenance: the history of computation and data.Several recent works have considered formal semantics of provenance [9,8].Cheney [12] presents a framework for provenance, built on a notion of system traces.Recently, W3C has proposed a data model for provenance, called PROV [5], which enjoys a formal description of its specified constraints and inferences in first-order logic, [13], however the given semantics does not cover the relationship between the provenance record and the actual system behavior.The confidentiality and integrity of provenance information is also a significant concern [26].

Conclusion
In this paper we have addressed the problem of audit log correctness.In particular, we have considered how to separate logging specifications from implementations, and how to formally establish that an implementation satisfies a specification.This separation allows security administrators to clearly define logging goals independently from programs, and inspires program rewriting tools that support correct, automatic instrumentation of logging specifications in legacy code.
By leveraging the theory of information algebra, we have defined a semantics of logging specifications as functions from program traces to information.By interpreting audit logs as information, we are then able to establish correctness conditions for audit logs via an information containment relation between log information and logging specification semantics.These conditions allow proof of correctness of program rewriting algorithms that automatically instrument general classes of logging specifications.
We define a particular program rewriting strategy for a core functional calculus that supports instrumentation of logging specifications expressed in first order logic, and then prove this strategy correct.This strategy is then applied to develop a practical tool for instrumenting logging specifications in OpenMRS, a popular medical records system.We discuss implementation features of this tool, including optimizations to minimize memory overhead.