Active Model Learning for the Analysis of Network Protocols

ion We recall relevant parts of the theory of abstractions from [10]. Existing model learning algorithms are only effective when applied to Mealy machines with small sets of inputs, e.g. fewer than 100 elements. Practical systems like TCP, however, typically have huge alphabets, since inputs and outputs carry parameters of type integer or string. In order to learn an over-approximation of a “large” Mealy machine M, we place a transducer in between the teacher and the learner, which translates concrete inputs in I to abstract inputs in X, concrete outputs in O to abstract outputs in Y , and vice versa. This allows us to abstract a Mealy machine with concrete symbols in I and O to a Mealy machine with abstract symbols in X and Y , reducing the task of the learner to inferring a “small” abstract Mealy machine. Formally, a mapper for inputs I and outputs O is a deterministic Mealy machine A = 〈I ∪O,X ∪ Y,R, r0, δ, λ〉, where I and O are disjoint sets of concrete input and output symbols, X and Y are disjoint sets of abstract input and output symbols, and λ : R× (I ∪O)→ (X ∪Y ), the abstraction function, respects inputs and outputs, that is, for all a ∈ I ∪O and r ∈ R, a ∈ I ⇔ λ(r, a) ∈ X. Basically, the abstraction of Mealy machineM via mapper A is the Cartesian product of the underlying transition systems. Let M = 〈I,O,Q, q0,→M〉 be a Mealy machine and let A = 〈I ∪O,X ∪ Y,R, r0, δA, λA〉 be a mapper. Then αA(M), the abstraction of M via A, is the Mealy machine 〈X,Y ∪ {⊥}, Q×R, (q0, r0),→α〉, where ⊥6∈ Y is a fresh output and →α is given by the rules q i/o −−→M q′, r i/x −−→A r′ o/y −−→A r′′ (q, r) x/y −−→α (q′, r′′) 6 ∃i ∈ I : r i/x −−→A (q, r) x/⊥ −−−→α (q, r) To understand how the mapper is utilized during learning, we follow the execution of a single input of a query. The learner produces an abstract input x, which it sends to the mapper. By inversely following abstraction function λA, the mapper converts this to a concrete input i and updates its state via transition r i/x −−→A r′. The concrete input i is passed on to the teacher, which responds with a concrete output o according to q i/o −−→M q′. This triggers the transition r′ o/y −−→A r′′ in which the mapper generates the corresponding abstract output y and updates its state again. The abstract output is then returned to the learner. We notice that the abstraction function is utilized invertedly when translating inputs. More precisely, the abstract input that the learner provides is an output for the mapper. 36 2. Model Learning and Model Checking of TCP Implementations The translation from abstract to concrete involves picking an arbitrary concrete value that corresponds to the given abstract value. It can be that multiple concrete values can be picked, in which case all values should lead to the same abstract behavior, thus ensuring that the resulting abstract model is deterministic. It can also be that no values correspond to the input abstraction, in which case, by the second rule, ⊥ is returned to the learner, without consulting the teacher. We define the abstraction component implementing αA as the transducer which follows from the mapper A, but inverts the abstraction of inputs. From the perspective of a learner, a teacher for M and abstraction component implementing αA together behave exactly like a teacher for αA(M). If αA(M) is deterministic, then the learner will eventually succeed in learning a deterministic machine H satisfying αA(M) ≈ H. In [10], also a concretization operator γA is defined. This operator is the adjoint of the abstraction operator: it turns any abstract machine H with symbols in X and Y into a concrete machine with symbols in I and O. If H is deterministic then γA(H) is weakly deterministic. As shown in [10], αA(M) ≤ H implies M≤ γA(H). This tells us that when we apply mapper A during learning of some “large” Mealy machineM, even though we may not be able to learn the behavior of M exactly, the concretization γA(H) of the learned abstract model H is an over-approximation of M, that is, M≤ γA(H). Similarly to the abstraction component, a concretization component for mapper A implements γA. This component is again fully defined by a mapper, but handles abstraction of outputs invertedly. During model checking, the composition of the abstract model H and the concretization component for A provides us with an over-approximation of M. Framework for mapper definition In order to apply our abstraction approach, we need an abstraction and a concretization component for a given mapper A. We could implement these components separately in an arbitrary programming language, but then they would have to remain consistent with A. Moreover, ensuring that translation in one component inverts the corresponding translation in the other is non-trivial, and difficult to maintain, as changes in one would have to be applied invertedly in the other. We used an alternative approach, in which we first define a mapper and then derive the abstraction and concretization components automatically. To this end, we built a language for defining a mapper in terms of (finite) registers, and functions to encode transitions and outputs. Our language supports case distinctions with programmingstyle if-else-statements, and requires that every branch leads to exactly one output and updates registers exactly once, such that the translations are complete. Except for the restrictions of finiteness and determinism, our language has the expressiveness of a simple programming language and should thus be usable to abstract (and concretize reversely) a wide range of systems and protocols. Listing 2.1 shows the example of a mapper for a simple login system. The mapper stores the first password received, and compares subsequent passwords to it. The abstract passwords used by the learner 2.3. Learning Setup 37 are {true, false}, denoting a correct or incorrect password, respectively. At the first attempt, true invertedly maps to any concrete password, and false maps to ⊥. Later on true invertedly maps to the value picked the first time, while false maps to any other value. For TCP, we define multiple abstraction functions for inputs and outputs, in terms of multiple parameters per input or output. Listing 2.1 A simple example mapper for a login system, in a simplified syntax integer stored := −1; map enter(integer password→ boolean correct) if (stored = −1 ∧ password ≥ 0) ∨ stored = password then correct := true else correct := false update if stored = −1 ∧ password ≥ 0 then stored := password else stored := stored . Every path explicitly assigns a value To derive the components, we need to implement the inverse of the abstraction function, for both inputs and outputs. This can be achieved using a constraint solver or by randomly picking concrete values until we find one that is translated to the abstract value we want to concretize, where translation is done with the mapper in the forward direction. The latter approach may be hard, as the concrete domain is usually very large, while there may be only a few concrete values matching the abstract value, meaning we would have to test many concrete values before we find a fitting one. To that end, heuristics can help reduce the pool of selectable concrete values. Where the latter approach improves on the former is in testing the abstraction function. We want to ensure that different concrete values translating to the same abstract value lead to the same abstract behavior, as the learner cannot handle non-determinism. A constraint solver usually picks values in a very structured and deterministic way, which does not test the abstraction function well. Picking concrete values randomly and checking the corresponding abstract value allows more control over obtaining a good test coverage, but is in general less scalable.