• Aucun résultat trouvé

Composition d’automates appliquée aux mécanismes de sécurité

4.2 Modèle formel et principe de la composition

4.2.2 Composition d’automates appliquée aux mécanismes de sécurité

Rappelons que notre principal objectif est de générer un programme sûr à partir d’un programme non fiable et d’une propriété de sûreté. Dans ce contexte, nous avons jugé qu’il serait intéressant d’établir un modèle qui permette au programme et à la propriété de s’exé- cuter simultanément, de sorte qu’aucune séquence du programme ne puisse s’exécuter sans que celle-ci ne satisfasse la propriété de sûreté. Ce critère constitue l’intuition derrière la composition d’automates appliquée comme mécanisme de sécurité.

Afin d’ajuster la définition4.2.2de la composition à nos besoins en matière de sécurité, l’ensembleΣ sera dorénavant spécifié comme étant le produit cartésien de deux ensembles P etA (Σ = P × A), où :

– L’ensemble A représente l’ensemble des actions atomiques que l’on peut rencontrer dans un programme telles que : affectation, lecture, écriture, etc.

– L’ensembleP = PV∪PAspécifie l’ensemble des expressions booléennes permises par

le langage utilisé pour spécifier le programme et la propriété oùPAdésigne l’ensemble

des conditions manipulées par la propriété (elles portent sur les actions du programme) etPV désigne l’ensemble des conditions manipulées par le programme (elles portent

sur les variables du programme).

Définition 4.2.3 (Composition d’automates pour l’application de la sécurité). Soient les deux AEF AP g = (Q1, Σ, δ1, i1) et Aφ = (Q2, Σ, δ2, i2) correspondant respectivement à l’AEF

spécifiant un programme P g et à l’AEF spécifiant une propriété de sûreté φ. En se basant

sur la définition4.2.2de l’opérateur de composition décrit précédemment, afin d’appliquer la propriétéφ sur le programme P g, la composition modulo la fonction safe de AP g et de permet de générer l’AEFAP g,φ= AP gsafeAφoù :

Q est le plus petit sous-ensemble de Q1× Q2 qui vérifie les conditions suivantes :

• Si (s1, s2) ∈ Q et s′1 = δ1(s1, a1) et s′2 = δ2(s2, a2) alors (s′1, s′2) ∈ Q.

i = (i1, i2),

δ est la fonction de transition décrite telle que :

• δ : (Q × Σ) → Q • δ(q, a) = qs’il existe{(s 1, s2), (s′1, s′2)} ⊆ Q et {a1, a2} ⊆ Σ, tels que : 1. (s1, s2) = q et (s′1, s′2) = q′, 2. δ1(s1, a1) = s′1 etδ2(s2, a2) = s′2, 3. safe(a1, a2) = a.

• La fonction safe qui spécifie la manière dont la propriété φ doit être appliquée sur le programmeP g est donnée par la formule suivante :

safe((p1, a1), (p2, a2)) = (p1∧ (a1 p2), a1)

où la notation “ ” désigne une fonction qui prend une action et une condition boo- léenne et qui retourne une condition booléenne. Cette fonction est baptisée fonction de satisfaction. Il s’agit de la notion clé que nous utilisons dans notre approche d’appli- cation des propriétés de sûreté. En effet, c’est cette fonction qui répond à la question intuitive : “est-ce que une action donnée du programme satisfait la propriété ?". Par conséquent, si la fonction “ ” est capable de prendre une décision statiquement, elle répond par vrai (tt) ou faux (ff). Sinon elle retourne un test dynamique qui dépendra des variables d’exécution du programme.

La fonction de satisfaction est définie en unifiant l’action du programme avec l’action sur laquelle porte la condition de la propriété.

Pour des raisons de simplicité, nous supposons que les conditions de la propriété obéissent à la syntaxe suivante :

a est une action atomique du programme qui appartient à l’ensemble A.

Formellement, nous définissions la fonction de satisfaction comme suit : :(A × P) → P a p =                          tt sip = tt ¬(a q) sip = ¬q (a p1) ∧ (a p2) sip = p1∧ p2

CV(a)(σ) siσ = mgu(a, p) existe

ff sinon

où :

- mgu(a, p) désigne l’unificateur le plus général des deux termes a et p. - V(a) désigne l’ensemble des variables impliquées dans l’action a.

- CV(a)(σ) est une condition portant sur l’ensemble des variables V(a). Cette condi-

tion représente le test dynamique à vérifier durant l’exécution. Elle est extraite de la substitutionσ comme suit :

CV(a)(∅) = tt

CV(a)({x 7→ t} ∪ σ) = (x = t) ∧ CV(a)(σ) six ∈ V(a)

CV(a)({x 7→ t} ∪ σ) = CV(a)(σ) six 6∈ V(a)

Par exemple :C{x}([x 7→ 5, y 7→ 3]) = (x = 5).

Ci-dessous quelques exemples illustrant la définition de la fonction safe :

• safe((p, read(x)), (¬read(3 ), ε)) = (p ∧ (read(x) ¬read(3 )), read(x)) = (p ∧ ¬(x = 3), read(x))

• safe((p, read(x)), (write(y), ε)) = (p ∧ (read(x) write(y)), read(x)) = (ff , read(x))

• safe((p, read(5)), (read(x), ε)) = (p ∧ (read(5) read(x)), read(5)) = (p, read(5))

Remarque 4.2.4. Dans un automate spécifiant une propriété de sûreté, les exigences de celle-ci sont traduites au niveau des conditions étiquetant les transitions. Par consé- quent, la partie action de chaque transition est vide (égale àε).

À noter que :

¬(tt) = f f

¬((x = v) ∧ C) = (x 6= v) ∨ ¬C ¬((x 6= v) ∧ C) = (x = v) ∨ ¬C

Pour alléger les notations, la fonction safe sera dorénavant considérée comme implicite et l’opérateur de composition sera noté par⊙ lorsqu’il n’y aura aucune ambiguïté.

Afin de mieux cerner la sémantique de la satisfaction d’une propriété donnée par un pro- gramme, nous donnons la définition formelle suivante :

Définition 4.2.5 (Satisfaction d’une propriété). On dit qu’un programmeP satisfait une pro-

priété de sûreté φ, qu’on note par : P  φ, si chaque trace du programme P satisfait la

propriétéφ.

Plus précisément, une trace τ = (p1, a1).(p2, a2) . . . du programme P satisfait une pro-

priété φ, s’il existe un mot w = (p

1, ε).(p′2, ε) . . . accepté par Aφ (l’automate spécifiant la propriétéφ) tel que pour tout i ≥ 1, on a : pi(ai pi) où ⋖ est une relation d’ordre sur les expressions booléennes.

Nous rappelons que les conditions du programme et les conditions de la propriété n’ont pas la même syntaxe. Les premières portent sur les variables du programme et les secondes portent sur les actions du programme. Par conséquent, elles ne sont pas forcément compa- rables. Pour ce faire, nous avons dû générer une nouvelle condition en utilisant la fonction pour répondre à la question : “sous quelle condition l’action du programme satisfait-elle la condition de la propriété”. Cette nouvelle condition porte sur les variables du programme, elle nous permet ainsi de vérifier si la condition initiale du programme est suffisamment forte pour satisfaire la propriété.

La relation d’ordre ⋖ utilisée dans la définition de la fonction est définie comme suit : – On dit qu’une condition b est plus restrictive (plus forte) qu’une condition b, qu’on

désigne parb ⋖ b: s’il existe une conditionb′′telle queb = b∧ b′′.

– On désigne par[[P ]] l’ensemble des traces générées par le programme P , et on étend la relation d’ordre ⋖ vers les traces et les programmes comme suit :

⋄ Soit τ1 = (p11, a11).(p12, a12) . . . et τ2 = (p21, a21).(p22, a22) . . . deux traces. On dit que

⋄ Soit P1etP2 deux programmes. On dit queP1 ⋖P2si pour chaque trace τ1 de[[P1]]

il existe une traceτ2 de[[P2]] telle que τ1 ⋖τ2.

Intuition derrière l’opérateur de composition pour l’application des propriétés de sûreté

Intuitivement, la tâche majeure de l’opérateur de composition est de rajouter -lorsque c’est nécessaire- des tests dynamiques à des points critiques du programme, de sorte que la propriété ne soit jamais violée. Par conséquent, on dira que la composition génère un programme sûr. Plus précisément, le programme résultant ne doit introduire aucun nouveau comportement par rapport au programme d’origine. En fait, ce n’est qu’une version plus restrictive du programme d’origine qui a pour particularité supplémentaire le fait de toujours satisfaire la propriété de sûreté à appliquer. Selon la sémantique du programme résultant de la composition, nous distinguons deux cas de figure :

(i) Si le programme d’origine comporte une trace qui viole la propriété de sécurité, celle- ci est tronquée juste avant la “mauvaise” action qui mène à la violation de la propriété. (ii) Si une trace du programme d’origine est valide (elle respecte la propriété), alors elle

ne subit aucune troncation et sera donc conservée dans le programme résultat.

C’est à partir de ce principe qu’est construit l’ensemble des traces valides correspondant au programme sûr que nous générons.

Optimisation

Après avoir construit l’automateAP⊙Aφ, et après avoir évalué statiquement les étiquettes des transitions (les prédicats via la fonction de satisfaction), nous devons effectuer quelques optimisations sur l’automate obtenu. Et ce afin d’éliminer tous les états superflus de l’auto- mate. Cette optimisation est faite, en éliminant chaque état qui n’est accessible qu’à travers des transitions “mortes”. Une transition est dite morte si elle est étiquetée par une paire(p, a) où le prédicatp est équivalent à faux (ff ). Une fois que ces états ont été éliminés, il en résulte

d’autres états qui seront non-atteignables, à partir de l’état initial. Ceux-là seront également supprimés de l’automate final. Ce procédé est réitéré jusqu’à ce qu’il n’y ait plus d’états à supprimer.