HOWTO Partition racine en lecture seule

Un article de Gentoo Linux Wiki.

Cet article fait partie des HOWTOs.
Méthodes d'installation CD Live Noyau et matériel Portables et Notebooks Portage Système Réseaux et Services Serveur X Logiciels fréquemment utilisés Autres

L'objectif de cette astuce est de faire fonctionner Gentoo avec la partition racine montée en lecture seule. La méthode exposée ici n'est pas encore parfaite, mais fonctionnera. Cette astuce trouve son origine dans un texte de Thomas Hood.

Sommaire

[modifier] But et principes

Le système de fichiers racine n'a pas à être modifié fréquemment, sauf pour quelques fichiers de configuration. Il est donc raisonnable de placer cette racine en lecture seule, et même tentant  :

  • si l'utilisateur souhaite une solution simple pour utiliser un support non réinscriptible pour le stockage de son répertoire racine (une meilleure solution serait d'aller voir HOWTO Construire son LiveCD ou HOWTO Créer une LiveCD ou une LiveUSB),
  • pour éviter que des coupures de courant ou plantages intempestifs ne causent des erreurs dans la partition racine (problème peu grave avec un système de fichiers journalisé),
  • si l'utilisateur est paranoïaque et souhaite sécuriser son système encore mieux qu'avant.

[modifier] Méthode

Pour cette astuce, il faut disposer de devfs ou de udev. L'un ou l'autre sont disponibles ou installés en standard dans Gentoo.

Il n'est pas possible de placer de but en blanc la racine en lecture seule, car plusieurs fichiers importants pour le système situés dans le répertoire /etc doivent être accessibles en écriture, notamment au démarrage du système. Une première idée serait de placer /etc sur une partition à part, avec un accès en écriture. Mais cela n'est pas non plus possible, car le fichier /etc/fstab doit être accessible avant le montage des partitions autres que racine.

Que les logiciels intègrent dans leur code que /etc sert aux fichiers de configuration et /var aux fichiers destinés à être modifiés lors du fonctionnement normal du système serait une bonne chose. Dans l'intervalle, il faudra soit :

  • modifier le code des programmes, ce qui est simple dans le cas de scripts de démarrage, mais plus fastidieux dans le cas de programmes compilés. Par ailleurs, il faudra appliquer soi-même le patch à chaque mise à jour des scripts ou logiciels, à moins d'avoir convaincu les mainteneurs de l'intérêt du problème.
  • mettre sur /etc des liens symboliques pointant vers une copie de ces fichiers sur une partition accessible en écriture.

Si la partition racine doit être en lecture seule, elle ne doit pas contenir de répertoires ayant besoin d'un accès en écriture. Il sera nécessaire de réserver une partition accessible en écriture pour chacun des répertoires /home, /tmp, /var (soit leur attribuer chacun une partition, soit les regrouper dans une seule partition par exemple à l'aide de liens, en faisant pointer /var vers /home/var et /tmp vers /home/tmp, si l'aspect inesthétique de la chose ne vos dérange pas trop).

Les fichiers de /etc devant être accédés en écriture ont besoin d'un stockage pérenne. Dans la suite, nous supposerons qu'un répertoire /var/etc est créé sur un disque local pour contenir ces fichiers.

[modifier] Le cas mtab

/etc/mtab est le fichier qui décrit les systèmes de fichiers montés sur l'arborescence. Il doit être accessible en écriture à chaque montage/démontage d'un système de fichiers, notamment au démarrage du système. Son cas est particulier parce que le programme mount tel qu'il est conçu ne peut pas écrire vers un lien symbolique.

[modifier] Première solution

Première solution, remplacer mtab par un lien symbolique vers /proc/mounts. Ce fichier spécial décrit également à tout instant l'état des systèmes de fichiers montés, et peut donc remplacer mtab sans qu'il soit besoin d'avoir un accès en écriture pour sa mise à jour. Cependant, le manuel de mount mentionne que dans le cas des périphériques loop, cette solution ne fonctionnera pas, car les informations fournies par /proc/mounts ne comprennent pas les options de montage.

Code : Création d'un lien vers /proc/mounts
# cd /etc
# rm mtab
# ln -s /proc/mounts mtab

Il faut également indiquer dans les scripts d'initialisation qu'il convient de ne pas tenter de créer de fichier /etc/mtab. Pour cela, il faut ajouter l'option -n aux commandes mount situées dans le script /etc/init.d/localmount.

Dans le script localmount, remplacer les lignes 13 et 36.

Fichier : Modification de localmount
La ligne 13 :
mount -at nocoda,nonfs,noproc,noncpfs,nosmbfs,noshm >/dev/null

devient :
mount -nat nocoda,nonfs,noproc,noncpfs,nosmbfs,noshm >/dev/null

La ligne 36 :
mount -t ${usbfs} none /proc/bus/usb &>/dev/null

devient :
mount -nt ${usbfs} none /proc/bus/usb &>/dev/null

[modifier] Deuxième solution

Deuxième solution, remplacer /etc/mtab par un lien symbolique vers un fichier sur une partition accessible en écriture. Cela nécessite alors d'appliquer un patch à mount de façon qu'il soit capable d'écrire vers un lien symbolique. Le patch, conçu pour la version 2.12 du paquet sys-apps/util-linux, peut être téléchargé depuis la page de Thomas Hood.

Supposons que les sources de ce paquet et le patch soient présents sur le disque. Pour appliquer le patch et recompiler, entrez les commandes suivantes (à adapter avec les numéros de version éventuellement plus récents ou vos noms de répertoire) :

Code : Compilation de mount avec le patch
# ebuild /usr/portage/sys-apps/util-linux/util-linux-2.12-r5.ebuild unpack
# cd /var/tmp/portage/util-linux-2.12-r5/work/util-linux-2.12/
# patch -Np1 < (/home/.../)mount-2.12-symlinkmtab_20030914
# cp /bin/mount /bin/mount.old
# cp /bin/umount /bin/umount.old
# ebuild /usr/portage/sys-apps/util-linux/util-linux-2.12-r5.ebuild merge

Il est alors possible de passer mtab en lien symbolique :

Code : Création d'un lien vers /var/etc/mtab
# cd /etc/
# cp mtab /var/etc
# rm mtab
# ln -s /var/etc/mtab

Si, pour une raison ou une autre, le fichier mtab venait à n'être pas synchronisé avec ce qu'il devrait être, il est toujours possible de créer un fichier mtab utilisable en entrant :

Code : Recréation de mtab en cas de problème
# cat /proc/mounts > /var/etc/mtab

[modifier] Scripts de démarrage

Certains scripts de démarrage du répertoire /etc/init.d, ont besoin d'un accès en écriture avant même que les systèmes de fichiers soient montés (ce qui est effectué par le script localmount). Il s'agit de modules, checkroot, checkfs et hostname. Dans ce cas, le mieux que nous ayons à faire est nous assurer qu'ils n'ont rien à faire de capital avec l'accès en écriture qu'ils ne pourront pas avoir. Le script domainname, quant à lui, demande un accès en écriture, mais est exécuté après le montage des systèmes de fichiers locaux.

[modifier] modules

Les dépendances des modules sont calculées à chaque démarrage de la distribution Gentoo et nécessitent un accès en écriture sur la partition racine. Pour contourner ce problème, il suffit de suivre l'astuce Un démarrage plus rapide. Cette astuce permet d'éviter que ce calcul soit effectué inutilement à chaque démarrage. Si par la suite, vous compilez un nouveau module pour le noyau, il faudra penser à exécuter le script modules-update avec l'écriture autorisée sur la racine, de façon à régénérer /etc/modules.conf

[modifier] checkroot

Le script checkroot initialise proprement mtab à partir de /proc/mounts. Si la solution choisie pour mtab est un lien de /proc/mounts vers mtab, il n'y a rien de particulier à faire, le système se contentera de cette sortie. Il n'est pas nécessaire d'initialiser mtab mais le faire ne créera aucun problème.

Dans l'autre cas (un lien de /var/etc/mtab vers /etc/mtab), l'initialisation de mtab doit être faite après le montage des systèmes de fichiers. Pour cela, il est possible d'inclure la partie de code utile dans un script de démarrage. Le choix le plus simple est de placer ces lignes dans /etc/conf.d/local.start, spécialement prévu pour la personnalisation par l'utilisateur. Cependant, pour être perfectionniste, il faudrait faire cette initialisation le plus tôt possible, c'est-à-dire dès le montage de la partition où se trouve mtab. Si le fichier mtab est sur un disque local, c'est /etc/init.d/localmount qui monte ces systèmes de fichiers. Il est donc possible d'ajouter ce code à la fonction start de localmount

Il s'agit de code copié de /etc/init.d/checkroot, en ayant pris soin de remplacer /etc/mtab par /var/etc/mtab.

Fichier : Partie du code de checkroot à insérer à localmount ou local.start
#
# Create /etc/mtab
#

# Clear the existing mtab
> /var/etc/mtab

# Add the entry for / to mtab
mount -f /

# Don't list root more than once
awk '$2 != "/" {print}' /proc/mounts >> /var/etc/mtab

# Now make sure /etc/mtab have additional info (gid, etc) in there
for x in $(awk '{ print $2 }' /proc/mounts | uniq)
do
        for y in $(awk '{ print $2 }' /etc/fstab)
        do
                if [ "${x}" = "${y}" ]
                then
                        mount -f -o remount $x
                        continue
                fi
         done
done


[modifier] checkfs

Si la solution retenue pour mtab est un lien vers /var/etc/mtab, alors le script checkfs ne pourra pas lire mtab et se plaindra lors du démarrage, pour les systèmes de fichiers étant marqués dans fstab comme noauto. Par exemple :

ext2fs_check_if_mount: No such file or directory while determining whether /edv/hdax is mounted

Les systèmes de fichiers dont il ne peut déterminer s'ils sont montés étant sont justement ceux qui ne sont pas montés au démarrage, l'échec de check_if_mount est bénin (voir e2fsprogs/e2fsck/unix.c à la fonction fonction check_mount).

Si la solution retenue est le lien vers /proc/mounts, checkfs pourra toujours avoir accès à cette information et ne se plaindra pas.

[modifier] hostname

/etc/init.d/hostname lit le fichier /etc/hostname, règle le nom de la machine en fonction de ces informations, et les écrit dans /etc/env.d/hostname. Si l'accès en écriture n'est pas possible, cette information ne pourra être mise à jour. Cela n'est pas bien grave, si le nom de l'ordinateur n'a pas changé. Si vous changez ce nom (en mettant à jour /etc/hostname), pensez à exécuter à nouveau hostname (l'écriture étant autorisée pour la racine).

[modifier] domainname

Le script /etc/init.d/domainname étant exécuté après le montage des systèmes de fichier, et est responsable de la création des fichiers resolv.conf et resolv.conf.new. Il ne suffit pas de créer un lien de /etc/resolv.conf vers /var/etc/resolv.conf. (et idem pour resolv.conf.new) En effet, le script veut renommer resolv.conf.new en resolv.conf, et la commande mv ne suit pas les liens. Si vous tenez à ce que ce script se termine comme il se doit, vous devrez modifier le script domainname. Au choix, vous pouvez :

  • créer dans /etc des liens symboliques vers /var/etc/resolv.conf et resolv.conf.new et remplacer dans domainname la commande mv par cp
  • remplacer dans le script domainname toute référence à /etc/resolv.conf et resolv.conf.new par /var/etc/resolv.conf et resolv.conf.new

/var/etc/resolv.conf.new

[modifier] Fichiers individuels

La liste exacte des fichiers devant être accessibles en écriture dépend des logiciels installés sur le système. Il est facile d'obtenir une liste des fichiers modifiés depuis une date donnée grâce au programme find.

Code : Recherche des fichiers à traiter
# find /etc -newer /etc/mtab

(Cela suppose que vous n'ayez pas encore modifié votre mtab ! Si vous l'avez déjà fait, essayez un autre fichier modifié au démarrage, comme resolv.conf.)

Le code ci-dessus détermine la liste des fichiers modifiés depuis le dernier montage ou démontage d'un système de fichiers avec la commande mount. Si l'utilisateur n'a rien monté de sa propre initiative depuis le démarrage, alors cette commande fournit la liste des fichiers modifiés depuis le script localmount, ce qui n'omettra que les fichiers modifiés par les scripts de démarrage de grande priorité, et dont une liste est donnée plus loin.

Parmi les fichiers qui doivent être accessibles en écriture, on trouve dans /etc :

  • adjtime, ioctl.save, resolv.conf, resolv.conf.new,
  • csh.env, profile.env (qui sont spécifiques à la distribution Gentoo),
  • printcap, cups/certs (si vous utilisez des services d'impression).

Ces fichiers n'étant utilisés qu'après le montage des systèmes de fichiers locaux, nous avons tout loisir des les remplacer par un lien vers /var/etc. Ces opérations doivent bien sûr être reproduites pour tous les fichiers que vous aurez à traiter. Dans le cas particulier de adjtime, la norme FHS propose comme répertoire : /var/lib/hwclock.

Code : Création d'un lien vers adjtime
# cd /var/lib
# mkdir hwclock
# cp /etc/adjtime /var/lib/hwclock
# cd /etc
# rm adjtime
# ln -s /var/lib/hwclock/adjtime

[modifier] varia

Il faut également prévoir des liens symbolique permettant de rediriger les quelques répertoires de la racine devant être accessibles en écriture. C'est le cas du répertoire /usr/tmp, que l'on peut rediriger au choix vers /tmp ou /var/tmp.

Code : Création d'un lien pour /usr/tmp
# cd /usr/
# rmdir tmp/
# ln -s /tmp/

[modifier] Modifications additionnelles

Si vous avez lancé des services comme samba, cups ou ppp, vous devrez faire quelques modification supplémentaires.

[modifier] cups

Dans le cas de cups, vous devrez comme plus haut créer un lien symbolique vers le répertoire /ect/cups/certs et les fichiers contenus à l'intérieur. N'oubliez pas de donner les permissions nécessaires à ces fichiers, qui doivent appartenir au groupe lp.

Par exemple :

Code : Copie des certificats de cups dans /var/etc/
# cd /var/etc/
# mkdir cups/
# chown root:lp cups
# cd cups
# cp -p -r /etc/cups/certs certs
# cd /etc/cups
# mv certs certs.old
# ln -s /var/etc/cups/certs
# chown root:lp /var/etc/cups/certs/*

[modifier] Touche finale

Une fois toutes ces opérations effectuées, il faut placer le répertoire racine en lecture seule pour le prochain redémarrage. Dans le fichier /etc/fstab, la ligne contenant le répertoire racine doit être modifiée de façon à ajouter l'option ro de lecture seule.

Fichier : Adapter fstab

Par exemple, la ligne :

/dev/hdax	/	ext2	noatime		0 1

devient :

/dev/hdax	/	ext2	noatime,ro	0 1

Dans l'utilisation quotidienne, vous souhaiterez à l'occasion passer la racine en lecture-écriture. Ce sera le cas si vous avez besoin de votre répertoire /root (qui ne doit pas être sur une autre partition, car il sert en cas de graves problèmes sur le système à se connecter en tant que root alors que les autres systèmes de fichier ne sont pas montés), vous installez un nouveau logiciel, vous mettez à jour la configuration...

Pour passer en écriture autorisée puis revenir à la lecture seule, une commande mount en tant que superutilisateur suffit :

Code : Passer en écriture autorisée et revenir en lecture seule
# mount -w -o remount / # L'écriture est désormais autorisée
# mount -r -o remount / # Lecture seule

Pour faciliter cette tâche, il est possible d'écrire des raccourcis pour le shell du super-utilisateur.

Code : Ajouter des alias pour bash
# echo "alias rw='mount -w -o remount /'" >> ~/.bashrc
# echo "alias ro='mount -r -o remount /'" >> ~/.bashrc

(Le fichier d'initialisation est parfois appelé .bash_login)

Passez votre racine en lecture seule à l'aide de la commande plus haut puis redémarrez. Soyez attentifs aux messages d'initialisation, ils contiennent des informations sur les opérations ayant échoué faute de pouvoir écrire. Une fois les problèmes de votre cas particulier résolus, vous pourrez venir compléter ce tutorial.

[modifier] Utilisation en lecture/écriture

Si vous souhaitez utiliser temporairement votre système de fichiers racine mode lecture-écriture, vous devrez penser que certains programmes (mount, en particulier, si le patch de Thomas Hood n'est pas utilisé) vont à la première occasion remplacer les liens symboliques que vous avez créés pour eux par des fichiers réguliers. Une fois que vous aurez terminé votre travail en mode lecture/écriture, si vous avez lancé un programme qui a besoin d'écrire sur les fichiers que vous avez remplacés par des liens symboliques, pensez à vérifier que vos liens existent toujours et recréez-les en cas de besoin.

Avant de lancer une commande emerge, pensez à passer en lecture-écriture. Si ce n'est pas le cas, emerge ne peut pas copier sur la racine les fichiers qu'il a compilés. Dans le cas de emerge --unmerge, il ne pourra pas effacer de fichiers, mais il est possible qu'il croie avoir réussi, et mette faussement à jour sa base de programmes installés. Dans ce cas de figure, il faut recompiler le programme avant de pouvoir l'enlever !

[modifier] Remarques

Si vous avez suivi cette astuce, vous avez dû modifier modules et vous avez peut-être choisi de modifier les scripts localmount et domainname. Si tel est le cas, vous serez obligé de faire les mêmes modifications lorsque vous mettrez à jour votre Gentoo avec emerge baselayout.

[modifier] Références

Les informations de base de cette méthode sont issues du texte (en anglais) de Thomas Hood. Son document est destiné à la distribution Debian, mais a un intérêt plus large. Notamment, l'auteur y maintient à jour une liste des paquets posant problème, ainsi que les modifications entreprises dans ces logiciels et dans la distribution Debian.

La page d'accueil de Thomas Hood contient également un lien vers le patch pour mount mentionné plus haut, les références de la discussion tenue sur la liste de diffusion debian-devel et une discussion sur l'intérêt pour ce sujet d'un éventuel répertoire /etc/run.

Autres langues