virli/tutorial/3/tutorial.tex

1758 lines
57 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\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{<<EOF}
\NormalTok{CREATE DATABASE metrics;}
\NormalTok{SHOW DATABASES;}
\OperatorTok{EOF}
\end{Highlighting}
\end{Shaded}
\end{english}
Vérifiez que la base de données \texttt{metrics} a bien été créée.
\hypertarget{monitoring-instantanuxe9-vers-la-console}{%
\subsubsection{Monitoring instantané vers la
console}\label{monitoring-instantanuxe9-vers-la-console}}
Dans un premier temps, commençons par afficher dans la console, la
quantité de mémoire utilisée par le groupe monitoré.
Vous pouvez utiliser un programme comme \texttt{memhog} pour remplir
rapidement votre mémoire.
\begin{english}[variant=american]
\begin{verbatim}
42sh# mkdir /sys/fs/cgroup...
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../tasks
42sh# ./monitor group_name memhog 500
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
~~~ 13595 ~~~ Current memory usage: 223690752/550502400 (40%)
~~~ 13595 ~~~ Current memory usage: 296828928/550502400 (53%)
~~~ 13595 ~~~ Current memory usage: 368001024/550502400 (66%)
~~~ 13595 ~~~ Current memory usage: 438517760/550502400 (79%)
~~~ 13595 ~~~ Current memory usage: 480329728/550502400 (87%)
~~~ 13595 ~~~ Current memory usage: 155648/550502400 (0%)
\end{verbatim}
\end{english}
Si vous n'avez pas le \emph{cgroup} \emph{memory}, il est possible qu'il
ne soit pas activé par défaut par votre système. Si vous êtes dans ce
cas, essayez d'ajouter \texttt{cgroup\_enable=memory} à la ligne de
commande de votre noyau.
\hypertarget{monitoring-vers-influxdb}{%
\subsubsection{Monitoring vers
InfluxDB}\label{monitoring-vers-influxdb}}
Maintenant, envoyons nos données vers la base
\url{https://docs.influxdata.com/influxdb/v1.6/guides/writing_data/} :
\begin{english}[variant=american]
\begin{Shaded}
\begin{Highlighting}[]
\ExtensionTok{curl}\NormalTok{ -i -XPOST }\StringTok{'http://localhost:8086/write?db=metrics'}\NormalTok{ --data-binary \textbackslash{}}
\StringTok{"}\VariableTok{$my_cgroup_name}\StringTok{ memory.usage_in_bytes=}\VariableTok{$(}\FunctionTok{cat}\NormalTok{ .../my_cgroup_name/memory.usage_in_bytes}\VariableTok{)}\StringTok{"}
\end{Highlighting}
\end{Shaded}
\end{english}
Pour vérifier que les données ont bien été ajoutées, nous pouvons
effectuer la requête suivante dans notre client \texttt{influx} :
\begin{english}[variant=american]
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{SELECT} \OperatorTok{*} \KeywordTok{from} \OtherTok{"$my_cgroup_name"}\NormalTok{;}
\end{Highlighting}
\end{Shaded}
\end{english}
\hypertarget{monitorer-davantage-de-donnuxe9es}{%
\subsubsection{Monitorer davantage de
données}\label{monitorer-davantage-de-donnuxe9es}}
Liste non exhaustive de données à monitorer :
\begin{itemize}
\tightlist
\item
Nombre d'IOs effectué ;
\item
nombre d'octets lu/écrit sur les disques ;
\item
temps de calcul utilisé ;
\item
trafic réseau généré ;
\item
\ldots{}
\end{itemize}
Tous les cgroups existants dans le dernier noyau publié ont leur
documentation accessible ici :
\url{https://www.kernel.org/doc/Documentation/cgroup-v1/}
\hypertarget{permettre-uxe0-lutilisateur-de-monitorer-des-processus}{%
\subsubsection{Permettre à l'utilisateur de monitorer des
processus}\label{permettre-uxe0-lutilisateur-de-monitorer-des-processus}}
Maintenant, séparons notre script en deux parties afin qu'un utilisateur
normal (non-root) puisse utiliser la partie monitoring de notre script.
Un premier script doit s'occuper de créer le(s) \emph{cgroup}s et lui
attribuer les bons droits, tandis que le deuxième va effectuer le
monitoring, sans privilèges particuliers.
\hypertarget{exemple}{%
\paragraph{Exemple}\label{exemple}}
\begin{english}[variant=american]
\begin{verbatim}
42sh$ sudo ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500
\end{verbatim}
\end{english}
\hypertarget{fixer-des-limites}{%
\subsection{Fixer des limites}\label{fixer-des-limites}}
Au delà de la simple consultation, les \emph{cgroup}s peuvent servir à
limiter la quantité de ressources mise à disposition à un groupe de
processus.
Pour définir une limite, nous allons écrire la valeur dans le fichier
correspondant à une valeur limite, comme par exemple
\texttt{memory.max\_usage\_in\_bytes}, qui limite le nombre d'octets que
notre groupe de processus va pouvoir allouer au maximum :
\begin{english}[variant=american]
\begin{verbatim}
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
0
# 0 = Aucune limite
42sh$ echo 4M > /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}