\PassOptionsToPackage{unicode=true}{hyperref} % options for packages loaded elsewhere \PassOptionsToPackage{hyphens}{url} \PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor} % \documentclass[12pt,english,a4paperpaper,]{article} \usepackage{lmodern} \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{textcomp} % provides euro and other symbols \else % if luatex or xelatex \usepackage{unicode-math} \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase} \setmainfont[]{Linux Libertine O} \setsansfont[]{Linux Biolinum O} \setmonofont[Mapping=tex-ansi]{FantasqueSansMono-Regular} \fi % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} % use microtype if available \IfFileExists{microtype.sty}{% \usepackage[]{microtype} \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts }{} \usepackage{xcolor} \usepackage{hyperref} \hypersetup{ pdftitle={Virtualisation légère -- TP no 3}, pdfauthor={Pierre-Olivier nemunaire Mercier}, colorlinks=true, linkcolor=black, filecolor=Maroon, citecolor=Blue, urlcolor=ForestGreen, breaklinks=true} \urlstyle{same} % don't use monospace font for urls \usepackage{color} \usepackage{fancyvrb} \newcommand{\VerbBar}{|} \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} % Add ',fontsize=\small' for more characters per line \newenvironment{Shaded}{}{} \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\BuiltInTok}[1]{#1} \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} \newcommand{\ExtensionTok}[1]{#1} \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} \newcommand{\ImportTok}[1]{#1} \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} \newcommand{\NormalTok}[1]{#1} \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} \newcommand{\RegionMarkerTok}[1]{#1} \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \setlength{\emergencystretch}{3em} % prevent overfull lines \providecommand{\tightlist}{% \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \setcounter{secnumdepth}{5} % Redefines (sub)paragraphs to behave more like sections \ifx\paragraph\undefined\else \let\oldparagraph\paragraph \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} \fi \ifx\subparagraph\undefined\else \let\oldsubparagraph\subparagraph \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} \fi % set default figure placement to htbp \makeatletter \def\fps@figure{htbp} \makeatother % Decent marging... \usepackage[cm]{fullpage} % Indentation for all paragraph (even the first one) + ventilate \usepackage{indentfirst} \setlength{\parskip}{6pt plus 2pt minus 1pt} % Avoid vertical space before/after itemize \usepackage{enumitem} \setlist{nosep} % Use sans-serif font for section' titles \usepackage{sectsty} \allsectionsfont{\sffamily \bfseries} % Use sans-serif font for title page \usepackage{titling} \renewcommand{\maketitlehooka}{\sffamily} % Use monospaced font for URLs \urlstyle{tt} % In french, list item starts with dash, not bullet \renewcommand\labelitemi{---} \usepackage{etoolbox} \makeatletter \pretocmd{\subsection}{\addtocontents{toc}{\protect\addvspace{-5\p@}}}{}{} \pretocmd{\subsubsection}{\addtocontents{toc}{\protect\addvspace{-6\p@}}}{}{} \makeatother \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[shorthands=off,american,main=english]{babel} \newcommand{\textenglish}[2][]{\foreignlanguage{american}{#2}} \newenvironment{english}[2][]{\begin{otherlanguage}{american}}{\end{otherlanguage}} \else % load polyglossia as late as possible as it *could* call bidi if RTL lang (e.g. Hebrew or Arabic) \usepackage{polyglossia} \setmainlanguage[]{english} \setotherlanguage[variant=american]{english} \fi \title{Virtualisation légère -- TP n\textsuperscript{o} 3} \providecommand{\subtitle}[1]{} \subtitle{Linux Internals partie 1} \author{Pierre-Olivier \emph{nemunaire} \textsc{Mercier}} \providecommand{\institute}[1]{} \institute{EPITA} \date{Mercredi 24 octobre 2018} \begin{document} \maketitle \begin{abstract} Ce premier TP consacré aux Linux Internals va nous permettre d'appréhender les notions de pseudos systèmes de fichiers, de cgroups ainsi que de capabilities. \vspace{1em} Certains éléments de ce TP sont à rendre à \href{mailto:virli@nemunai.re}{\nolinkurl{virli@nemunai.re}} au plus tard le mercredi 7 novembre 2018 à 12 h 42. Consultez la dernière section de chaque partie pour plus d'information sur les éléments à rendre. En tant que personnes sensibilisées à la sécurité des échanges électroniques, vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à \href{https://pgp.mit.edu/pks/lookup?op=vindex\&search=0x842807A84573CC96}{me} faire signer votre clef et n'hésitez pas à \href{https://www.meetup.com/fr/Paris-certification-de-cles-PGP-et-CAcert/}{faire signer votre clef}. \end{abstract} \renewcommand*\contentsname{Sommaire} { \hypersetup{linkcolor=} \setcounter{tocdepth}{3} \tableofcontents } \newpage \hypertarget{pruxe9requis}{% \section{Prérequis}\label{pruxe9requis}} \hypertarget{noyau-linux}{% \subsection{Noyau Linux}\label{noyau-linux}} Ce TP requiert un noyau Linux, dans sa version 3.8 au minimum. Il doit de plus être compilé avec les options suivantes (lorsqu'elles sont disponibles pour votre version) : \begin{english}[variant=american] \begin{verbatim} General setup ---> [*] Control Group support ---> [*] Freezer cgroup subsystem [*] PIDs cgroup subsystem [*] Device controller for cgroups [*] Cpuset support [*] Simple CPU accounting cgroup subsystem [*] Memory Resource Controller for Control Groups [*] Group CPU scheduler ---> [*] Group scheduling for SCHED_OTHER [*] Group scheduling for SCHED_RR/FIFO <*> Block IO controller [*] Networking support ---> Networking options ---> [*] Network priority cgroup [*] Network classid cgroup \end{verbatim} \end{english} \hypertarget{vuxe9rification-via-menuconfig}{% \subsubsection{\texorpdfstring{Vérification via \texttt{menuconfig}}{Vérification via menuconfig}}\label{vuxe9rification-via-menuconfig}} L'arbre ci-dessous correspond aux options qui seront \emph{built-in} (signalées par une \texttt{*}) ou installées en tant que module (signalées par un \texttt{M}). En effet, chaque noyau Linux peut être entièrement personnalisé en fonction des options et des pilotes que l'on voudra utiliser. Pour parcourir l'arbre des options du noyau, il est nécessaire d'avoir les sources de celui-ci. Les dernières versions stables et encore maintenues sont disponibles sur la page d'accueil de \url{https://kernel.org}. Dans les sources, on affiche la liste des options avec la commande : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{make}\NormalTok{ menuconfig} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{vuxe9rification-via-bootconfig-xxx}{% \subsubsection{\texorpdfstring{Vérification via \texttt{/boot/config-xxx}}{Vérification via /boot/config-xxx}}\label{vuxe9rification-via-bootconfig-xxx}} Les distributions basées sur Debian ont pour habitude de placer le fichier de configuration ayant servi à compiler le noyau et ses modules dans le dossier \texttt{/boot}, aux côtés de l'image du noyau \texttt{vmlinuz-xxx}, de l'éventuel système de fichiers initial (\texttt{initramfs-xxx}) et des symboles de débogage \texttt{System.map-xxx}. Ce fichier répertorie toutes les options qui ont été activées. Par rapport à l'arbre présenté ci-dessus, vous devriez trouver : \begin{english}[variant=american] \begin{verbatim} CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_MEMCG=y CONFIG_CGROUP_SCHED=y CONFIG_BLK_CGROUP=y CONFIG_NET=y CONFIG_CGROUP_NET_PRIO=y CONFIG_CGROUP_NET_CLASSID=y \end{verbatim} \end{english} \hypertarget{vuxe9rification-via-procconfig.gz}{% \subsubsection{\texorpdfstring{Vérification via \texttt{/proc/config.gz}}{Vérification via /proc/config.gz}}\label{vuxe9rification-via-procconfig.gz}} Dans la plupart des autres distributions, la configuration est accessible à travers le fichier \texttt{/proc/config.gz}. Comme vous ne pouvez pas écrire dans \texttt{/proc} pour décompresser le fichier, utilisez les outils \texttt{zcat}, \texttt{zgrep}, \ldots{} Vous devez retrouver les mêmes options que celles de la section précédente. \hypertarget{pruxe9sence-des-en-tuxeates}{% \subsection{Présence des en-têtes}\label{pruxe9sence-des-en-tuxeates}} Si vous utilisez un noyau standard fourni par votre distribution, les options requises seront a priori déjà sélectionnées et vous n'aurez donc pas à compiler votre propre noyau. Néanmoins, durant ce TP, nous allons nous interfacer avec le noyau, il est donc nécessaire d'avoir les en-têtes de votre noyau. Sous Debian, vous pouvez les installer via le paquet au nom semblable à \texttt{linux-headers}. \newpage \hypertarget{lisolation-du-pauvre}{% \section{L'isolation \ldots{} du pauvre}\label{lisolation-du-pauvre}} Depuis les premières versions d'Unix, il est possible de changer le répertoire vu comme étant la racine du système de fichiers. En anglais : \emph{change root}: \texttt{chroot}. Le processus effectuant cette action ainsi que tous ses fils, verront donc une racine différente du reste du système. \hypertarget{mise-en-place-de-lenvironnement}{% \subsection{Mise en place de l'environnement}\label{mise-en-place-de-lenvironnement}} Pour se créer un environnement afin de changer notre racine, il va falloir commencer par créer le dossier de notre nouvelle racine : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{mkdir}\NormalTok{ newroot} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{busybox}{% \subsubsection{\texorpdfstring{\texttt{busybox}}{busybox}}\label{busybox}} Queques mots, pour commencer, à propos du projet Busybox : c'est un programme \emph{linké} statiquement, c'est-à-dire qu'il ne va pas chercher ni charger de bibliothèque dynamique à son lancement. Il se suffit donc à lui-même dans un \emph{chroot}, car il n'a pas de dépendances. Nous pouvons donc tester notre première isolation~: \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{cp} \VariableTok{$(}\FunctionTok{which}\NormalTok{ busybox}\VariableTok{)}\NormalTok{ newroot/} \FunctionTok{chroot}\NormalTok{ newroot /busybox ash} \end{Highlighting} \end{Shaded} \end{english} Jusque là \ldots{} ça fonctionne, rien de surprenant ! Mais qu'en est-il pour \texttt{bash} : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ cp }\VariableTok{$(}\FunctionTok{which}\NormalTok{ bash}\VariableTok{)}\NormalTok{ newroot/} \ExtensionTok{42sh}\NormalTok{# chroot newroot /bash} \ExtensionTok{chroot}\NormalTok{: failed to run command ‘bash’: No such file or directory} \end{Highlighting} \end{Shaded} \end{english} De quel fichier est-il question ici ? \hypertarget{debootstrap}{% \subsubsection{\texorpdfstring{\texttt{debootstrap}}{debootstrap}}\label{debootstrap}} \texttt{debootstrap} est le programme utilisé par l'installeur des distributions Debian et ses dérivées. Il permet d'installer dans un dossier (en général, ce dossier correspond au point de montage de la nouvelle racine choisie par l'utilisateur lors de l'installation) le système de base. \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{debootstrap}\NormalTok{ jessie newroot/ http://httpredir.debian.org/debian/} \end{Highlighting} \end{Shaded} \end{english} \texttt{pacstrap} est le programme équivalent pour Archlinux. \hypertarget{stage3}{% \subsubsection{\texorpdfstring{\emph{stage3}}{stage3}}\label{stage3}} Les distributions \emph{à l'ancienne} proposent encore de télécharger leur système de base sous forme de tarball~: \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{wget}\NormalTok{ http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20181021T214502Z.tar.xz} \FunctionTok{tar}\NormalTok{ xpf stage3-amd64-*.tar.xz -C newroot/} \end{Highlighting} \end{Shaded} \end{english} L'avantage de télécharger l'archive de Gentoo est que l'on a déjà \texttt{gcc} dans un environnement qui tient dans 300 MB. \hypertarget{exercice}{% \subsection*{Exercice}\label{exercice}} \addcontentsline{toc}{subsection}{Exercice} Écrivons maintenant un programme dont le seul but est de s'échapper du \texttt{chroot} : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{make}\NormalTok{ escape} \BuiltInTok{echo}\NormalTok{ bar }\OperatorTok{>}\NormalTok{ ../foo} \FunctionTok{chroot}\NormalTok{ .} \end{Highlighting} \end{Shaded} \end{english} Dans le nouvel environnement, vous ne devriez pas pouvoir faire : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{cat}\NormalTok{ ../foo} \end{Highlighting} \end{Shaded} \end{english} Mais une fois votre programme \texttt{escape} exécuté, vous devriez pouvoir ! \begin{english}[variant=american] \begin{verbatim} (chroot) 42sh# ./escape bash# cat /path/to/foo \end{verbatim} \end{english} \newpage \hypertarget{pseudos-systuxe8mes-de-fichiers}{% \section{Pseudos systèmes de fichiers}\label{pseudos-systuxe8mes-de-fichiers}} \hypertarget{rappels-sur-les-points-de-montage}{% \subsection{Rappels sur les points de montage}\label{rappels-sur-les-points-de-montage}} Les systèmes Unix définissent le système de fichiers comme étant un arbre unique partant d'une racine\footnote{Consultez \url{https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard} pour plus de détails sur l'arboresence.} et où l'on peut placer au sein de son arborescence des points de montage. Ainsi, l'utilisateur définit généralement deux points de montage : \begin{english}[variant=american] \begin{verbatim} /dev/sda1 on / type ext4 (rw,relatime,data=ordered) /dev/sda3 on /home type ext4 (rw,relatime,data=ordered) \end{verbatim} \end{english} Dans ce schéma, la racine correspond à la première partition du premier disque, et les fichiers des utilisateurs sont sur la troisième partition du premier disque. \hypertarget{pruxe9sentation-des-pseudos-systuxe8mes-de-fichiers}{% \subsection{Présentation des pseudos systèmes de fichiers}\label{pruxe9sentation-des-pseudos-systuxe8mes-de-fichiers}} D'autres points de montage sont utilisés par le système : \texttt{/dev}, \texttt{/proc}, \texttt{/tmp}, \ldots{} Ces points de montage vont, la plupart du temps, être montés par le programme d'initialisation en utilisant des systèmes de fichiers virtuels, mis à disposition par le noyau. Ces systèmes sont virtuels, car ils ne correspondent à aucune partition d'aucun disque : l'arborescence est créée de toute pièce par le noyau pour trier les informations mises à disposition, mais il n'est pas toujours possible d'y apporter des modifications. Linux emploie de nombreux systèmes de fichiers virtuels : \begin{itemize} \tightlist \item \texttt{/proc} : contient, principalement, la liste des processus (\texttt{top} et ses dérivés se contentent de lire les fichiers de ce point de montage) ; \item \texttt{/proc/sys} : contient la configuration du noyau ; \item \texttt{/sys} : contient des informations à propos du matériel (utilisées notamment par \texttt{udev} pour peupler \texttt{/dev}) et des périphériques (taille des tampons, clignottement des DELs, \ldots{}) ; \item \texttt{/sys/firmware/efi/efivars} : pour accéder et modifier les variables de l'UEFI ; \item \ldots{} \end{itemize} Tous ces systèmes de fichiers sont généralement exclusivement stockés en RAM. Pour rendre une modification persistante, il est nécessaire de modifier un fichier de configuration qui sera chargé par le programme d'initialisation. Par exemple, pour modifier les paramètres du noyau, on passe par le fichier \texttt{/etc/sysctl.conf} et du programme \texttt{sysctl}. \hypertarget{consultation-et-modification}{% \subsubsection{Consultation et modification}\label{consultation-et-modification}} La consultation d'un élément se fait généralement à l'aide d'un simple \texttt{cat} : \begin{english}[variant=american] \begin{verbatim} 42sh$ cat /sys/power/state freeze mem \end{verbatim} \end{english} La modification d'un élément se fait avec \texttt{echo}, comme ceci : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{# echo mem }\OperatorTok{>}\NormalTok{ /sys/power/state} \end{Highlighting} \end{Shaded} \end{english} Vous devriez constater l'effet de cette commande sans plus attendre ! \hypertarget{exercices}{% \subsection{Exercices}\label{exercices}} \hypertarget{procinfo}{% \subsubsection{\texorpdfstring{\texttt{procinfo}}{procinfo}}\label{procinfo}} Explorons le pseudo système de fichiers \texttt{/proc} pour écrire un script qui va afficher des informations sur un processus donné : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./procinfo $$ PID: 4242 Path: /bin/bash Command line: bash Working directory: /home/nemunaire/virli/ Root: / State: S (sleeping) Threads: 1 CGroups ======= 12:pids:/ 11:net_prio:/ 10:perf_event:/ 9:net_cls:/ 8:freezer:/ 7:devices:/ 6:memory:/ 5:blkio:/ 4:cpuacct:/ 3:cpu:/ 2:cpuset:/ 1:name=openrc:/ Namespaces ========== cgroup:[4026531835] ipc:[4026531839] mnt:[4026531840] net:[4026531969] pid:[4026531836] user:[4026531837] uts:[4026531838] \end{verbatim} \end{english} \hypertarget{rev_kdb_leds.sh-batinfo.sh-cpuinfo.sh}{% \subsubsection{\texorpdfstring{\texttt{rev\_kdb\_leds.sh}, \texttt{batinfo.sh}, \texttt{cpuinfo.sh}}{rev\_kdb\_leds.sh, batinfo.sh, cpuinfo.sh}}\label{rev_kdb_leds.sh-batinfo.sh-cpuinfo.sh}} Explorons le pseudo système de fichiers \texttt{/sys} pour écrire un script qui va, en fonction de ce que vous avez de disponible : \begin{itemize} \tightlist \item inverser l'état des diodes de notre clavier ; \item nous afficher des statistiques sur notre batterie ; \item nous afficher des statistiques la fréquence de notre CPU. \end{itemize} \hypertarget{rev_kdb_leds.sh}{% \paragraph{\texorpdfstring{\texttt{rev\_kdb\_leds.sh}}{rev\_kdb\_leds.sh}}\label{rev_kdb_leds.sh}} Si vous avez : \begin{itemize} \tightlist \item numlock On, \item capslock Off, \item scrolllock Off ; \end{itemize} Après avoir exécuté le script, nous devrions avoir : \begin{itemize} \tightlist \item numlock Off, \item capslock On, \item scrolllock On. \end{itemize} Voici un exemple d'utilisation : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./rev_kdb_leds.sh input20 \end{verbatim} \end{english} \hypertarget{batinfo.sh}{% \paragraph{\texorpdfstring{\texttt{batinfo.sh}}{batinfo.sh}}\label{batinfo.sh}} Voici un exemple d'utilisation : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./batinfo.sh BAT0 Discharging ==== Capacity: 83% (Normal) Voltage: 11.972000 V (minimal: 11.400000 V) Energy: 18.290000/21.830000 Wh Power: 7.937000 W Remaining time: 2.304 h BAT1 Unknown ==== Capacity: 83% (Normal) Voltage: 11.972000 V (minimal: 11.400000 V) Energy: 18.290000/21.830000 Wh Power: 0.0 W Remaining time: N/A \end{verbatim} \end{english} \hypertarget{cpuinfo.sh}{% \paragraph{\texorpdfstring{\texttt{cpuinfo.sh}}{cpuinfo.sh}}\label{cpuinfo.sh}} Voici un exemple d'utilisation : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./cpuinfo.sh cpu0 ==== Current frequency: 2100384 Hz Current governor: powersave Allowed frequencies: between 500000 - 2100000 Hz Thermal throttle count: 0 cpu1 ==== Current frequency: 2099871 Hz Current governor: powersave Allowed frequencies: between 500000 - 2100000 Hz Thermal throttle count: 0 \end{verbatim} \end{english} N'hésitez pas à rajouter toute sorte d'information intéressantes ! \newpage \hypertarget{les-capabilities}{% \section{\texorpdfstring{Les \emph{capabilities}}{Les capabilities}}\label{les-capabilities}} \hypertarget{pruxe9sentation}{% \subsection{Présentation}\label{pruxe9sentation}} Historiquement, dans la tradition UNIX, on distinguait deux catégories de processus : \begin{itemize} \tightlist \item les processus \emph{privilégiés} : dont l'identifiant de son utilisateur est 0 ; \item les processus \emph{non-privilégiés} : dont l'identifiant de son utilisateur n'est pas 0. \end{itemize} Lors des différents tests de permission fait par le noyau, les processus privilégiés outrepassaient ces tests, tandis que les autres devaient passer les tests de l'effective UID, effective GID, et autres groupes supplémentaires\ldots{} Depuis Linux 2.2 (en 1998), les processus privilégiés peuvent activer ou désactiver des \emph{capabilities}, chacune donnant accès à un groupe d'actions privilégiées au sein du noyau. On trouve par exemple : \begin{itemize} \tightlist \item \texttt{CAP\_CHOWN} : permet de modifier le propriétaire d'un fichier de manière arbitraire ; \item \texttt{CAP\_KILL} : permet de tuer n'importe quel processus ; \item \texttt{CAP\_SYS\_BOOT} : permet d'arrêter ou de redémarrer la machine ; \item \texttt{CAP\_SYS\_MODULE} : permet de charger et décharger des modules ; \item et beaucoup d'autres, il y en a environ 39 en tout (ça dépend de la version du noyau) ! \end{itemize} \hypertarget{ping}{% \subsubsection{\texorpdfstring{\texttt{ping}}{ping}}\label{ping}} Pour émettre un ping, il est nécessaire d'envoyer des paquets ICMP. À la différence des datagrammes UDP ou des segments TCP, il n'existe pas d'interface exposée par le noyau aux utilisateurs pour envoyer des paquets ICMP. Pour le faire, il est nécessaire de pouvoir écrire directement sur l'interface ; ça, seul le super-utilisateur peut le faire. Pour permettre à tous les utilisateurs de pouvoir envoyer des ping, le programme est donc généralement \emph{Setuid root}. Cela permet à n'importe quel utilisateur de prendre les droits du super-utilisateur, le temps de l'exécution du programme. Les problèmes surviennent lorsque l'on découvre des vulnérabilités dans les programmes \emph{Setuid root}. En effet, s'il devient possible pour un utilisateur d'exécuter du code arbitraire, ce code sera exécuté avec les privilèges de l'utilisateur \emph{root} ! Dans le cas de \texttt{ping}, on se retrouverait alors à pouvoir lire l'intégralité de la mémoire, alors que l'on avait juste besoin d'écrire sur une interface réseau. C'est donc à ce moment que les \emph{capabilities} entrent en jeu : un processus (ou même un thread) privilégié peut décider, généralement à son lancement, de réduire ses \emph{capabilities}, pour ne garder que celles dont il a réellement besoin. Ainsi, \texttt{ping} pourrait se contenter de \texttt{CAP\_NET\_RAW}. \hypertarget{les-attributs-de-fichier-uxe9tendus}{% \subsection{Les attributs de fichier étendus}\label{les-attributs-de-fichier-uxe9tendus}} Une grosse majorité des systèmes de fichiers (ext{[}234{]}, XFS, btrfs, \ldots{}) permet d'enregistrer, pour chaque fichier, des attributs (dits attributs \emph{étendus}, par opposition aux attributs \emph{réguliers} qui sont réservés à l'usage du système de fichiers). Sous Linux, les attributs sont regroupés dans des espaces de noms : \begin{itemize} \tightlist \item \emph{security} : espace utilisé par les modules de sécurité du noyau, tel que SELinux, \ldots{} ; \item \emph{system} : espace utilisé par le noyau pour stocker des objets système, tels que les ACL POSIX ; \item \emph{trusted}: espace dont la lecture et l'écriture est limité au super-utilisateur ; \item \emph{user} : modifiable sans restriction, à partir du moment où l'on est le propriétaire du fichier. \end{itemize} Par exemple, on peut définir un attribut sur un fichier comme cela : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ echo }\StringTok{'Hello World!'} \OperatorTok{>}\NormalTok{ toto} \ExtensionTok{42sh}\NormalTok{$ setfattr -n user.foo -v bar toto} \ExtensionTok{42sh}\NormalTok{$ getfattr -d toto} \CommentTok{# file: toto} \ExtensionTok{user.foo}\NormalTok{=}\StringTok{"bar"} \end{Highlighting} \end{Shaded} \end{english} Encore plus fort, vous pouvez utiliser les ACL POSIX : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ sudo chown root:root toto }\KeywordTok{&&} \FunctionTok{sudo}\NormalTok{ chmod o-r toto} \ExtensionTok{42sh}\NormalTok{$ cat toto} \ExtensionTok{cat}\NormalTok{: toto: Permission denied} \ExtensionTok{42sh}\NormalTok{$ sudo setfattr -m u:}\VariableTok{$USER}\NormalTok{:r toto} \ExtensionTok{42sh}\NormalTok{$ cat toto} \ExtensionTok{Hello}\NormalTok{ World!} \end{Highlighting} \end{Shaded} \end{english} Bien que les droits UNIX traditionnels ne vous donnent pas accès au fichier, les ACL POSIX vous autorisent à le lire. Vous pouvez voir ces attributs avec la commande : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ getfattr -d -m }\StringTok{"^system"}\NormalTok{ toto} \CommentTok{# file: toto} \ExtensionTok{system.posix_acl_access}\NormalTok{=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{ping-1}{% \subsubsection{\texorpdfstring{\texttt{ping}}{ping}}\label{ping-1}} De la même manière que l'on peut définir de façon plus fine les droits d'accès par utilisateur, un attribut de l'espace de nom \emph{security} peut être défini pour accroître les \emph{capabilities} d'un processus lorsqu'il est lancé par un utilisateur non-privilégié. On peut alors voir le Setuid root comme l'utilisation de cet attribut auquel on accroîtrait l'ensemble des \emph{capabilities}. Si votre distribution profite de ces attributs étendus, vous devriez obtenir : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ getfattr -d -m }\StringTok{"^security"} \VariableTok{$(}\FunctionTok{which}\NormalTok{ ping}\VariableTok{)} \CommentTok{# file: bin/ping} \ExtensionTok{security.capability}\NormalTok{=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=} \end{Highlighting} \end{Shaded} \end{english} Ou, dans sa version plus lisible : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{42sh}\NormalTok{$ getcap }\VariableTok{$(}\FunctionTok{which}\NormalTok{ ping}\VariableTok{)} \ExtensionTok{/bin/ping}\NormalTok{ = cap_net_raw+ep} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{exercice-visualisateur-de-capabilities-dun-processus}{% \subsection{Exercice : visualisateur de capabilities d'un processus}\label{exercice-visualisateur-de-capabilities-dun-processus}} Écrivons maintenant un programme permettant de voir les \emph{capabilities} d'un processus : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./view_caps 1 cap_user_header_t ----------------- Version: 20080522 PID: 1 cap_user_data_t --------------- effective: 0x3fffffffff CAP_AUDIT_CONTROL CAP_AUDIT_READ [...] CAP_SYS_TIME CAP_SYS_TTY_CONFIG CAP_SYSLOG CAP_WAKE_ALARM permitted: 0x3fffffffff CAP_AUDIT_CONTROL CAP_AUDIT_READ [...] CAP_SYS_TIME CAP_SYS_TTY_CONFIG CAP_SYSLOG CAP_WAKE_ALARM inheritable: 0x0 \end{verbatim} \end{english} Astuces : \texttt{capget(2)}, X-macros, \ldots{} \hypertarget{pour-aller-plus-loin}{% \subsection*{Pour aller plus loin}\label{pour-aller-plus-loin}} \addcontentsline{toc}{subsection}{Pour aller plus loin} Je vous recommande la lecture des \emph{man} suivants : \begin{itemize} \tightlist \item \texttt{capabilities(7)} : énumérant tous les capabilities, leur utilisation, etc. ; \item \texttt{xattrs(7)} : à propos des attributs étendus. \end{itemize} Et de ces quelques articles : \begin{itemize} \tightlist \item \href{https://rhelblog.redhat.com/2016/10/17/secure-your-containers-with-this-one-weird-trick/}{Secure Your Containers with this One Weird Trick} \item \href{https://www.freedesktop.org/wiki/CommonExtendedAttributes/}{Guidelines for extended attributes} \item \href{https://lwn.net/Articles/211883/}{File-based capabilities} \item \href{https://lwn.net/Articles/199004/}{A bid to resurrect Linux capabilities} \item \href{https://forums.grsecurity.net/viewtopic.php?f=7\&t=2522\&sid=c6fbcf62fd5d3472562540a7e608ce4e\#p10271}{False Boundaries and Arbitrary Code Execution} \end{itemize} Pour revenir à Docker, par défaut, un certain nombre de \emph{capabilities} sont désactivées par défaut ; vous pouvez en ajouter et en retirer via les arguments \texttt{-\/-cap-add} et \texttt{-\/-cap-drop} du \texttt{docker\ container\ run}. \newpage \hypertarget{utiliser-les-cgroups}{% \section{\texorpdfstring{Utiliser les \emph{cgroup}s}{Utiliser les cgroups}}\label{utiliser-les-cgroups}} Les \emph{cgroup}s (pour \emph{Control Group}s) permettent de collecter des statistiques sur des groupes de processus (appelés tâches) et de leur attribuer des propriétés. Par exemple, il est possible leur imposer des limites d'utilisation de ressources ou d'altérer leur comportement. \hypertarget{premiers-tests}{% \subsection{Premiers tests}\label{premiers-tests}} Nous allons commencer par faire quelques tests avec le \emph{cgroup} \emph{freezer}, qui permet d'interrompre l'exécution d'un groupe de processus et de la reprendre. \hypertarget{montage-du-cgroup}{% \subsubsection{\texorpdfstring{Montage du \emph{cgroup}}{Montage du cgroup}}\label{montage-du-cgroup}} En fonction de la configuration de votre système, il est possible que les \emph{cgroup}s ne soient pas montés au démarrage dans \texttt{/sys/fs/cgroup/}. Si vous n'avez pas de dossier \texttt{freezer} ou si celui-ci est vide, montez-le en suivant la procédure suivante : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{mkdir}\NormalTok{ /sys/fs/cgroup/freezer/} \FunctionTok{mount}\NormalTok{ -t cgroup -o freezer none /sys/fs/cgroup/freezer/} \end{Highlighting} \end{Shaded} \end{english} Cette dernière commande monte l'arborescence de groupes relative à ce \emph{cgroup} \emph{freezer}. Tous les dossiers contenus dans cette racine sont donc des sous-groupes. \hypertarget{cruxe9ation-dun-nouveau-groupe}{% \subsubsection{Création d'un nouveau groupe}\label{cruxe9ation-dun-nouveau-groupe}} La première étape dans l'utilisation d'un \emph{cgroup} est de créer un groupe. Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant, par exemple la racine : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \FunctionTok{mkdir}\NormalTok{ /sys/fs/cgroup/freezer/virli/} \FunctionTok{ls}\NormalTok{ /sys/fs/cgroup/freezer/virli/} \end{Highlighting} \end{Shaded} \end{english} Nous avons maintenant un nouveau groupe de processus \texttt{virli} dans le \emph{cgroup} \emph{Freezer}. Comme il s'agit d'une hiérarchie, le groupe \texttt{virli} hérite des propriétés de son (ses) père(s). \hypertarget{rattachement-de-processus}{% \subsubsection{Rattachement de processus}\label{rattachement-de-processus}} Pour le moment, ce nouveau groupe ne contient aucune tâche. Ouvrons un nouveau terminal (c'est lui que l'on va geler), et récupérons son PID : \texttt{echo\ \$\$}. La liste des processus rattachés à un \emph{cgroup} se trouve dans le fichier \texttt{task} du groupe. Pour ajouter une tâche à ce groupe, cela se passe de cette manière : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \BuiltInTok{echo} \VariableTok{$PID} \OperatorTok{>}\NormalTok{ /sys/fs/cgroup/freezer/virli/tasks} \end{Highlighting} \end{Shaded} \end{english} Il faut ici remplacer \texttt{\$PID} par le PID du shell que l'on a relevé juste avant. En validant cette commande, nous avons déplacé le processus dans ce groupe, il n'est alors plus dans aucun autre groupe (pour ce \emph{cgroup}, il ne bouge pas dans les autres \emph{cgroup}s). Malgré l'utilisation de la redirection \texttt{\textgreater{}} (et non \texttt{\textgreater{}\textgreater{}}), il s'agit belle et bien d'un ajout au fichier et non d'un écrasement. Il faut garder en tête que le système de fichier est entièrement simulé et que certains comportements sont adaptés. \hypertarget{consultation-de-luxe9tat}{% \subsubsection{Consultation de l'état}\label{consultation-de-luxe9tat}} En affichant le contenu du dossier \texttt{virli}, nous pouvions constater que celui-ci contenait déjà un certain nombre de fichiers. Certain d'entre-eux sont en lecture seule et permettent de lire des statistiques instantanées sur le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier. Nous pouvons consulter l'état de gel du groupe en affichant le contenu du fichier\newline \texttt{/sys/fs/cgroup/freezer/virli/freezer.state}. Pour plus d'information sur les différents fichiers présents dans ce \emph{cgroup}, consultez \href{https://www.kernel.org/doc/Documentation/cgroup-v1/freezer-subsystem.txt}{la documentation associée}. \hypertarget{changement-duxe9tat}{% \subsubsection{Changement d'état}\label{changement-duxe9tat}} Faisons exécuter à notre interpréteur une commande pour voir effectivement l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \KeywordTok{for} \ExtensionTok{i}\NormalTok{ in }\VariableTok{$(}\FunctionTok{seq}\NormalTok{ 9999}\VariableTok{)}\KeywordTok{;} \KeywordTok{do} \BuiltInTok{echo}\NormalTok{ -n }\VariableTok{$i}\KeywordTok{;} \FunctionTok{sleep}\NormalTok{ .1}\KeywordTok{;} \BuiltInTok{echo}\NormalTok{ -n }\StringTok{" - "}\KeywordTok{;} \FunctionTok{sleep}\NormalTok{ .1}\KeywordTok{;} \KeywordTok{done} \end{Highlighting} \end{Shaded} \end{english} Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de calcul à notre shell et ses fils : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \BuiltInTok{echo}\NormalTok{ FROZEN }\OperatorTok{>}\NormalTok{ /sys/fs/cgroup/freezer/virli/freezer.state} \end{Highlighting} \end{Shaded} \end{english} À cet instant, vous devriez voir votre compteur s'arrêter. Pour reprendre l'exécution : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \BuiltInTok{echo}\NormalTok{ THAWED }\OperatorTok{>}\NormalTok{ /sys/fs/cgroup/freezer/virli/freezer.state} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{exercice-script-de-monitoring}{% \subsection{Exercice : script de monitoring}\label{exercice-script-de-monitoring}} À nous maintenant de concevoir un script qui va enregistrer vers une base de données des statistiques issues des \emph{cgroup}s. \hypertarget{rappel-dinfluxdb}{% \subsubsection{Rappel d'InfluxDB}\label{rappel-dinfluxdb}} Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de l'installer sur notre machine) : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{docker}\NormalTok{ container run --name mytsdb -d -p 8086:8086 influxdb} \end{Highlighting} \end{Shaded} \end{english} Il nous faut ensuite créer une base de données pour y stocker nos métriques. Voici comment on s'était débrouillé dans un précédent TP pour interagir avec InfluxDB : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \ExtensionTok{docker}\NormalTok{ container exec -i mytsdb influxdb }\OperatorTok{< /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes # Maintenant, la limite est à 4MB, vérifions... 42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes 4194304 \end{verbatim} \end{english} Chaque \emph{cgroup}s défini de nombreux indicateurs et possède de nombreux limiteurs, n'hésitez pas à consulter la documentation associée à chaque \emph{cgroup}. \hypertarget{pour-aller-plus-loin-1}{% \subsection*{Pour aller plus loin}\label{pour-aller-plus-loin-1}} \addcontentsline{toc}{subsection}{Pour aller plus loin} Pour tout connaître en détails, \href{https://lwn.net/Articles/604609/}{la série d'articles de Neil Brown sur les Control groups} est excellente ! Depuis les noyaux 4.5, il est possible d'utiliser la nouvelle version du pseudo système de fichiers des \emph{CGroup}s. Le principal changement vient du regroupement au sein d'une seule hiérarchie des différents \emph{CGroup}s que l'on avait dans la v1. Davantage d'informations sont disponibles : \begin{itemize} \tightlist \item \href{https://lwn.net/Articles/679786/}{Understanding the new control groups API} ; \item \href{https://www.kernel.org/doc/Documentation/cgroup-v2.txt}{Kernel Document about Control Group v2}. \end{itemize} \newpage \hypertarget{gestion-de-la-muxe9moire}{% \section{Gestion de la mémoire}\label{gestion-de-la-muxe9moire}} Linux a une gestion de la mémoire bien particulière\footnote{Dépendant de la valeur de \texttt{/proc/sys/vm/overcommit\_memory}, généralement 0. Voir \url{https://www.kernel.org/doc/Documentation/vm/overcommit-accounting}.} : par défaut, \texttt{malloc(3)} ne retournera jamais \texttt{NULL}. En se basant sur l'euristique qu'un bloc mémoire demandé ne sera pas utilisé directement et que de nombreux process ne feront pas un usage total des blocks qu'ils ont alloués, le noyau permet d'allouer plus de mémoire qu'il n'y en a réellement disponible. La mémoire est donc utilisée de manière plus efficace. Mais évidemment, cela peut donner lieu à des situations où le noyau n'est plus en mesure de trouver de bloc physiquement disponible, alors qu'ils avaient effectivement été alloués au processus. Pour autant, ce n'est pas une raison pour tuer ce processus, car il est peut-être vital pour le système (peut-être est-ce \texttt{init} qui est en train de gérer le lancement d'un nouveau daemon). On dit alors que le noyau est \emph{Out-Of-Memory}. Pour se sortir d'une telle situation, et après avoir tenté de vider les caches, il lance son arme ultime, pour retrouver au plus vite de la mémoire : l'\emph{Out-Of-Memory killer}. \hypertarget{oom-killer}{% \subsection{OOM killer}\label{oom-killer}} Selon un algorithme dont on raconte qu'il ne serait pas basé entièrement sur l'aléatoire\footnote{\url{https://linux-mm.org/OOM_Killer}}, un processus est tiré au sort (plus un processus occupe de mémoire et plus il a de chance d'être tiré au sort) par l'OOM killer. Le sort qui lui est réservé est tout simplement une mort brutale. Pour permettre au système de disposer à nouveau de mémoire disponible. Si cela n'est pas suffisant, un ou plusieurs autres processus peuvent être tués à tour de rôle, jusqu'à ce que le système retrouve sa sérénité. \hypertarget{esquiver-loom-killer}{% \subsection{Esquiver l'OOM killer}\label{esquiver-loom-killer}} Au sein d'un \emph{cgroup} \emph{memory}, le fichier \texttt{memory.oom\_control} peut être utilisé afin de recevoir une notification du noyau avant que l'OOM-killer ne s'attaque à un processus de ce groupe. Grâce à cette notification, il est possible de figer le processus pour l'envoyer sur une autre machine. Et ainsi libérer la mémoire avant que l'OOM killer ne passe. Jetez un œil à \href{https://lwn.net/Articles/590960/}{cet article parru sur LVM} à ce sujet. \newpage \hypertarget{secure-computing-mode}{% \section{Secure Computing Mode}\label{secure-computing-mode}} Plus connue sous l'acronyme \emph{seccomp}, cette fonctionnalité du noyau Linux permet de restreindre les appels systèmes qu'un processus est autorisé à utiliser. En cas d'appel non autorisé, le processus fautif est directement tué (\texttt{SIGKILL}) par le noyau, ou, lorsque c'est précisé, un code \texttt{errno} particulier peut être renvoyé au programme. Depuis la version 3.17 du noyau, l'appel système \texttt{seccomp(2)} permet de faire entrer le processus courant dans ce mode. En effet, c'est le processus lui-même qui déclare au noyau qu'il peut désormais se contenter d'une liste réduite d'appel système ; à l'inverse des politiques de sécurité comme SELinux ou AppArmor, qui encapsulent les programmes pour toute la durée de leur exécution. \emph{Seccomp} est particulièrement utile lorsqu'un processus a terminé son initialisation (ne dépendant en général pas de données sujettes à l'exploitation de vulnérabilité) et doit commencer à entrer dans des portions de code promptes aux vulnérabilités : c'est notamment le cas des moteurs de rendus des navigateurs Firefox et Chrome. \hypertarget{pruxe9requis-1}{% \subsection{Prérequis}\label{pruxe9requis-1}} L'utilisation de \texttt{seccomp} nécessite d'avoir un noyau compilé avec l'option \texttt{CONFIG\_SECCOMP}. Vous aurez également besoin de la bibliothèque \texttt{libseccomp} car l'appel système \texttt{seccomp(2)} n'a pas de \emph{wrapper} dans la libc, vous devrez donc passer par cette bibliothèque. \hypertarget{mode_strict}{% \subsection{\texorpdfstring{\texttt{MODE\_STRICT}}{MODE\_STRICT}}\label{mode_strict}} Le mode traditionnel de \emph{seccomp} est de ne permettre uniquement l'utilisation des appels système \texttt{read(2)}, \texttt{write(2)} (sur les descripteurs de fichier déjà ouvert), \texttt{\_exit(2)} et \texttt{sigreturn(2)}. Historiquement, avant la création de l'appel système \texttt{seccomp(2)}, on activait ce mode via : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \NormalTok{prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);} \end{Highlighting} \end{Shaded} \end{english} Une fois passé cet appel système, toute entrée dans un appel système non autorisé conduit à un \texttt{SIGKILL} du processus. \hypertarget{mode_filter}{% \subsection{\texorpdfstring{\texttt{MODE\_FILTER}}{MODE\_FILTER}}\label{mode_filter}} Plus modulable que le mode strict, le mode de filtrage permet une grande amplitude en permettant au programmeur de définir finement quels appels systèmes le programme est autorisé à faire ou non, et quel sentence est exécutée en cas de faute. Notons que les processus fils issus (\texttt{fork(2)} ou \texttt{clone(2)}) d'un processus auquel est appliqué un filtre \texttt{seccomp}, héritent également de ce filtre. La construction de ce filtre est faite de manière programatique, via des règles BPF (\texttt{Berkeley\ Packet\ Filter}). On passe ensuite ce filtre BPF en argument de l'appel système : \begin{english}[variant=american] \begin{Shaded} \begin{Highlighting}[] \KeywordTok{struct}\NormalTok{ sock_filter filter[];} \KeywordTok{struct}\NormalTok{ sock_fprog prog = \{} \NormalTok{ .len = (}\DataTypeTok{unsigned} \DataTypeTok{short}\NormalTok{) (}\KeywordTok{sizeof}\NormalTok{(filter) / }\KeywordTok{sizeof}\NormalTok{(filter[}\DecValTok{0}\NormalTok{])),} \NormalTok{ .filter = filter,} \NormalTok{\};} \NormalTok{seccomp(SECCOMP_SET_MODE_FILTER, }\DecValTok{0}\NormalTok{, &prog);} \end{Highlighting} \end{Shaded} \end{english} \hypertarget{exercice-1}{% \subsubsection*{Exercice}\label{exercice-1}} \addcontentsline{toc}{subsubsection}{Exercice} Écrivez un programme filtrant un appel système, à l'aide de \texttt{seccomp} : \begin{english}[variant=american] \begin{verbatim} 42sh$ ./syscall_filter sleep 5 sleep: cannot read realtime clock: Operation not permitted 42sh$ \end{verbatim} \end{english} Dans cet exemple, l'appel système filtré est \texttt{nanosleep(2)}. \newpage \hypertarget{projet-et-rendu}{% \section{Projet et rendu}\label{projet-et-rendu}} \hypertarget{sujet}{% \subsection{Sujet}\label{sujet}} Vous allez commencer aujourd'hui un projet qui s'étendra au prochain TP et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs ! Cette semaine, il faudra faire en sorte de restreindre un groupe de processus pour qu'il ne puisse pas faire de déni de service sur notre machine. Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien utiliser du C, du C++, du Python, etc. L'usage de bibliothèques \textbf{non relatives} au projet est autorisé : le but de ce sujet est d'évaluer votre compréhension et votre utilisation de la tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette plomberie, n'hésitez pas à l'utiliser ! Gardez en tête que ce projet sera à continuer au prochain TP, où il sera principalement question de faire des appels systèmes. \hypertarget{palier-1-restreindre-lenvironnement-2-points}{% \subsection*{Palier 1 : Restreindre l'environnement (2 points)}\label{palier-1-restreindre-lenvironnement-2-points}} \addcontentsline{toc}{subsection}{Palier 1 : Restreindre l'environnement (2 points)} Après avoir mis en place les bases de votre programme, commencez par créer les différentes hiérarchies (si vous avez un noyau récent, vous pouvez utiliser les cgroups-v2) dont vous allez avoir besoin pour limiter l'utilisation de ressources. Puis, mettez en place ces limites : \begin{itemize} \tightlist \item pas plus d'1 GB de mémoire utilisée ; \item 1 seul CPU au maximum ; \item 100 PIDs ; \item \ldots{} \end{itemize} En bonus, vous pouvez gérer les cas où le noyau sur lequel s'exécute votre moulinette ne possède pas tous ces \emph{CGroup}s, au lieu de planter, ne rien faire n'est pas forcément une mauvaise solution. \hypertarget{palier-2-ruxe9duire-les-capabilities-2-points}{% \subsection*{\texorpdfstring{Palier 2 : Réduire les \texttt{capabilities} (2 points)}{Palier 2 : Réduire les capabilities (2 points)}}\label{palier-2-ruxe9duire-les-capabilities-2-points}} \addcontentsline{toc}{subsection}{Palier 2 : Réduire les \texttt{capabilities} (2 points)} Réduisez au maximum les \emph{capabilities}, de telle sorte qu'il ne soit pas possible de faire un ping dans l'environnement restreint : \begin{english}[variant=american] \begin{verbatim} 42sh# ping 9.9.9.9 PING 9.9.9.9 (9.9.9.9) 56(84) bytes of data. 64 bytes from 9.9.9.9: icmp_seq=1 ttl=56 time=3.93 ms 64 bytes from 9.9.9.9: icmp_seq=2 ttl=56 time=3.97 ms ^C --- 9.9.9.9 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 3.931/3.954/3.978/0.067 ms 42sh# ./mymoulette /bin/bash bash# curl http://www.linuxcontainers.org/ | md5sum c7d68d1cb4737125a84cd69f55add202 bash# ping 9.9.9.9 ping: icmp open socket: Permission denied \end{verbatim} \end{english} \textbf{Astuces~:} \texttt{prctl(2)}, \texttt{capabilities(7)}, \texttt{capget(2)}, \texttt{capset(2)}, \ldots{} Aidez-vous du visualisateur de \emph{capabilities} de la partie 4 du TP, pour voir si vous êtes sur la bonne voie. \hypertarget{palier-3-utilisable-par-un-utilisateur-1-point}{% \subsection*{Palier 3 : Utilisable par un utilisateur (1 point)}\label{palier-3-utilisable-par-un-utilisateur-1-point}} \addcontentsline{toc}{subsection}{Palier 3 : Utilisable par un utilisateur (1 point)} Jouez avec les attributs étendus pour qu'un utilisateur non-privilégié puisse exécuter votre moulinette. Ajoutez la/les commande(s) à votre Makefile ou script d'installation. \hypertarget{cruxe9ation-dun-environnement-dexuxe9cution-minimal}{% \subsection*{Création d'un environnement d'exécution minimal}\label{cruxe9ation-dun-environnement-dexuxe9cution-minimal}} \addcontentsline{toc}{subsection}{Création d'un environnement d'exécution minimal} Plutôt que d'utiliser votre système hôte au complet, avec tous ses programmes et toutes ses bibliothèques, il faudrait utiliser un système contenant le strict minimum. Recréez un environnement minimaliste, comme on a pu en voir dans la partie sur les \texttt{chroot}. \textbf{Ne mettez pas cet environnement dans votre tarball de rendu, il vous sera seulement utile pour faire des tests.} \hypertarget{palier-4-isolation-du-pauvre-1-point}{% \subsection*{Palier 4 : Isolation du pauvre (1 point)}\label{palier-4-isolation-du-pauvre-1-point}} \addcontentsline{toc}{subsection}{Palier 4 : Isolation du pauvre (1 point)} Nous n'avons pas encore vu de meilleure méthode pour mieux isoler l'environnement que de faire un \texttt{chroot}, ajoutez à votre programme cette isolation rudimentaire. Et rendez-vous au prochain cours pour avoir une meilleure isolation ! \begin{english}[variant=american] \begin{verbatim} 42sh$ which firefox /usr/bin/firefox 42sh# ./mymoulette ./newrootfs/ /bin/bash bash# which firefox which: no firefox in (/usr/bin:/usr/local/bin:/bin:/opt/bin) \end{verbatim} \end{english} \hypertarget{palier-5-seccomp-2-points}{% \subsection*{Palier 5 : seccomp (2 points)}\label{palier-5-seccomp-2-points}} \addcontentsline{toc}{subsection}{Palier 5 : seccomp (2 points)} Filtrez les appels systèmes de telle sorte qu'aucun programme exécuté dans votre bac à sable ne puisse plus lancer les appels systèmes suivants : \begin{itemize} \tightlist \item \texttt{nfsservctl(2)} ; \item \texttt{personality(2)} ; \item \texttt{pivot\_root(2)} ; \item \ldots{} \end{itemize} N'hésitez pas à en utiliser d'autres pour vos tests ;) \textbf{Astuces~:} \texttt{seccomp(2)}, \texttt{seccomp\_init(3)}, \texttt{seccomp\_load(3)}, \ldots{} \hypertarget{palier-bonus-automatisation-de-la-cruxe9ation-de-lenvironnement-5-points}{% \subsection*{Palier bonus : Automatisation de la création de l'environnement (5 points)}\label{palier-bonus-automatisation-de-la-cruxe9ation-de-lenvironnement-5-points}} \addcontentsline{toc}{subsection}{Palier bonus : Automatisation de la création de l'environnement (5 points)} Pour \emph{moulinéter} plusieurs étudiants en parallèle, vous allez avoir besoin de plusieurs environnements identiques. Plutôt que de recopier cet environnement, de le nettoyer, de le recréer, pour chaque étudiant, ajoutez à votre moulinette un support pour LVM : utilisez des \emph{snapshots} pour figer votre environnement et le dupliquer facilement pour chaque étudiant. L'usage est laissé à votre discrétion : vous pouvez ajouter un/des paramètres à votre \emph{moulette} pour indiquer le volume LVM à utiliser ou le définir en dur ou encore séparer la création de l'environnement et de la snapshot initiale dans un programme distinct. Si votre noyau dispose d'un UnionFS (AUFS ou OverlayFS par exemple), ou que vous disposez d'une partition \texttt{btrfs}, vous pouvez utiliser l'une de ces méthodes pour ajouter une couche en écriture, à la place de LVM. \hypertarget{modalituxe9-de-rendu}{% \subsection{Modalité de rendu}\label{modalituxe9-de-rendu}} Un service automatique s'occupe de réceptionner vos rendus, de faire les vérifications nécessaires et de vous envoyer un accusé de réception (ou de rejet). Ce service écoute sur l'adresse \href{mailto:virli@nemunai.re}{\nolinkurl{virli@nemunai.re}}, c'est donc à cette adresse et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne sera pas pris en compte. Par ailleurs, n'oubliez pas de répondre à \href{https://www.epitaf.fr/moodle/mod/quiz/view.php?id=40}{l'évaluation du cours}. \hypertarget{tarball}{% \subsection{Tarball}\label{tarball}} Tous les fichiers identifiés comme étant à rendre pour ce TP sont à placer dans une tarball (pas d'archive ZIP, RAR, \ldots{}). Voici une arborescence type (adaptez les extensions et les éventuels fichiers supplémentaires associés au langage que vous aurez choisi pour chaque exercice) : \begin{english}[variant=american] \begin{verbatim} login_x-TP3/escape.c login_x-TP3/procinfo.sh login_x-TP3/rev_kdb_leds.sh login_x-TP3/view_caps.c login_x-TP3/monitor.sh login_x-TP3/monitor_init.sh login_x-TP3/syscall_filter.c \end{verbatim} \end{english} Les premières étapes du projet ne sont pas à rendre et feront l'objet d'un rendu à part. \end{document}