
Wir haben zwei RHEL 6-Systeme, auf denen identische Versionen des Kernels und von glibc (glibc–2.12–1.90.el6_3.6) laufen. Laut POSIX-Standard und den Linux-Manpages gilt: Wenn der Kernel feststellt, dass eine ausführbare Datei nicht in einem ausführbaren Format wie ELF vorliegt und keine Shebang( #!
)-Zeile hat, versuchen die Funktionen execl
, execlp
, execle
, execv
, execvp
, und execvpe
(aber nicht execve
), diese Datei mit einer POSIX-Shell auszuführen, was unter Linux der Fall ist /bin/sh
.
Auf einem der Systeme schlägt jedoch die Ausführung eines Shell-Skripts fehl, dessen erste Zeile :
die Funktion verwendet execvp
, während auf dem anderen Rechner das Skript wie erwartet mit ausgeführt wird /bin/sh
. Konkret verwenden wir diese Testprogramme; /tmp/test_script
ausführbar gemacht wird:
xc:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> externer Zeichen **Umgebung; int haupt () { char *argv[] = { "/tmp/test_script", NULL }; char *Programmname = argv[0]; wenn (execvp(Programmname, argv) == -1) { perror("execvp"); Rückgabe -1; } }
/tmp/test_script:
: echo "Testskript aufgerufen" Ausfahrt 0
Wir haben im Quell-RPM nach der installierten Version von glibc gesucht und es implementiert definitiv das gewünschte Verhalten (execvp ist ein trivialer Wrapper um execvpe):
posix/execvpe.c:
wenn (strchr(Datei, '/') != NULL) { /* Nicht suchen, wenn ein Schrägstrich enthalten ist. */ __execve(Datei, argv, envp); wenn (errno == ENOEXEC) { /* Zähle die Argumente. */ argc = 0; während (argv[argc++]) ; size_t Länge = (argc + 1) * Größe von (Zeichen *); Zeichen **Skriptargv; void *ptr = NULL; wenn (__libc_use_alloca(Länge)) script_argv = alloca(Länge); anders script_argv = ptr = malloc(Länge); wenn (script_argv != NULL) { scripts_argv(Datei, argv, argc, script_argv); __execve(Skriptargv[0], Skriptargv, envp); frei(ptr); } } } anders ︙
Dies scripts_argv
ist eine einfache Funktion, die /bin/sh
der Argumentliste vorangestellt wird und __execve
mit der Funktion identisch ist execve
, die dem Benutzerbereich über glibc zur Verfügung gestellt wird.
Ist dieses Problem bei anderen unter Linux aufgetreten? Auf allen anderen Systemen, auf denen ich es ausprobiert habe, ist das Verhalten korrekt.
Antwort1
Okay, ich habe herausgefunden, was das Problem verursacht hat. Nachdem ich die x.c
ausführbare Datei kompiliert hatte, habe ich ldd
sie ausgeführt und festgestellt, dass eine Bibliothek liboit.so
dynamisch mit der ausführbaren Datei verknüpft war. Diese Bibliothek wurde vomObserveIT Unix Auditor, das alle Aktivitäten angemeldeter Benutzer abfängt, einschließlich Systemaufrufen. Ich würde jedoch denken, dass das bloße Abfangen von Systemaufrufen nicht zu dem beobachteten Verhalten führen würde, da die erneute Ausführung /bin/sh
innerhalb von glibc erfolgt. Vielleicht emuliert ObserveIT auch POSIX-Funktionen, in dieser Situation offenbar nicht konform.