Re: exit(0) oder nicht exit(0)

From: Oliver Fromme <olli(at)lurza.secnetix.de>
Date: Wed, 16 Aug 2006 14:29:40 +0200 (CEST)

Daniel Graupner wrote:
> Oliver Fromme wrote:
> > Daniel Graupner wrote:
> > > Dominik Brettnacher wrote:
> > Ja, aber auf unterschiedliche Weise, z.B. sieht der Stack
> > in beiden Fällen ganz anders aus. Wenn Du also irgendwo
> > einen Bug hast (Pointer-bug, Buffer-overflow o.ä.), der
> > einen Teil des Stacks überschreibt (z.B. die Rücksprung-
> > adresse von main()), würde es das Phänomen exakt erklären.
>
> Hmm, ich dachte das "return 0" resultiert letztlich auch nur in nem
> "exit(0)".

Das ist richtig. Aber der Weg dorthin ist unterschiedlich.

> Warum sieht der stack anders aus, die Sachen im Stack müssen doch so
> oder so "geseichert" werden.

Nein, im Normalfall nicht. Das ist eines der Probleme von
Sprachen wie C oder C++.

Die main()-Funktion eines Programmes wird von crt1 aufgeru-
fen. Zu diesem Zeitpunkt befinden sich auf dem Stack fol-
gende Daten:

1. Rücksprungadresse von crt1
2. Argumente von main(): argc, argv, envp

Mal angenommen, Dein Programm hat irgendwo einen subtilen
Pointer-Fehler oder Buffer-overflow, der die Rücksprung-
adresse auf dem Stack überschreibt. Was passiert nun bei
einem exit() und was bei einem return?

Beim return wird die Rücksprungadresse vom Stack geholt
und dorthin gesprungen. Im Normalfall landen wir dabei
also wieder in crt1, was dann seinerseits exit() aufruft.
Ist aber die Rücksprungadresse zerstört, landet er nicht
mehr in crt1, sondern irgendwo im Speichernirwana, was
höchstwahrscheinlich zu SIGSEGV führt.

Wenn der Prozess dagegen exit() aufruft, wird gar nichts
vom Stack geholt. Im Gegenteil: Die exit()-Funktion der
libc wird direkt aufgerufen, wobei die Rücksprungadresse
von main() auf dem Stack landet. Die libc wiederum führt
ein paar Aufräumarbeiten durch und ruft dann den Syscall
_exit() auf, der den Prozess mitsamt aller VM-Pages (inkl.
Stack) auflöst. Es wird zu keinem Zeitpunkt irgendwas
vom Stack geholt, d.h. es ist wurscht, ob da irgendwelcher
Müll liegt oder nicht.

Falls Du selbst nachlesen möchtest:

crt1: src/lib/csu/i386-elf/crt1.c
       Dort speziell die letzte Zeile der Funktion _start:
       exit( main(argc, argv, env) );

exit(): src/lib/libc/stdlib/exit.c

_exit(): src/sys/kern/kern_exit.c
          Dort die Funktionen sys_exit() und exit1().

Gruß
   Olli

-- 
Oliver Fromme,  secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing
Dienstleistungen mit Schwerpunkt FreeBSD: http://www.secnetix.de/bsd
Any opinions expressed in this message may be personal to the author
and may not necessarily reflect the opinions of secnetix in any way.
"I made up the term 'object-oriented', and I can tell you
I didn't have C++ in mind."
        -- Alan Kay, OOPSLA '97
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Wed 16 Aug 2006 - 14:31:43 CEST

search this site