[SOS] sos: au sujet de defauts d'initialisation

ecolbus at voila.fr ecolbus at voila.fr
Ven 23 Nov 22:11:50 CET 2007


> Je pensais que SOS s'etait eteint d'une mort discrete. J'ai ete surpris -agreablement- de constater , 
> courant Octobre, qu'il etait toujours vivant.
> 
> J'en profite pour rapporter deux classes d'incident que j'ai essentiellement rencontrees au cours 
> d'exploration de versions derivees de la 9_5. A l'analyse du code de la version 10, je constate que la 
> plupart des incidents sont encore applicables.
> 
> Il me semble donc utile de les communiquer:
> 
> Anomalie constatee:
> 
> A. Initialisation incorrecte de variables statiques:
> 
> ====================================================
> 
> Dans "certaines conditions" , certaines variables supposees initialisees ne le sont pas.
> 
> Exemple: 
> 
> - fs.c: fs_list
> 
> - uaccess.c : __uaccess_zero_fool_gcc
> 
> - mm_context.c: current_mm_context et list_mm_context
> 
> - process.c: process_list (non applicable a la version 10)
> 
> 
> 
> De plus, et inversement, certaines variables , dont l'etat doit etre tres precis au demarrage et ne 
> faisant l'objet d'aucune action d'initialisation (que ce soit dans la declaration ou dans une procedure > explicite) se retrouvent dans un etat compatible avec celui attendu et ne perturbent en rien le 
> fonctionnement de SOS.
> 
> Dans "certaines conditions", ce fait est dramatique.
> 
> Par exemple:
> 
> - fs_virtfs.c: structure virtfs_type
> 
> - chardev.c : registered_chardev_classes
> 
> - blkdev.c : registered_blockdev_instances
> 
> Pour ces trois exemples, ces variables doivent imperativement etre initialisee a zero. Ceci n'est pas 
> fait, et , dans la plupart des cas, le systeme fonctionne correctement.
> 
> 
> 
> Le linkeur place toutes ces variables apres la borne __e_load. Cette borne est definie de maniere a 
> englober les sections ".data" et ".rodata". 
> 
> Nos variables fautives ne sont donc pas placees dans aucune de ces deux sections. 
> 
> Elles echappent ainsi a l'initialisation realisee par le processus de chargement du noyau (qui arrete le 
> chargement a la borne __e_load).
> 
> l'outil "nm" renseigne que ces variables sont placees dans une section 'b'(ou 'B'), c'est a dire , non 
> initialisee. Pour les variables ne faisant pas l'objet d'une initialisation a la declaration, ce 
> placement ne semble pas aberrant. 
> 
> 
>
> En examinant de pres le comportement de gcc, on constate qu'il traite de maniere particuliere le
> placement des variables initialisees a zero: toutes les variables ainsi initialisee sont placees 
> dans une section placee au dela de notre borne de chargement. En fait, dans une section ".bss". 
> On peut alors conjecturer que GCC compte sur le runtime pour initialiser la zone .bss a zero. Nous en 
> avons un exemple au sein meme de SOS: dans la section "userland", la fonction de demarrage des taches 
> (_start) commence en tout premier a fixer a zero toute la zone bss. 

Bonjour,

Le comportement de gcc est parfaitement correct : pour ne pas prendre de place dans le binaire ELF
généré, les variables initialisées à 0 sont placées dans une section qui n'occupe aucun espace physique
dans le fichier (et la spécification du C précise bien que les variables statiques non initialisées par
le programmeur, qu'elles fassent ou non partie du common, sont initialisées à 0).

Gcc place donc ces variables dans la section .bss, dont la taille virtuelle indique la taille que cette section doit occuper en mémoire, et dont la taille physique est de 0. Comme la spécification ELF impose
que les zones mémoires dépassant du fichier projeté soient mises à 0, toutes ces variables
sont automatiquement initialisées lorsque le système d'exploitation charge les pages correspondantes
en mémoire.

> Ce dysfonctionnement a ete constate sur un seul PC (sur les 3 uniques PCs qui m'ont servi de test) et 
> sur une version derivee de la 9.5.
> 
> 
> Je pense donc que ,pour une raison que j'ignore (etat initial a zero, initialisation explicite par le 
> Bios ?), la memoire se trouve souvent dans un etat compatible avec les attentes de SOS. Ceci n'est pas 
> une raison pour proposer une version de SOS plus robuste capable de resister a ce type d'alea en 
> corrigeant ce defaut dans l'initialisation.

Le bogue se trouve manifestement dans le chargeur de SOS. Simplement, la RAM s'initialise généralement
à 0 après le démarrage, mais ce n'est pas obligatoire. De plus, le BIOS et le chargeur peuvent laisser
certaines zones altérées après leur passage.

> De mon coté, j'ai ajoute des instructions explicites d'initialisation dans les fonctions 
> d'initialisation de chaque module, quand ceci etait possible:
> 

Je ne connais pas le code de SOS, donc je ne suis pas sûr de mon fait, mais il y a un risque pour
que cela ne fonctionne pas. Si gcc parvient à démontrer que la variable n'a pas été modifiée avant
le passage dans cette fonction, comme il sait que la variable a été initialisée à 0, il est en droit,
à titre d'optimisation, de supprimer cette affectation.

Heureusement, ce genre de démonstration n'est généralement pas possible dans un module, où il y a
plusieurs points d'entrée menant à des modifications des différentes variables. Mais, pour
un module qui n'exporterait qu'une seule fonction, cela peut se produire.

E. Colbus



Plus d'informations sur la liste de diffusion Sos