L'indicateur GCC -fstack-protector permet d'utiliser des canaris de pile pour la protection contre les débordements de pile. L'utilisation de ce drapeau par défaut a été plus importante ces dernières années.
Si un paquet est compilé avec -fstack-protector, et que nous débordons un tampon dans le programme, nous aurons probablement une erreur telle que:
*** buffer overflow detected ***: /xxx/xxx terminated
Cependant, "qui" est responsable de ces messages d'erreur? Où ces messages sont-ils enregistrés? Le démon syslog récupère-t-il ces messages?
libssp
affichera son message par la sortie stderr utilisée par nginx. Ensuite,libssp
essayez de quitter le processus (ou le processus enfant pour nginx). S'il "n'a pas besoin" de planter l'application, alors les enregistreurs de sortie anormaux ne le prendront pas. Est-ce une interprétation correcte?__builtin_trap()
abord, puis , si cela ne fonctionne pas, en essayant de provoquer une violation du segment, et seulement si cela échoue, la sortie avec le statut 127.abort()
).Les distributions Linux modernes comme CentOS / Fedora mettent en place un démon de gestion des plantages (par exemple
systemd-coredump
ouabortd
), par défaut.Ainsi, lorsque votre programme se termine de façon anormale (erreur de segmentation, exception non interceptée, abandon, instruction illégale, etc.), cet événement est enregistré et enregistré par ce démon. Ainsi, vous trouverez des messages dans le journal système et éventuellement une référence à un répertoire avec quelques détails supplémentaires (par exemple fichier core, logs, etc.).
Exemple
Compiler:
Exécuter:
L'état de sortie est 134, soit 128 + 6, c'est-à-dire 128 plus le numéro de signal d'abandon.
Le journal système:
Cela signifie que vous obtenez la journalisation à partir du
auditd
démon d'audit et dusystemd-coredump
gestionnaire de plantage.Pour vérifier si un démon de gestion des plantages est configuré, vous pouvez vérifier
/proc
, par exemple:(tout testé sur Fedora 26, x86-64)
la source
abort()
qui produit un signal d'abandon, c'est-à-dire qu'il n'y a pas de défaut de segmentation en cours. C'est juste que les gestionnaires de signaux par défaut pour les défauts d'abandon / de segmentation, etc. produisent la même action: écrire le cœur et quitter le processus avec un état de sortie zéro égal qui code également le numéro du signal. L'écriture du noyau est effectuée par le noyau et son comportement est configurable via/proc/.../core_pattern
. Dans l'exemple ci-dessus, un assistant d'espace utilisateur est configuré et donc appelé. Le noyau déclenche également l'audit.abort()
, le code SSP utilise__builtin_trap()
(mais l'effet est le même).abort()
s'appelle.__builtin_trap()
pour éviter d'avoir une dépendance expliciteabort()
). D'autres distributions ont des traces de pile différentes.