Paldium
Well-Known Member
Bei meinen ersten Versuchen, C anhand des Quelltextes von OpenBSD besser verstehen zu können, bin ich auf ein paar Dinge gestoßen, die ich mir nicht erklären kann ... Ich hoffe, dass ihr mir weiterhelfen könnt.
Zum einen ist mir der unterschiedliche Einsatz von "exit" und "return" am Ende der main()-Funktion aufgefallen. Ich hatte mal gelesen, dass beides zum gleichen Ergebnis führen soll, habe aber dennoch mal auf meinem OpenBSD-3.7-System ausprobiert, ob das stimmt. Ich habe folgende einfache Programme genutzt:
und
So weit, so gut, die Programme machen natürlich genau das, was sie machen sollen. Da ich aber wissen wollte, wo genau der Unterschied im Ablauf ist, habe ich mir mit "gcc -S return.c" und "gcc -S exit.c" den Assemblercode ausgeben lassen. Dabei ist mir dann aufgefallen, dass propolice nur in return.s zum Greifen kommt. Wenn ich das Programm mit exit beende, dann wird __guard zwar initialisiert, aber niemals überprüft.
Ein Programm, bei dem ich jetzt nicht verstehe, warum mit "exit" beendet wird, ist /bin/cat. Selbst wenn es sinnlos erscheint, propolice zu aktivieren... es wird ja gemacht, schließlich wird zu Beginn __guard initialisiert. Wenn ich mir mit "gcc -S cat.c" den Assemblercode ansehe, wird aber kein __stack_smash_handler aufgerufen, wodurch der ganze Schutz hinfällig ist.
Meine Frage daher: Gibt es einen guten Grund dafür, am Ende von bin/cat "exit(retval)" statt "return retval" aufzurufen? "return retval" hätte ja eine Überprüfung von __guard zur Folge ...
Zum einen ist mir der unterschiedliche Einsatz von "exit" und "return" am Ende der main()-Funktion aufgefallen. Ich hatte mal gelesen, dass beides zum gleichen Ergebnis führen soll, habe aber dennoch mal auf meinem OpenBSD-3.7-System ausprobiert, ob das stimmt. Ich habe folgende einfache Programme genutzt:
Code:
int
main(int argc, char *argv[])
{
return 0;
}
Code:
#include <stdlib.h>
int
main(int argc, char *argv[])
{
exit(0);
}
So weit, so gut, die Programme machen natürlich genau das, was sie machen sollen. Da ich aber wissen wollte, wo genau der Unterschied im Ablauf ist, habe ich mir mit "gcc -S return.c" und "gcc -S exit.c" den Assemblercode ausgeben lassen. Dabei ist mir dann aufgefallen, dass propolice nur in return.s zum Greifen kommt. Wenn ich das Programm mit exit beende, dann wird __guard zwar initialisiert, aber niemals überprüft.
Ein Programm, bei dem ich jetzt nicht verstehe, warum mit "exit" beendet wird, ist /bin/cat. Selbst wenn es sinnlos erscheint, propolice zu aktivieren... es wird ja gemacht, schließlich wird zu Beginn __guard initialisiert. Wenn ich mir mit "gcc -S cat.c" den Assemblercode ansehe, wird aber kein __stack_smash_handler aufgerufen, wodurch der ganze Schutz hinfällig ist.
Meine Frage daher: Gibt es einen guten Grund dafür, am Ende von bin/cat "exit(retval)" statt "return retval" aufzurufen? "return retval" hätte ja eine Überprüfung von __guard zur Folge ...