figure a

1 Introduction

Hyperproperties [4] generalize trace properties in that they not only check the correctness of individual computation traces in isolation, but relate multiple computation traces to each other. \(\text {HyperLTL}\) [3] is a logic for expressing temporal hyperproperties, by extending linear-time temporal logic with explicit trace quantification. \(\text {HyperLTL}\) has been used to specify a variety of information-flow and security properties. Examples include classical properties like non-interference and observational determinism, as well as quantitative information-flow properties, symmetries in hardware designs, and formally verified error correcting codes [8]. While model checking and satisfiability checking tools for HyperLTL already exist [5, 8], the runtime verification of HyperLTL specifications has so far, despite recent theoretical progress [1, 2, 7], not been supported by practical tool implementations.

Monitoring hyperproperties is difficult: in principle, the monitor not only needs to process every observed trace, but must also store every trace observed so far, so that future traces can be compared with the traces seen so far. On the other hand, a runtime verification tool for hyperproperties is certainly useful, in particular if the implementation of a security critical system is not available. Even without access to the source code, monitoring the observable execution traces still detects insecure information flow.

In this paper, we present \(\text {RVHyper}\), a runtime verification tool for monitoring temporal hyperproperties. \(\text {RVHyper}\) tackles this challenging problem by implementing two major optimizations: (1) a trace analysis, which detects all redundant traces that can be omitted during the monitoring process and (2) a specification analysis to detect exploitable properties of a hyperproperty, such as symmetry.

We have applied \(\text {RVHyper}\) in classical information-flow security, such as checking for violations of observational determinism. \(\text {HyperLTL}\) is, however, not limited to security policies. As an example of such an application beyond security, we show how \(\text {RVHyper}\) can be used to detect spurious dependencies in hardware designs.

2 \(\text {RVHyper}\)

In this section we give an overview on the monitoring approach, including the input and output of the monitoring algorithm and the two major optimization techniques implemented in \(\text {RVHyper}\).

Specification. The input to \(\text {RVHyper}\) is a \(\text {HyperLTL}\) specification. \(\text {HyperLTL}\) [3] is a temporal logic for specifying hyperproperties. The logic extends \(\text {LTL}\) with quantification over trace variables \(\pi \) and a method to link atomic propositions to specific traces. The set of trace variables is \(\mathcal {V}\). Formulas in \(\text {HyperLTL}\) are given by the grammar

where \(a \in \text {AP}\) and \(\pi \in \mathcal {V}\). The finite trace semantics [2] for \(\text {HyperLTL}\) is based on the finite trace semantics of LTL. In the following, when using \(\mathcal {L}(\varphi )\) we refer to the finite trace semantics of a \(\text {HyperLTL}\) formula \(\varphi \). Let t be a finite trace, \(\epsilon \) denotes the empty trace, and |t| denotes the length of a trace. Since we are in a finite trace setting, \(t[i,\ldots ]\) denotes the subsequence from position i to position \(|t|-1\). Let \(\varPi _{ fin }: \mathcal {V}\rightarrow \varSigma ^*\) be a partial function mapping trace variables to finite traces. We define \(\epsilon [0]\) as the empty set. \(\varPi _{ fin }[i, \ldots ]\) denotes the trace assignment that is equal to \(\varPi _{ fin }(\pi )[i,\ldots ]\) for all \(\pi \). We define a subsequence of t as follows.

$$ t[i,j] = {\left\{ \begin{array}{ll} \epsilon &{} \text {if } i \ge |t|\\ t[i,\textit{min}(j,|t|-1)], &{} \text {otherwise} \end{array}\right. } $$
figure b

For example, above mentioned observational determinism can be formalized as the HyperLTL formula , where is the weak version of .

Input and Output. The input of \(\text {RVHyper}\) consists of a HyperLTL formula and the observed behavior of the system under consideration. The observed behavior is represented as a trace set T, where each \(t \in T\) represents a previously observed execution of the system under consideration. If \(\text {RVHyper}\) detects that the system violates the hyperproperty, it outputs a counter example, i.e, a k-ary tuple of traces, where k is the number of quantifiers in the HyperLTL formula.

Monitoring Algorithm. Given a HyperLTL formula \(\varphi \) and a trace set T, \(\text {RVHyper}\) processes a fresh trace under consideration as depicted in Algorithm 1. The algorithm revolves around a monitor-template \(\mathcal {M}_\varphi \), which is constructed from the HyperLTL formula \(\varphi \). The basic idea of the monitor template is that it still contains every trace variables of \(\varphi \), which can be initialized with explicit traces at runtime. This way, the automaton construction of the monitor template is constructed only once as a preprocessing step.

\(\text {RVHyper}\) initializes the monitor template for each k-ary combination of traces in \(T\cup \{t\}\). If one tuple violates the hyperproperty, \(\text {RVHyper}\) returns that k-ary tuple of traces as a counter example, otherwise \(\text {RVHyper}\) returns satisfied.

Trace Analysis: Minimizing Trace Storage. The main obstacle in monitoring hyperproperties is the potentially unbounded space consumption. \(\text {RVHyper}\) uses a trace analysis to detect redundant traces, with respect to a given HyperLTL formula, i.e., traces that can be safely discarded without losing any information and without losing the ability to return a counter example.

\(\text {RVHyper}\)’s trace analysis is based on the definition of trace redundancy: we say a fresh trace t is \((T, \varphi )\)-redundant, if T is a model of \(\varphi \) if and only if \(T \cup \{t\}\) is a model of \(\varphi \). The idea, depicted in Algorithm 2, is to check if another trace \(t'\) contains at least as much informations as t: we say a \(t'\) dominates t if \(\bigwedge _{\pi \in \mathcal {V}} \mathcal {L}(\mathcal {M}_\varphi [t'/\pi ]) \subseteq \mathcal {L}(\mathcal {M}_\varphi [t/\pi ])\). For a fresh incoming trace, RVHyper performs this language inclusion check in both directions in order to compute the minimal trace set that must be stored to monitor the hyperproperty under consideration.

Specification Analysis: Decreasing Running Time. \(\text {RVHyper}\) uses a specification analysis, which is a preprocessing step that analyzes the HyperLTL formula under consideration. \(\text {RVHyper}\) detects whether a formula is (1) symmetric, i.e., we halve the number of instantiated monitors, (2) transitive, i.e, we reduce the number of instantiated monitors to two, or (3) reflexive, i.e., we can omit the self comparison of traces [7].

Symmetry is especially interesting because many information flow policies satisfy this property. Consider, for example, observational determinism: \(\text {RVHyper}\) detects symmetry by translating this formula to a formula that is unsatisfiable if there exists no pair of traces which violates the symmetry condition: . If the resulting formula turns out to be unsatisfiable, \(\text {RVHyper}\) omits the symmetric instantiations of the monitor automaton, which turns out to be, especially in combination with \(\text {RVHyper}\)s trace analysis, a major optimization in practice [7].

Implementation. \(\text {RVHyper}\)Footnote 1 is written in . It uses spot for building the deterministic monitor automata and the Buddy BDD library for handling symbolic constraints. We use the \(\text {HyperLTL}\) satisfiability solver \(\text {EAHyper}\) [5, 6] to determine whether the input formula is reflexive, symmetric, or transitive. Depending on those results, we omit redundant tuples in the monitoring algorithm.

3 Detecting Spurious Dependencies in Hardware Designs

While \(\text {HyperLTL}\) has been applied to a range of domains, including security and information flow properties, we focus in the following on a classical verification problem, the independence of signals in hardware designs. We demonstrate how \(\text {RVHyper}\) can automatically detect such dependencies from traces generated from hardware designs.

Fig. 1.
figure 1

mux circuit with black box

Input and Output. The input to \(\text {RVHyper}\) is a set of traces where the propositions match the atomic propositions of the \(\text {HyperLTL}\) formula. For the following experiments, we generate a set of traces from the Verilog description of several example circuits by random simulation. If a set of traces violates the specification, \(\text {RVHyper}\) returns a counter example.

Specification. We consider the problem of detecting whether input signals influence output signals in hardware designs. We write to denote that the inputs \({\varvec{i}}\) do not influence the outputs \({\varvec{o}}\). Formally, we specify this property as the following \(\text {HyperLTL}\) formula:

where \(\overline{{\varvec{i}}}\) denotes all inputs except \({\varvec{i}}\). Intuitively, the formula asserts that for every two pairs of execution traces \((\pi _1,\pi _2)\) the value of \({\varvec{o}}\) has to be the same until there is a difference between \(\pi _1\) and \(\pi _2\) in the input vector \(\overline{{\varvec{i}}}\), i.e., the inputs on which \({\varvec{o}}\) may depend.

Sample Hardware Designs. We apply \(\text {RVHyper}\) to traces generated from the following hardware designs. Note that, since \(\text {RVHyper}\) observes traces and treats the system that generates the traces as a black box, the performance of \(\text {RVHyper}\) does not depend on the size of the circuit.

Example 1

( xor). As a first example, consider the xor function \({\varvec{o}} = {\varvec{i}} \oplus {\varvec{i}}'\). In the corresponding circuit, every j-th output bit \(o_j\) is only influenced by the j-the input bits \(i_j\) and \(i'_j\).

Example 2

( mux). This example circuit is depicted in Fig. 1. There is a black box combinatorial circuit, guarded by a multiplexer that selects between the two input vectors \({\varvec{i}}\) and \({\varvec{i}}'\) and an inverse multiplexer that forwards the output of the black box either towards \({\varvec{o}}\) or \({\varvec{o}}'\). Despite there being a syntactic dependency between \({\varvec{o}}\) and \({\varvec{i}}'\), there is no semantic dependency, i.e., the output \({\varvec{o}}\) does solely depend on \({\varvec{i}}\) and the selector signal.

When using the same example, but with a sequential circuit as black box, there may be information flow from the input vector \({\varvec{i}}'\) to the output vector \({\varvec{o}}\) because the state of the latches may depend on it. We construct such a circuit that leaks information about \({\varvec{i}}'\) via its internal state.

Example 3

(counter). Our last example is a binary counter with two input control bits \( incr \) and \( decr \) that increments and decrements the counter. The corresponding Verilog design is shown in Fig. 2. The counter has a single output, namely a signal that is set to one when the counter value overflows. Both inputs influence the output, but timing of the overflow depends on the number of counter bits.

Fig. 2.
figure 2

Verilog description of Example 3 (counter).

Table 1. Results of \(\text {RVHyper}\) on traces generated from circuit instances. Every instance was run 10 times with different seeds and the average is reported.

Results. The results of multiple random simulations are given in Table 1. Despite the high complexity of the monitoring problem, \(\text {RVHyper}\) is able to scale up to thousands of input traces with millions of monitor instantiations (cf. Algorithm 1). \(\text {RVHyper}\)’s optimizations, i.e., keeping only a minimal set of traces and reducing the number of instances by the specification analysis, are a key factor to those results. For the two instances where the property is satisfied (xor and mux), \(\text {RVHyper}\) has not found a violation for any of the runs. For instances where the property is violated, \(\text {RVHyper}\) is able to find counter examples. While counter examples can be found quickly for xor and mux2, the counter instances need more traces since the chance of finding a violating pair of traces is lower.

4 Conclusion

RVHyper monitors a running system for violations of a HyperLTL specification. The functionality of RVHyper thus complements model checking tools for HyperLTL, like MCHyper [8], and tools for satisfiability checking, like EAHyper [6]. RVHyper is in particular useful during the development of a \(\text {HyperLTL}\) specification, where it can be used to check the HyperLTL formula on sample traces without the need for a complete model. Based on the feedback of the tool, the user can refine the HyperLTL formula until it captures the intended policy.