web-dev-qa-db-fra.com

différence entre gcc -D_FORTIFY_SOURCE = 1 et -D_FORTIFY_SOURCE = 2

Quelqu'un peut-il souligner la différence entre gcc -D_FORTIFY_SOURCE=1 et -D_FORTIFY_SOURCE=2? J'imagine =2 est plus sécurisé? Je n'ai pas pu trouver une liste qui énumère les différences point par point.

J'ai également lu que -D_FORTIFY_SOURCE=2 doit être utilisé avec -O2, sinon toutes les fonctionnalités ne seraient pas disponibles. Ici aussi, je n'ai pas trouvé de liste qui spécifierait les régressions en détail. Je serais particulièrement intéressé à compiler avec -Os car la cible est un appareil avec moins de mémoire flash.

Toutes les indications sur l'endroit où cela est documenté sont les bienvenues!

58
Frank Meerkötter

À partir de la page de manuel des macros de test de fonctionnalités ( man 7 feature_test_macros )

_FORTIFY_SOURCE (depuis la glibc 2.3.4)

La définition de cette macro entraîne des vérifications légères pour détecter certaines erreurs de dépassement de tampon lors de l'utilisation de diverses fonctions de manipulation de chaînes et de mémoire (par exemple, memcpy, memset, stpcpy, strcpy, strncpy, strcat, strncat, sprintf, snprintf, vsprintf, vsnprintf, gets, et leurs variantes à caractères larges). Pour certaines fonctions, la cohérence des arguments est vérifiée; par exemple, on vérifie que open a été fourni avec un argument mode lorsque les indicateurs spécifiés incluent O_CREAT. Tous les problèmes ne sont pas détectés, seulement certains cas courants.

Si _FORTIFY_SOURCE est défini sur 1, avec le niveau d'optimisation du compilateur 1 (gcc -O1) et au-dessus, des vérifications qui ne devraient pas changer le comportement des programmes conformes sont effectuées.

Avec _FORTIFY_SOURCE défini sur 2, une vérification supplémentaire est ajoutée, mais certains programmes conformes peuvent échouer.

Certaines vérifications peuvent être effectuées au moment de la compilation (via la logique des macros implémentée dans les fichiers d'en-tête) et entraîner des avertissements du compilateur; d'autres vérifications ont lieu au moment de l'exécution et entraînent une erreur d'exécution si la vérification échoue.

L'utilisation de cette macro nécessite la prise en charge du compilateur, disponible avec gcc depuis la version 4.0.

De plus, l'article Améliorer la sécurité des applications avec FORTIFY_SOURCE (mars 2014) dit:

  • gcc -D_FORTIFY_SOURCE=1 ajoute des vérifications au moment de la compilation uniquement (certains en-têtes sont nécessaires comme #include <string.h>)
  • gcc -D_FORTIFY_SOURCE=2 ajoute également des vérifications au moment de l'exécution (un débordement de tampon détecté termine le programme)

Essentiellement, _FORTIFY_SOURCE le niveau 2 est plus sûr, mais est une stratégie de compilation légèrement plus risquée; si vous l'utilisez, assurez-vous d'avoir des tests de régression très forts pour votre code compilé pour prouver que le compilateur n'a introduit aucun comportement inattendu.

46
Colonel Panic

http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html va plus en détail que feature_test_macros(7) .

Voici l'extrait pertinent, légèrement édité/reformaté pour plus de clarté:

La différence entre -D_FORTIFY_SOURCE=1 Et -D_FORTIFY_SOURCE=2 Est par exemple pour

  struct S {
      struct T {
        char buf[5];
        int x;
      } t;
      char buf[20];
  } var;

Avec -D_FORTIFY_SOURCE=1,

  strcpy (&var.t.buf[1], "abcdefg");

n'est pas considéré comme un débordement (l'objet est entier VAR), alors qu'avec -D_FORTIFY_SOURCE=2

  strcpy (&var.t.buf[1], "abcdefg");

sera considéré comme un débordement de tampon.

Une autre différence est qu'avec -D_FORTIFY_SOURCE=2, %n Dans les chaînes de format des fonctions de la famille *printf Les plus courantes n'est autorisé que s'il est stocké en mémoire morte (généralement des littéraux de chaîne, _("%s string %n") de gettext est très bien aussi), mais généralement lorsqu'un attaquant tente d'exploiter une vulnérabilité de chaîne de format, %n sera un endroit où l'attaquant pourrait l'écrire.

13
jjlin