Les débordements sur le tas

Avertissement

Section en cours de création, veuillez vous repporter à l'ancien cours: http://www.lse.epita.fr/secu/old/Cours-3.html#hof

Nous allons maintenant étudier une autre zone de la mémoire : le tas. Nous y trouvons les variables globales, statiques et les zones renvoyé par malloc. Comme dans la pile, le tas contient les données utilisateur et des informations de gestions. Nous allons voir ce qui se passe quand un débordement à lieu dans cette zone.

Doug Lee malloc (linux)

Note: la version utilisée est celle de la glibc version 2.2.4-13. Les dernieres versions implementent des verifications qui interrompent le programme si des anomalies sont detectees. Malheuresement ce qui va etre abortee est concidere comme une anomalie.

Fonctionnement

Ce memory allocator, aussi appelé dlmalloc est celui utilisé par linux. Il gére la mémoire de mannière linéaire. Chaque zone allouée (chunk) contient une entête avec les informations sur la taille de la chunk et celle d'avant. Cela permet une gestion efficasse de la mémoire : toutes les zones gérées par malloc peuvent être parcourru a partir d'une chunk connue, et deux zones libres collées peuvent être fuzionées.

Exemple 6.1. Structure de l'entète d'une chunk

struct malloc_chunk
{
  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;   /* double links -- used only if free. */
  struct malloc_chunk* bk;
};
      

D'autre part, dlmalloc se sert du bit de poids faible de la taille de la chunk pour savoir si celle d'avant est utilisée (PREV_INUSE).

Exemple 6.2. Chunk alloué

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk, if allocated            | |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
            |             User data starts here...                          .
            .                                                               .
            .             (malloc_usable_space() bytes)                     .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of chunk                                     |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      

Les chunk libres sont stockées dans une double liste chaîné :

Exemple 6.3. Chunk libre

    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Size of previous chunk                            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Forward pointer to next chunk in list             |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Back pointer to previous chunk in list            |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            |             Unused space (may be 0 bytes long)                .
            .                                                               .
            .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `foot:' |             Size of chunk, in bytes                           |
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        

Bon, donc voici a quoi ressemble le tas :

Voyons voir ce qui se passe quand un buffer mallocé déborde :

Exemple 6.4. Disposition du tas


        

Le premiere buffer a bien débordé dans le second, mais il ne s'est rien passé car la structure du buffer2 n'a pas été utilisé. A la fin du programme l'ensemble de la zone gérée par malloc a été désalloué sans ce soucier de la répartition interne de la zone.

Poul-Henning Kamp's malloc (*BSD)