3.2
Control Mechanisms: Verification vs Enforcement
Now that we have made clear what is a correctness condition, we can start talking about control mechanisms. As already said, a control mechanism implements the correctness condition and, optionally, it performs some repairing actions if it finds an incorrect system. Hence, we can distinguish two kinds of control mechanisms: verifiers and enforcers.
Verification is intended as the general process of checking if a system complies with a
specification. So verification checks if a system is correct or not. This process can be static or dynamic. In the static case the analysis of the system is done without executing it (e.g. an- alyzing its code if the system is a program). If the specification control is performed during the execution of the system, so dynamically, then the process is called runtime verification. A verifier (runtime or not) can only figure out if a system performs not allowed actions, noth- ing else. Giving to the verifier the power to modify the system execution, a mechanism of
enforcement is obtained. So enforcement assures that the system under control is correct, or
better, assures that it behaves like a correct system. Also in this case there is the possibility to perform the process statically or dynamically (runtime enforcer).
The power of the verification/enforcement mechanisms, i.e. the specifications that they are able to verify/enforce, depends on their “capabilities” or, dually, on the constraints they have to respect. For instance, a mechanism could be limited to only observe the behavior of the system, i.e. it does not have extra information other than the actions executed by the system. This type of mechanisms does not have the possibility to look-forward in the system execution, i.e. decisions rely only on the actions already seen. Furthermore, an unrestricted runtime enforcer can stop, insert, delete, delay and edit all the actions performed by the system under control. In addition it could perform some analysis of the system and look- forward for retrieving information about the future actions executed. This modifications to the system behavior can also be performed syntactically before its execution, so statically, and they are termed rewriting. A particular class of mechanisms is defined restricting the power of a runtime enforcer to only stop system executions, and it is called monitoring.
In any case, a verifier is formally a function Verifier ∈ Specs × Sys −→ {“yes”, “no”} implementing the correctness condition, namely
Verifier(Q, s) = (
“yes” if s |= Q “no” otherwise
Enforcement is a slightly different process, since it has to modify the systems under control. Indeed, enforcement is the process of retrieving the closest system s0such that s0 |= Q. An enforcer could be defined as a function Enforcer ∈ Specs × Sys −→ Sys such that:
Enforcer(Q, s) = s0 and s0 |= Q and s ' s0
for a given equivalence relation ' ⊆ Sys × Sys. The definition of this latter is crucial, since it reflects the precision of the enforcement process. For instance, it is easy to make an enforcer for the trivial equivalence ' , Sys × Sys.
Example 1. Given a specification Q, it is not so hard to retrieve a system (maybe a trivial one) ˆs satisfying Q. Then an enforcement for the equivalence relation ' ⊆ Sys × Sys is trivially definable as Enforcer(Q, s) , ˆs.
24 24
Chapter 3. System Correctness M. Pasqua
Remark. Usually, a control mechanism is built specifically for a particular specification.
Hence it is more realistic to say that a verifier (and similarly, an enforcer) is a function in Sys −→ {“yes”, “no”}, parametric on Q, namely VerifierQ
(s) ,(s |= Q?“yes”:“no”). Both verification and enforcement mechanisms should be feasible, i.e. implementable in some way. Unfortunately, due to Rice’s theorem, every non trivial (semantics) correctness condition is undecidable, hence verification mechanisms need approximations. For what concerns enforcement, it is always possible to enforce every correctness condition, as long as we sacrifice precision. In this thesis we do not deal with enforcement, we have just sketched the idea here. Hence, in the next subsection, we talk about approximate verification, in order to make the problem decidable.
3.2.1
Analysis and Approximations
Systems analysis is a related, but yet slightly different, concept compared to verification. As already said, in verification we want to answer the question: “does a system satisfy a given specification?”. In analysis, instead, we do not have the concept of specification to verify. Indeed, an analysis of a system returns the most precise information we are able to retrieve about the system. Usually, a system could fulfill more than one specification, hence, a system analysis returns the strongest specification fulfilled by the system. This means that analysis is an automatic means for computing {I(s)} and verification, instead, is an automatic means for computing {I(s)} ⊆ Q.
Unfortunately, in general, we are able to compute neither {I(s)} nor {I(s)} ⊆ Q. In- deed, we need approximations. A set of abstract specification Specs]
, which we are able to compute, represents concrete specifications in a simpler way, usually losing some infor- mation. Clearly, we have to define when an abstract specification is a sound approxima- tion of a concrete one, namely we need a soundness function ς ∈ Specs]
−
→ Specs. This latter naturally induces a preorder on Specs]
(a partial order if ς is injective), defined as: ⊆] , {hQ] 1, Q ] 2i | ς(Q ] 1) ⊆ ς(Q ] 2)}3. The order ⊆
]mimics the approximation order ⊆ in the
abstract, namely Q]
1⊆
]Q]
2implies that the set of systems satisfying ς(Q
]
1)is a subset of the set of systems satisfying ς(Q]
2). Note that we can express this in the abstract interpretation framework, where the concrete objects domain is hSpecs, ⊆i, namely concrete specifications, the abstract objects domain is hSpecs], ⊆]i, namely approximate specifications, and the con-
cretization function γ is exactly ς.
Remark. Note that an abstraction is always (silently) performed in classic program analysis.
Systems are represented with sets of executions and hence, technically, specifications are sets of sets of executions. Trace properties are sets of executions, namely they are already abstract specifications. In this case, the abstract approximation order remains set-inclusion and the soundness function is the powerset operator. Finally, in this setting the interpreta- tion of a system, i.e. a set of executions, plays also the role of the strongest specification.
In this setting, the analysis aims to compute a sound abstract specification of a given system, namely it could be defined as a function Analyzer]∈ Sys −→ Specs]
such that: {I(s)} ⊆ ς(Analyzer](s))
3This definition is very strong and, in practice, we settle for an order ⊆]⊆ {hQ] 1, Q ] 2i | ς(Q ] 1) ⊆ ς(Q ] 2)}. This is sufficient to guarantee soundness and it is much easier to achieve in practice: ⊆]