diff --git a/figs/miss-v-hit.png b/figs/miss-v-hit.png new file mode 100644 index 0000000..7f0d30d Binary files /dev/null and b/figs/miss-v-hit.png differ diff --git a/figs/predicted-miss.png b/figs/predicted-miss.png new file mode 100644 index 0000000..31b8a57 Binary files /dev/null and b/figs/predicted-miss.png differ diff --git a/figs/predicted-remote-hit.png b/figs/predicted-remote-hit.png new file mode 100644 index 0000000..a1cdacb Binary files /dev/null and b/figs/predicted-remote-hit.png differ diff --git a/figs/topology-miss.jpg b/figs/topology-miss.jpg new file mode 100644 index 0000000..12a9007 Binary files /dev/null and b/figs/topology-miss.jpg differ diff --git a/main.tex b/main.tex index e761512..ac2e22b 100644 --- a/main.tex +++ b/main.tex @@ -12,6 +12,7 @@ \usepackage{amsmath} \usepackage{xcolor} \usepackage{syntax} +\usepackage{float} % configuration des packages \hypersetup{colorlinks=false} @@ -37,34 +38,21 @@ Université de \textsc{Rennes} 1} \maketitle \begin{abstract} - \TODO{Réécrire parce qu'il fallait juste que je démarre mais ça ne ressemblait à rien} + Les attaques par canaux auxiliaires sont particulièrement intéressantes car elles + permettent un accès à des informations restreintes, par delà même les \ang{sandbox} ou + machines virtuelles. Nous nous intéresserons plus particulièrement aux attaques par + canaux auxiliaires sur le cache : Flush+Reload et Flush+Flush. + + Ce stage cherche à renseigner la topologie des appels à l'instruction \texttt{clflush} + sur des systèmes \ang{Intel} à deux \ang{sockets} ; notamment pour mieux évaluer l'état d'une + ligne de cache en fonction du temps d'exécution de l'instruction \texttt{clflush} sur celle-ci. \end{abstract} \tableofcontents \newpage -\section{Introduction} - -\TODO{Réordonner, faire des liens entre les subsubsections} - -\subsubsection{Low Core Count} - -Pour répondre à des demandes variées, \ang{Intel} base ses processeurs serveurs sur -trois tailles \TODO{à partir de la micro-architecture Haswell ?}: -\begin{itemize} - \item LCC (\ang{Low Core Count}) : de 4 à 8 coeurs physiques pour - la micro-architecture Haswell (jusqu'à 10 pour Broadwell) - \item MCC (\ang{Medium Core Count}) : de 10 à 12 coeurs pour Haswell (12 à 14 pour Broadwell) - \item HCC (\ang{High Core Count}) : de 14 à 18 coeurs pour Haswell (16 à 24 pour Broadwell) -\end{itemize} - -Les machines que nous utiliserons sont uniquement basées sur la \ang{die} LCC, mais certaines -(les Broadwell à 8 coeurs par exemple) sont alors livrées avec des coeurs désactivés. La \ang{slice} -de cache L3 associée est alors désactivée également. Cela pose tout de même question sur la possibilité -de sauts supplémentaires dûs à ces coeurs manquants. \TODO{Alors, quel est le coeur désactivé ? -Est-ce similaire sur toutes les puces du même modèle ou choisi spécifiquement en usine ? Quelle -est la conséquence dans ce cas ?} +\section{Contexte} \subsection{Hiérarchie de cache} @@ -80,8 +68,8 @@ des données et des instructions. Au dernier niveau, le L3 est partagé entre to stockée dans le cache L1 ou L2 est également dans le L3. Si le L3 est partagé, il n'est cependant pas situé en un seul endroit dans le CPU -mais est réparti en différentes \ang{slices} : des tranches de mémoire accolées chacune à un coeur. Dans le modèle -étudié, chaque coeur a exactement une \ang{slice}. +mais est réparti en différentes \ang{slices} : des tranches de mémoire accolées chacune à un coeur. +Dans le modèle étudié, chaque coeur a exactement une \ang{slice}. \begin{figure}[ht] \centering @@ -109,13 +97,13 @@ s'ajoute sur les autres processeurs. \begin{figure}[ht] \centering \includegraphics[width=1.0\textwidth]{lstopo} - \caption{Topologie \ang{NUMA} de \textit{paravance} extraite + \caption{Topologie \ang{NUMA} de la machine \textit{paravance} extraite avec l'outil \texttt{lstopo} de \texttt{hwloc}} \end{figure} Dans un système à plusieurs \ang{sockets}, chaque \ang{socket} a de la mémoire DRAM à laquelle il peut accéder directement. Sur les machines Intel, le \ang{QPI} (\ang{QuickPath Interconnect}) -permet à un processeur d'accéder au données localisées dans la mémoire rattachée à un autre processeur. +permet à un processeur d'accéder aux données localisées dans la mémoire rattachée à un autre processeur. Le principe \ang{NUMA} (\ang{Non-uniform memory access}) délimite alors des groupes contenant un processeur et les adresses mémoire qui en sont rapprochées et les transmet au système d'exploitation. @@ -128,7 +116,7 @@ Sur Linux, si beaucoup d'accès mémoire sont réalisés d'un processeur Dans des systèmes à plusieurs coeurs, d'autant plus avec plusieurs processeurs, où chaque coeur a un cache qui lui est propre, un problème de cohérence apparaît. Comment s'assurer qu'une ligne de données -ne soit pas réécrite de différentes manières en plusieurs cache du système ? +ne soit pas réécrite de différentes manières en plusieurs caches du système ? On peut commencer par définir des états dans lesquels sont considérées les lignes de cache : @@ -142,7 +130,6 @@ sont considérées les lignes de cache : \end{itemize} D'autres sont parfois ajoutés à cette liste comme \ang{Forward}. - Une première solution au problème de cohérence de cache, dite par annuaire (\ang{directory}), consiste à avoir à côté des différents caches un \ang{directory} qui contient pour chaque ligne de mémoire en cache @@ -257,6 +244,8 @@ Les avantages de cette méthode par rapport à Flush+Reload sont multiples : (le L3 par exemple). \end{itemize} +\ + Similairement à ces autres méthodes, Flush+Flush peut extraire des données du fonctionnement des autres processus en regardant les accès mémoires faits dans les bibliothèques partagées, qui occupent les mêmes zones de la mémoire physique pour différents processus. @@ -267,25 +256,16 @@ en regardant les zones mémoire accédées pendant le chiffrement de données. Un enregistreur de frappe (\ang{keylogger}) basé sur les pages accédées dans la librairie \textsc{Gtk} \texttt{libgdk.so} y est également mis en oeuvre. -\section{Motivation} +\ Là où Flush+Reload choisit de mesurer le temps pour charger à nouveau une adresse en mémoire, Flush+Flush choisit de mesurer le temps nécessaire pour l'évincer : la différence entre un \ang{cache hit} et un \ang{cache miss} est alors beaucoup moins perceptible (moins de 12 cycles de CPU). + De bons résultats~\cite{flushflush} ont toutefois été obtenus en appliquant un seuil global. +Mais la connaissance des coeurs attaquant et victime et de la \ang{slice} de la ligne surveillée +permettent potentiellement une meilleure précision. -Guillaume \textsc{Didier} et Clémentine -\textsc{Maurice}~\cite{calibrationdoneright} proposent une rétro-ingénierie des -messages échangés en fonction de l'état de cohérence des lignes -évincées du cache. Cela passe par l'étude des sources de variabilité et permet de -mieux choisir un seuil propre à chaque combinaison attaquant/victime/\ang{slice}. - -Ce travail s'était intéressé à certains processeurs Intel de micro-architectures -\ang{Coffee Lake} et -\ang{Haswell} à une seule \ang{socket}, mais a révélé que les résultats seraient bien plus complexes -sur des systèmes à plusieurs \ang{sockets}. - -\TODO{paragraphe à déplacer} \label{nonprivilegedinfo} Dans un scénario réel, l'attaquant peut choisir le coeur sur lequel il s'exécute, a accès au coeur sur lequel le processus victime s'exécute via \texttt{/proc/pid}. @@ -298,6 +278,19 @@ mêmes \ang{slices}. Une connaissance fine d'éléments dépendants du numéro d le temps d'exécution de \texttt{clflush} dans certaines conditions -- permettrait alors de déterminer la \ang{slice}. +\section{Motivation} + +Guillaume \textsc{Didier} et Clémentine +\textsc{Maurice}~\cite{calibrationdoneright} proposent une rétro-ingénierie des +messages échangés en fonction de l'état de cohérence des lignes +évincées du cache. Cela passe par l'étude des sources de variabilité et permet de +mieux choisir un seuil propre à chaque combinaison attaquant/victime/\ang{slice}. + +Ce travail s'était intéressé à certains processeurs Intel de micro-architectures +\ang{Coffee Lake} et +\ang{Haswell} à une seule \ang{socket}, mais a révélé que les résultats seraient bien plus complexes +sur des systèmes à plusieurs \ang{sockets}. + \section{Organisation des expériences} Les expériences ont été faites sur 6 machines différentes, @@ -328,7 +321,8 @@ Les machines suivantes ont donc été utilisées~\cite{g5k-nodes} \end{tabular} \end{center} -La prise de mesure consistait à relever pour un lot d'adresse (chacune correspondant à une \ang{slice}) +La prise de mesure consistait à relever pour un lot d'adresses +(chacune correspondant à une \ang{slice}) les temps d'exécution de l'instruction \texttt{clflush} pour toutes les paires de coeurs et tous les états de cohérence possibles. @@ -356,16 +350,19 @@ Les fichiers de résultats bruts sont accessibles en ligne~\cite{g5k-results}. \section{Analyse des résultats} - \begin{figure}[ht] \centering \includegraphics[width=0.5\textwidth]{low-core-count} - \caption{Topologie LCC Haswell EP d'après~\cite{tuningXeon} \TODO{schéma à déplacer}} + \caption{Topologie LCC Haswell EP d'après~\cite{tuningXeon}} \end{figure} Les schémas de présentation d'Intel suggèrent une topologie en anneau, avec un CPU divisé en deux grandes parties. -Pour la numérotation des coeurs, les premiers tests semblent révéler une numérotation +\subsection{Questions génériques} + +\subsubsection{Numérotation des coeurs} + +Les premiers tests semblent révéler une numérotation suivant ce schéma\footnote{Il est possible que la numérotation soit en fait tournée à 180°. Comme nous avons appliqué la même rotation aux \ang{slice}, cela n'affecterait que les positions respectives du QPI et du \ang{Home Agent}}: @@ -404,12 +401,35 @@ Pour trouver la numérotation des \ang{slices}, deux méthodes sont possibles: afin d'être sûr que les numéros de \ang{slice} correspondent aux numéros de coeurs. \end{itemize} +\subsubsection{Coeurs fantômes} +\TODO{Où peut aller ce paragraphe ?} -\subsection{Topologie Miss} +Pour répondre à des demandes variées, \ang{Intel} base ses processeurs serveurs sur +trois tailles à compter de la micro-architecture Haswell: +\begin{itemize} + \item LCC (\ang{Low Core Count}) : de 4 à 8 coeurs physiques pour + la micro-architecture Haswell (jusqu'à 10 pour Broadwell) + \item MCC (\ang{Medium Core Count}) : de 10 à 12 coeurs pour Haswell (12 à 14 pour Broadwell) + \item HCC (\ang{High Core Count}) : de 14 à 18 coeurs pour Haswell (16 à 24 pour Broadwell) +\end{itemize} -\TODO{graphiques comparaison prédiction/réel} +Les machines que nous utiliserons sont uniquement basées sur la \ang{die} LCC, mais certaines +(les Broadwell à 8 coeurs par exemple) sont alors livrées avec des coeurs désactivés. La \ang{slice} +de cache L3 associée est alors désactivée également. Cela pose tout de même question sur la possibilité +de sauts supplémentaires dûs à ces coeurs manquants: quel est le coeur désactivé ? Est-ce le même +sur tous les processeurs du même modèle ? Quel est alors l'impact sur le temps d'exécution ? -Les résultats obtenus quand le \ang{socket} attaquant et victime diffèrent suggèrent l'échange des messages suivants lors d'un \texttt{clflush} qui provoque un \ang{cache miss}: +\subsection{Topologie \ang{miss}} + +\begin{figure}[ht] + \centering + \includegraphics[width=1\textwidth]{predicted-miss} + \caption{durée prédite et réelle d'un cache \ang{miss} selon les différents paramètres} +\end{figure} + + +Les résultats obtenus quand le \ang{socket} attaquant et victime diffèrent +suggèrent l'échange des messages suivants lors d'un \texttt{clflush} qui provoque un \ang{cache miss}: \begin{enumerate} \item Le coeur attaquant contacte la \ang{slice} locale suivant \ref{figs:topology-miss}. \item La \ang{slice} locale contacte la \ang{slice} distante en passant par le QPI. @@ -421,58 +441,127 @@ Les résultats obtenus quand le \ang{socket} attaquant et victime diffèrent sug \item Le chemin est parcouru à l'envers pour repasser par la \ang{slice} locale jusqu'au coeur attaquant \end{enumerate} -\TODO{À quel point faut-il justifier ce qui est avancé ici ? La progression qui suggère le 2. -vient du \texttt{optimize.curve\_fit} et affichait qqchose d'étrange (les coeurs 2 par 2). -J'imagine que c'est toujours bon à préciser} - -\begin{figure}[ht] +\begin{figure}[H] \centering - \rotatebox{270}{ - \includegraphics[width=0.7\textwidth]{topology-miss} - } - \caption{\TODO{schéma propre}} + \includegraphics[width=0.7\textwidth]{pattern} + \caption{trajet coeur attaquant $\rightarrow$ \ang{slice} locale} \label{figs:topology-miss} \end{figure} -Ainsi, le chemin privilégié pour le trajet coeur attaquant - \ang{slice} locale serait assez proche du plus court, mais tenterait de limiter les passages +Ainsi, le chemin privilégié pour le trajet coeur attaquant $\rightarrow$ \ang{slice} locale +serait assez proche du plus court, mais tenterait de limiter les passages par le \ang{Home Agent} possiblement pour éviter de ralentir les opérations qui ont besoin de passer par lui. -\subsection{\TODO{Topologie Hit}} +\subsection{Topologie \ang{hit} exclusif} + +On peut diviser le \ang{hit} en deux grands cas : +\begin{itemize} + \item L'attaquant et la victime sont dans la même \ang{socket} + \item L'attaquant et la victime ne sont pas dans la même \ang{socket} +\end{itemize} + +Initialement, le trajet de l'information est le même que dans le cas d'un \ang{miss}, +et ce n'est qu'au moment où le message parvient au niveau de la \ang{slice} contenant +la ligne en cache que les choses changent. La \ang{slice} contacte alors le coeur victime, +et le message fait le chemin retour une fois la ligne de cache évincée. + +\begin{figure}[H] + \centering + \includegraphics[width=0.4\textwidth]{miss-v-hit} + \caption{Nombre de cache \ang{hit} et cache \ang{miss} selon + la durée d'exécution de l'instruction \texttt{clflush}} +\end{figure} + +Alors, on note une différence de coût significative entre un \ang{hit} local et un \ang{hit} +distant, dû au passage par le \ang{QPI}. Dans le cas où l'attaquant et la victime partagent la +même \ang{socket}, le coût d'un \ang{hit} devient alors généralement beaucoup +moins élevé que celui d'un \ang{miss} ; contrairement au comportement sur +des systèmes à une seule \ang{socket}. + +\begin{figure}[H] + \centering + \includegraphics[width=0.7\textwidth]{predicted-remote-hit} + \caption{durée prédite et réelle d'un cache \ang{hit} selon les différents paramètres} +\end{figure} + +Si ce modèle est assez proche des données, on comprend que celui-ci est loin d'être parfait. +La majeure difficulté dans l'établissement d'un modèle dans le cas d'un \ang{cache hit} +est la grande quantité de données : on ajoute une dépendance en une nouvelle variable, le +coeur victime, qui n'était pas prise en compte pour un \ang{miss}. +De plus, les différents facteurs sont ici difficiles à décorréler, +ce qui a rendu l'analyse plus chronophage. + +\section{Conclusion} + +Si nous n'avons pas pu trouver un modèle parfaitement cohérents +avec les résultats analysés pour une question de temps, +nous avons désormais une méthode pour prendre les mesures, +tout en maîtrisant les principales sources de bruit. + +Plusieurs pistes se proposent alors pour continuer le travail présenté ici : +\begin{itemize} + \item Affiner le modèle, qui nes't pas parfait sur les \ang{cache miss} et ne colle pas + bien aux \ang{cache hit}. On pourrait ensuite voir comment celui-ci s'étend aux autres + états de cohérrence de cache ; + \item Clarifier les hypothèses avancées dans ce rapport en effectuant certaines vérifications : + \texttt{numactl} permet-il bien de verrouiller les pages partagées ? Peut-on proposer une + renumérotation automatique des slices ? Cela permettra de créer un modèle crédible d'attaquant ; + \item Proposer une méthode de réassignation automatique des slices pour savoir depuis un + utilisateur non privilégié la \ang{slice} d'une adresse virtuelle ; + \item Réaliser l'attaque Flush+Flush sur des systèmes à 2 \ang{sockets} +\end{itemize} + +%\TODO{Extension au Xeon SP, L3 non inclusif+topologie différente + +%Extension aux nouveaux proc avec slice != 1/coeur} -\section{\TODO{Ouverture}} -\TODO{Extension au Xeon SP, L3 non inclusif+topologie différente +\newpage{} +%\nocite{*} +\bibliographystyle{plain} +\bibliography{refs} -Extension aux nouveaux proc avec slice != 1/coeur} + +\newpage{} +\section*{Annexe} + +\subsection*{Contexte du stage} + +Ce stage a été effectué dans l'université de \textsc{Rennes} 1, +dans le laboratoire de l'\textsc{Irisa} (Institut de Recherche en Informatique +et Systèmes Aléatoires), l'un des plus grands laboratoires de recherche français dans le domaine +de l'informatique avec plus de 850 personnes. + +Il accueille 7 départements et une quarantaine d'équipes, j'ai été encadré par deux chercheurs de +l'équipe \textsc{Taran} (Architectures matérielles spécialisées pour l’ère post loi-de-Moore ) : Guillaume \textsc{Didier} et Angeliki \textsc{Kritikakou}. +En discutant avec les autres membres de l'équipe, j'ai pu découvrir de loin des problématiques +liées aux FPGA, l'ISA RISC-V et l'injection de fautes notamment. + +J'ai beaucoup apprécié l'ambiance générale et tout ce que j'ai dû comprendre pour avancer sur +ce sujet de recherche, mais j'ai regretté qu'il soit trop spécifique pour pouvoir demander des conseils +facilement autour d'une pause café. + +\subsection*{Contributions de code} + +Le code utilisé pour prendre les mesures a principalement été +réutilisé de travaux existants~\cite{dendrobates}. +J'y ai contribué en résolvant quelques problèmes liés aux machines utilisées, et en ajoutant un +exécutable limitant la fréquence de l'\ang{uncore}. + +Le code que j'ai écrit ou auquel j'ai apporté des modifications consiste principalement en: + +\begin{itemize} + \item Toute la logique d'analyse des résultats, afin d'afficher les données qui m'intéressaient et de comprendre les relations. Il est disponible dans~\cite{dendrobates} \texttt{cache\_utils/*.py} + \item Un environnement et un script pour déployer l'expérience automatiquement sur des noeuds de Grid'5000~\cite{g5k-results} +\end{itemize} + +\subsection*{\TODO{Remerciements}} +Remercier équipe, maitre de stage, labo +\ \textbf{Aknowledgements} Experiments presented in this paper were carried out using the Grid'5000 testbed, supported by a scientific interest group hosted by Inria and including \textsc{Cnrs}, \textsc{Renater} and several Universities as well as other organizations (see \url{https://www.grid5000.fr} ). -%\nocite{*} -\bibliographystyle{plain} -\bibliography{refs} - -\section{À faire pour continuer le stage} - -Plusieurs pistes se proposent pour continuer le travail présenté dans ce rapport : -\begin{itemize} - \item Clarifier les hypothèses avancées dans ce rapport : - sur la cohérence des modèles proposés avec la réalité et effectuer certaines vérifications : - \texttt{numactl} permet-il bien de verrouiller les pages partagées ? Peut-on proposer Une - renumérotation automatique des slices ? - \item proposer une méthode de réassignation automatique des slices pour savoir depuis un - utilisateur non privilégié la \ang{slice} d'une adresse virtuelle ; - \item réaliser l'attaque Flush+Flush sur des systèmes à 2 \ang{sockets} -\end{itemize} - -\TODO{Question à poser pour les systèmes à 10 sockets : si l'on désactive un coeur, la slice correspondante est-elle désactivée ? dans ce cas, qu'en est-il de la fonction de hachage ?} - - -\TODO{Faire un passage sur le code : ce que j'ai apporté, -ce qui était déjà fait. Où le trouver} - -\TODO{Passage sur le labo, l'équipe, l'ambiance} - \end{document} diff --git a/refs.bib b/refs.bib index 72a53be..f8bb310 100644 --- a/refs.bib +++ b/refs.bib @@ -121,3 +121,11 @@ note={\url{https://gitea.augustin64.fr/l3-ENSL/g5k-results/}}, year={2024} } + +@online{dendrobates, + author={Guillaume DIDIER, Augustin LUCAS}, + title={dendrobates-t-azureus}, + url={https://gitea.augustin64.fr/l3-ENSL/dendrobates-t-azureus/}, + note={\url{https://gitea.augustin64.fr/l3-ENSL/dendrobates-t-azureus/}}, + year={2024} +}