Ce premier TP est un TP d'introduction. Il ne donnera lieu ni à un compte-rendu ni à une note. Les TPs 2 et 3 utiliseront MINIX et tout ce qui se trouve dans ce TP (sauf la dernière partie) sera considéré comme acquis.
Comme nous allons utiliser des outils UNIX, tout le TP se fera sous Linux (système principal) et MINIX (système émulé).
Les systèmes Unix possèdent de nombreux utilitaires en ligne de commande bien pratiques tels que wc
(compte les lignes, mots, octets dans un fichier), sed
(remplacement de chaînes de caractères dans un fichier), grep
(recherche d'expression régulières dans un fichier), cut
(sélection de colonnes dans un fichier), ... Certaines de ces commandes sont des filtres et peuvent être composées grâce à l'opérateur |
. Nous vous conseillons d'apprendre à les utiliser car sous MINIX, vous aurez seulement une interface en ligne de commande. (Vous aurez par contre toujours accès à votre session graphique Linux.)
MINIX ("Mini Unix") est à l'origine un système d'exploitation à but pédagogique. Depuis la version 3, il s'agit également d'un système d'exploitation de type UNIX (conforme à la norme POSIX) qui peut facilement être adapté et utilisé dans des systèmes embarqués. Même s'il s'agit d'un système minimaliste de type micro-noyau, il est possible d'installer toute une chaîne de développement (gcc, emacs, etc.) ainsi qu'un serveur X.
La dernière version stable est la version 3.3.0, mais nous utiliserons une version précédente (3.1.8) qui est plus facile à modifier...
Plutôt que d'installer MINIX réellement sur le disque, nous allons l'installer dans une machine virtuelle. Cela a plusieurs intérêts comme :
Nous allons utiliser QEMU, un émulateur libre qui permet d'émuler de nombreux type de processeurs (i386
, x86_64
, sparc
, PowerPC, ...). Autrement dit, nous pouvons choisir le type de processeur utilisé par la machine virtuelle. Comme MINIX est un système 32 bit, nous allons utiliser le processeur i386
.
L'installation de MINIX est relativement aisée. Nous allons installer MINIX dans un « disque virtuel » (contenu dans un fichier) et l'utiliser à travers QEMU.
Pour ne pas saturer vos comptes personnels (l'image décompressée du CD d'installation fait environ 115MB, et il faut compter environ 300MB pour pouvoir compiler un système confortablement), nous allons installer MINIX dans un répertoire temporaire.
Ceci signifie que votre installation de MINIX sera disponible uniquement sur l'ordinateur que vous utilisez pour le TP, et seulement jusqu'au prochain redémarrage.
Une autre possibilité est de l'installer dans un sous répertoire de /local/
, sur lequel vous avez les droits d'écriture. Votre système virtuel ne sera pas effacé au redémarrage, mais ne sera disponible que sur la machine initiale, et utilisable par toute personne loggée sur cette machine...
Les lignes de commandes que vous devrez taper sont indiquées comme ceci :
LINUX$ commande1 LINUX$ commande2
Notez bien que :
$
" : il s'agit du "prompt" et il ne fait pas partie de la commande ;
$
" est précédé du LINUX
ou bien MINIX
: cela vous indique si cette commande doit être tapée dans le système principal (Linux) ou le système émulé (Minix) ;
$
" est remplacé par "#
" : cela signifie que cette commande doit être entrée par l'administrateur (sous Minix).
Avant d'installer MINIX à proprement parler, il faut booter une machine virtuelle en utilisant l'image du CD d'installation. Tout ceci se fait de la manière suivante :
TP-OS
dans /tmp/
:
LINUX$ cd /tmp/ LINUX$ mkdir TP-OS LINUX$ cd TP-OS
LINUX$ df -h
/
) doit contenir au moins 1G.
LINUX$ qemu --version
/tmp/TP-OS/
, soit par un navigateur (voir les liens au début du sujet), soit avec
LINUX$ wget http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/1617/info524/minix3_1_8_ide_r8165.iso.bz2
LINUX$ bunzip2 minix3_1_8_ide_r8165.iso.bz2
LINUX$ md5sum minix3_1_8_ide_r8165.iso
e3575aba599f07ae58dd532fde8d5407
minix-TP.img
de 300MB avec QEMU
LINUX$ qemu-img create minix-TP.img 300M
Nous avons maintenant tout ce qu'il faut pour installer Minix !
Nous allons maintenant démarrer le système virtuel en bootant "sur le CDROM virtuel" (fichier contenant l'image ISO du CD d'installation) :
LINUX$ qemu-system-i386 -m 256 -cdrom minix3_1_8_ide_r8165.iso -drive file=minix-TP.img,if=ide,media=disk,cache=writeback -boot d
Les arguments intéressants sont :
-m 256
pour spécifier 256MB de RAM à l'intérieur du système émulé
-cdrom minix3_1_8_ide_r8165.iso
pour dire que le fichier est l'image du CD contenu dans le lecteur de CD virtuel
-drive file=minix-TP.img,if=ide,media=disk,cache=writeback
pour spécifier que le disque virtuel est donné par le fichier minix-TP.img
et donner donner quelque optimisations pour QEMU,
-boot d
pour forcer la machine virtuelle à booter sur le lecteur de CD.
Comme la plupart des systèmes réels, QEMU va essayer de booter sur le CD avant de booter sur le disque dur. QEMU lancera donc le CD d'installation.
Si le boot sur le CD virtuel se passe bien, vous devriez obtenir une nouvelle fenêtre QEMU qui contient le système émulé. L'installation se fait maintenant en suivant les instructions du CD d'installation : loggez vous en tant qu'administrateur (root
, sans mot de passe).
Attention, il se peut que l'affichage initial ne se mette pas à jours avant le login. Il faut alors appuyer sur Entrée
afin de voir le login apparaitre.
Lancez ensuite la commande setup
pour commencer l'installation.
MINIX# setup
et suivez les instructions :
/home/
de 40MB
Vous pouvez ensuite éteindre la machine virtuelle :
MINIX# shutdown
et quitter QEMU :
cd>off
Félicitations, vous avez installé MINIX sur une machine virtuelle. Pour démarrer cette machine virtuelle, on utilise la commande
LINUX$ qemu-system-i386 -m 256 -drive file=minix-TP.img,if=ide,media=disk,cache=writeback
(Notez qu'on ne déclare plus d'image pour le CD.)
Control
et c
(en même temps) pour continuer.
Control
et Alt
en même temps.
NumLock
" est activée. Il suffit de la désactiver et tout fonctionne normalement.
Lors du démarrage de MINIX, il est préférable de choisir le second système ("2 Start Custom MINIX 3
") car c'est le noyau qui est modifié par défaut. Le choix 1
reste (normalement) le système officiel.
Au boot (avant le login), le clavier est par défaut en mode QWERTY. Pour choisir le noyau 2, il faut donc appuyer sur la touche 2 sans la touche Shift.
Les premières étapes pour configurer MINIX seront :
MINIX# passwd
other
et donnez lui le login etu
. Son répertoire personnel sera dans /home/etu
. La commande nécessaire s'appelle adduser
...
Quittez la session root
et utilisez ce nouveau compte utilisateur...
L'éditeur par défaut de MINIX, s'appelle mined
:
MINIX$ mined <nom_de_fichier>
Il suffit de connaître 2 commandes :
Control
et x
en même temps pour quitter mined
Control
et w
en même temps pour sauver le fichier sur le disque
Control
et s
en même temps ne fait pas ce à quoi vous vous attendez. Évitez de l'utiliser...
Pour avoir d'autres raccourcis clavier, reportez vous aux commentaires au début du fichier /usr/src/commands/mined/mined1.c
, section 4 (lien local).
Pour les TPs suivant, une image MINIX déjà configurée vous sera fournie. Elle contiendra entre autre l'éditeur de texte Nano et ViM afin de rendre l'édition de code source plus facile.
Commencez par éditer le fichier .ashrc
dans votre répertoire personnel. Il s'agit d'un fichier texte qui permet de configurer votre shell. Vous pouvez par exemple :
PS1
:
export PS1="\w $ "
\w
). (Si vous changez le prompt de l'administrateur, mettez un #
à la place du $
pour les différencier...)
alias ls='ls -F' alias la='ls -A' alias ll='ls -l'
ll
au lieu de ls -l
dans le shell et ainsi de gagner quelques secondes ! (Il ne faut pas oublier de redémarrer le shell avec exec sh
ou bien en le quittant et se reloguant...)
Afin de gagner du temps dans la partie suivante, il est fortement conseillé de recompiler le noyau MINIX (sans modification) pendant que vous faites cette partie du TP. Pour cela, loggez-vous comme administrateur sur la deuxième console (accessible avec Alt-F2
) et
MINIX# cd /usr/src/tools/ MINIX# make image
Vous pouvez revenir sur la première console (Alt-F1
) pendant que le noyau compile...
fork()
) et affiche le PID du sous-processus créé
MINIX$ cc proc1.c -o proc1 MINIX$ ./proc1 & Salut, je m'appelle Bob et je suis le pere. Mon fils a le PID 185. Hej, je suis le fils de Bob.
ps
pour obtenir la liste des processus.
kill
depuis le shell) sans que le fils ne disparaisse.
Recommencez mais tuez cette fois ci le fils. Que se passe t'il ?
Vérifiez qu'un processus zombie disparaît quand son père l'a « attendu ». Comment procédez-vous ?
Rappel : l'appel système pour attendre qu'un processus fils se termine est wait
. Il s'utilise de la manière suivante :
int status, pid; ... pid = wait(&status);
La variable pid
aura comme valeur le PID du fils qui s'est terminé et la variable status
contiendra des informations sur comme ce processus s'est terminé. (On n'aura besoin ni de l'un ni de l'autre dans cet exercice...)
Pour ces questions, vous pouvez facilement insérer des sleep(1);
dans votre programme pour attendre 1 seconde. Cela vous permettra de regarder l'évolution des processus...
Pour installer et utiliser un nouveau noyau, il faut :
/usr/src/tools
,
make install
(si vous avez compilé le noyau dans la partie précédente, ça sera assez rapide : un peu moins de 5 minutes sur les machines de l'université). Cette commande recompile et installe le noyau.
2 Start Custom MINIX 3
" au démarrage. (Le noyau "1 Start MINIX 3
" ne sera jamais écrasé, ce qui vous permet de rebooter sur le noyau Minix standard.)
Attention : lorsque vous modifiez un fichier du noyau, n'oubliez pas de faire une sauvegarde !
MINIX# cp <fichier> <fichier.bak>
Ceci vous permettra de retrouver l'état de départ si vous faites des erreurs !
Recompilez un noyau en changeant le message de bienvenue du début :
Copyright 2010, Vrije Universiteit, Amsterdam, The Netherlands ...
De cette manière, vous pourrez vérifier que vous exécutez bien votre nouveau noyau.
Note : les sources du noyau se trouvent dans le répertoire /usr/src/kernel/
Les exemples précédents utilisent la fonction POSIX fork()
. Cette fonction est gérée par le serveur « process manager
» dans /usr/src/servers/pm/
.
Trouvez le fichier correspondant et modifier le pour afficher un message lors de chaque exécution de fork()
.
Recompilez votre noyau et testez le.
fork()
n'est pas un appel système. Sous MINIX, l'architecture micro-noyau a pour conséquence qu'il y a très peu de vrais appels système. (Fonctions qui nécessitent le mode noyau.) En général, un appel système se décompose en :
sendrec
),
Seules les étapes 2 et 4 se font en mode noyau.
Vous pouvez obtenir la liste des commandes qui vont nécessiter ceci en regardant dans le répertoire /usr/src/lib/libc/syscall
. (Je crois...)
Nous allons maintenant ajouter une « porte dérobée », c'est à dire, une manière d'accéder au système en tant qu'administrateur sans fournir de mot de passe !
Si vous arrivez à distribuer votre version modifiée de Minix, vous pourrez ainsi accéder à tous les systèmes installés qui utilisent votre version...
Pour installer la backdoor, il va falloir effectuer quelques opérations sur les chaînes de caractères.
strcmp
(str
ingc
omp
are), qui prend 2 chaînes en arguments et qui renvoie 0
lorsqu'elles sont identiques.
strcpy
(str
ing c
opy
) comme ceci :
strcpy(s, "test");
Il n'est pas nécessaire de comprendre tout le code de login.c
pour pouvoir le modifier. La stratégie suivante permettra de créer la backdoor assez facilement :
backdoor
qui prendra la valeur 0
lorsque que l'utilisateur utilise Gulliver
comme login,
name
est initialisée : c'est elle qui contient le nom saisi par l'utilisateur,
backdoor
à ce moment là
name
par root
pour garantir l'accès à un shell administrateur,
backdoor != 0
.
backdoor != 0
.
Il n'est pas nécessaire de recompiler le noyau pour avoir la nouvelle version de login
: il suffit de recompiler login.c
avec la commande make
dans le répertoire contenant login.c
. Il faut ensuite tester le fichier exécutable, et quand il fonctionne, l'installer.
Vous devrez donc faire quelque chose comme :
MINIX# cd /usr/src/commands/login/ MINIX# cp login.c login-orig.c MINIX# mined login.c < modification de "login.c" > MINIX# make MINIX# ./login < test de la commande "login" > MINIX# cp login /usr/bin/login < seulement si la commande "login" fonctionne correctement >
Attention ! Si vous installez une version buggée de login
, vous risquez de ne pas pouvoir vous logger sur le système MINIX...
Faites une copie de sauvegarde du fichier /usr/src/commands/login/login.c
, puis modifiez le pour ajouter un « backdoor » dans votre version de Minix : lors de la procédure de login, si l'utilisateur utilise le nom "Gulliver", alors il n'aura pas besoin de mot de passe et obtiendra l'accès au compte administrateur !
À la fin du processus de boot, le noyau demande au serveur init
(dans /usr/src/servers/init/
) d'ouvrir des consoles pour se logger. (MINIX en démarre trois par défaut, Linux en démarre six.) Ces consoles sont accessibles avec Alt
et une touche Fonction
. C'est /usr/src/commands/login/login.c
qui gère le login, et /usr/src/commands/getty/getty.c
qui appelle la commande de login dans chaque console.
Nous allons modifier la backdoor pour que le mot de passe Gulliver
ne fonctionne que sur la troisième console. Il va donc falloir modifier le fichier /usr/src/commands/getty/getty.c
. Lorsque que vous avez pu installé la backdoor dans `login``, vous allez :
login.c
et une version avec backdoor :
MINIX# mv login.c _login.c MINIX# mv login-orig.c login.c MINIX# mined Makefile < ajout de "_login" sur la ligne "PROG="> MINIX# make MINIX# cp login _login /usr/bin/
login
pour la version standard et _login
pour la version avec backdoor.
do_login
(dans le fichier /usr/src/commands/getty/getty.c
) pour avoir une version qui appelle /usr/bin/_login
à la place de /usr/bin/login
,
do_login
existant par un test :
tty_name
) correspond à la troisième console ("/dev/ttyc2"
), on appelle la nouvelle version de do_login
,
do_login
normalement.
getty
:
MINIX# cd /usr/src/commands/getty MINIX# cp getty.c getty-orig.c MINIX# mined getty.c < modification de "getty.c" > MINIX# make MINIX# cp getty /bin/ < seulement si la compilation se fait sans erreur >
Modifiez votre backdoor pour que la procédure de login acceptant "Gulliver" ne soit utilisé que sur la troisième console virtuelle.