"stack smashing detected" bei Message Queues auf Linux (Ubuntu)
-
Hallo, vielleicht könnt ihr mir helfen, ich weiß nicht mehr weiter.
Ich versuch ne simple Message Queue zu implementieren, aber wenn die Queue beendet werden soll (bzw. kurz davor) gibt es den Fehler (aus den ich nicht schlau werde).Hier erstmal die Quellcodes:
input.c
#include <stdio.h> #include <sys/msg.h> #include <stdlib.h> #include <string.h> struct mymsg{ long mtype; int status; char mtext[100]; }; main(){ int msqid, msqflag, flag, rc; key_t msqkey; size_t len; struct mymsg nachricht; msqkey = 101; msqflag = IPC_CREAT|0644; msqid = msgget(msqkey, msqflag); nachricht.mtype = getpid(); nachricht.status = 2; len = sizeof(nachricht); flag = 0; rc = msgsnd(msqid, &nachricht, len, flag); nachricht.status = 1; while( fgets(nachricht.mtext, sizeof(nachricht.mtext), stdin) != NULL ){ rc = msgsnd(msqid, &nachricht, len, flag); } nachricht.status = 0; rc = msgsnd(msqid, &nachricht, len, flag); }
output.c
#include <stdio.h> #include <sys/msg.h> struct mymsg{ long mtype; int status; char mtext[100]; }; main(){ struct mymsg nachricht; key_t msqkey; size_t len; int l, flag, msqid, msqflag, sendcounter = 1, end = 0, rc; long msgtyp; msqkey = 101; msqflag = IPC_CREAT|0644; msqid = msgget(msqkey, msqflag); nachricht.mtype = 1; len = sizeof(nachricht); msgtyp = 0; flag = 0; while( (l = msgrcv(msqid, &nachricht, len, msgtyp, flag)) > 0 ){ printf("Sendcounter: %d\n", sendcounter); if( nachricht.status == 0 ){ printf("Input %ld wird beendet\n", nachricht.mtype); sendcounter--; printf("Sencounter--\n"); if( sendcounter <= 1 ){ printf("Alle Inputs wurden beendet, Queue wird geschlossen ..."); break; } } else if( nachricht.status == 2 ) { sendcounter++; } else { printf("%ld: %s", nachricht.mtype, nachricht.mtext); } nachricht.mtype = 1; } rc = msgctl(msqid, IPC_RMID, 0); }
Fehler tritt genau an der Stelle auf, wo "sendcounter" dekrementiert wird (print wird noch ausgeführt). Ich poste einfach einen Ausschnitt (Eingabe auf anderer Konsole). Übrigens bin ich mir sicher, dass es an meinem Betriebssystem liegt (Ubuntu), da es auf einen SUN-BS einwandfrei läuft. Kennt jemand Probleme bezüglich Ubuntu?
Sendcounter: 1
Sendcounter: 2
15431: hallo welt
Sendcounter: 2
Input 15431 wird beendet
Sencounter--
*** stack smashing detected ***: ./output terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7eed6d8]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7eed690]
./output[0x804868b]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe5)[0xb7e09685]
./output[0x8048471]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:06 1100299 /home/bloodredangel/Desktop/C-Binaries/output
08049000-0804a000 r--p 00000000 08:06 1100299 /home/bloodredangel/Desktop/C-Binaries/output
0804a000-0804b000 rw-p 00001000 08:06 1100299 /home/bloodredangel/Desktop/C-Binaries/output
09c99000-09cba000 rw-p 09c99000 00:00 0 [heap]
b7dd5000-b7de2000 r-xp 00000000 08:06 1040405 /lib/libgcc_s.so.1
b7de2000-b7de3000 r--p 0000c000 08:06 1040405 /lib/libgcc_s.so.1
b7de3000-b7de4000 rw-p 0000d000 08:06 1040405 /lib/libgcc_s.so.1
b7df2000-b7df3000 rw-p b7df2000 00:00 0
b7df3000-b7f4b000 r-xp 00000000 08:06 1057445 /lib/tls/i686/cmov/libc-2.8.90.so
b7f4b000-b7f4d000 r--p 00158000 08:06 1057445 /lib/tls/i686/cmov/libc-2.8.90.so
b7f4d000-b7f4e000 rw-p 0015a000 08:06 1057445 /lib/tls/i686/cmov/libc-2.8.90.so
b7f4e000-b7f51000 rw-p b7f4e000 00:00 0
b7f5e000-b7f61000 rw-p b7f5e000 00:00 0
b7f61000-b7f7b000 r-xp 00000000 08:06 1042587 /lib/ld-2.8.90.so
b7f7b000-b7f7c000 r-xp b7f7b000 00:00 0 [vdso]
b7f7c000-b7f7d000 r--p 0001a000 08:06 1042587 /lib/ld-2.8.90.so
b7f7d000-b7f7e000 rw-p 0001b000 08:06 1042587 /lib/ld-2.8.90.so
bff68000-bff7d000 rw-p bffeb000 00:00 0 [stack]
Alle Inputs wurden beendet, Queue wird geschlossen ...Aborted
-
Editieren geht ja als Gast nicht.
Naja auf jeden Fall gehts jetzt, aber wieso ist mir unklar. Hab noch Fileausgabe hinzugefügt (und printf's entfernt), woraufhin alles ging. Weiß jemand wieso? Fänd ich sehr interessant.
Hier mal der aktuelle Code:input.c
#include <stdio.h> #include <sys/msg.h> #include <stdlib.h> #include <string.h> struct mymsg{ long mtype; int status; char mtext[100]; }; main(){ int msqid, msqflag, flag, rc; key_t msqkey; size_t len; struct mymsg nachricht; msqkey = 101; msqflag = IPC_CREAT|0644; msqid = msgget(msqkey, msqflag); if( rc < 0){ perror("msgget"); exit(1); } nachricht.mtype = getpid(); nachricht.status = 2; len = sizeof(nachricht); flag = 0; rc = msgsnd(msqid, &nachricht, len, flag); if( msqid < 0){ perror("msgsnd"); exit(1); } nachricht.status = 1; while( fgets(nachricht.mtext, sizeof(nachricht.mtext), stdin) != NULL ){ rc = msgsnd(msqid, &nachricht, len, flag); if( rc < 0){ perror("msgsnd"); exit(1); } } nachricht.status = 0; rc = msgsnd(msqid, &nachricht, len, flag); if( rc < 0){ perror("msgsnd"); exit(1); } }
#include <stdio.h> #include <sys/msg.h> #include <stdlib.h> #include <string.h> struct mymsg{ long mtype; int status; char mtext[100]; }; main(){ struct mymsg nachricht; key_t msqkey; size_t len; int l, flag, msqid, msqflag, sendcounter = 1, end = 0, rc; long msgtyp; FILE *file; char filename[5], text[100]; msqkey = 101; msqflag = IPC_CREAT|0644; msqid = msgget(msqkey, msqflag); if( msqid < 0){ perror("msqid"); exit(1); } nachricht.mtype = 1; len = sizeof(nachricht); msgtyp = 0; flag = 0; while( (l = msgrcv(msqid, &nachricht, len, msgtyp, flag)) > 0 ){ if( nachricht.status == 0 ){ sendcounter--; if( sendcounter <= 1 ){ break; } } else if( nachricht.status == 2 ) { sendcounter++; } else { printf("%ld: %s", nachricht.mtype, nachricht.mtext); sprintf(filename, "%ld", nachricht.mtype); sprintf(text, "%ld: %s", nachricht.mtype, nachricht.mtext); file = fopen(filename, "ab"); if( file == NULL ){ perror("fopen"); exit(1); } rc = fwrite(text, strlen(text), 1, file); if( rc != 1 ){ perror("fwrite"); exit(1); } if( fclose(file) == EOF ){ perror("fclose"); exit(1); } } nachricht.mtype = 1; } if( l != sizeof(nachricht)){ perror("msgrcv"); exit(1); } rc = msgctl(msqid, IPC_RMID, 0); if(rc < 0){ perror("msgctl"); exit(1); } }
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
stack smashing protection ist ein sicherheitsfeatures, das verhindern soll, dass jemand einen buffer overflow am stack zur ausführung von eingeschleustem code nützt. es soll verhindert werden, dass die am stack gespeicherte rücksprung adresse überschrieben wird.
sehr wahrscheinlich ist, dass einer deiner buffer zu kurz ist für die daten, die du reinschreibst. vielleicht filename[5].
-
OK, danke, wieder was gelernt.
Wo siehst du denn ein "filename[5]"?
Könnte mir in dem Zusammenhang höchstens vorstellen, dass "long mtype" die pid (die ja meines Wissens int ist) sich beharken.
-
Bloodredangel schrieb:
Wo siehst du denn ein "filename[5]"?
char filename[5], text[100];
schau einfach mal ob dein inhalt größer ist als 5 bzw 100. Und natürlich bei den anderen Variablen auch.
blan
-
Achso, naja das kommt ja erst im bereits funktionierendem Quelltext vor (der aus dem 1. Post funktioniert nicht). Hab dadurch angespornt aber noch ein wenig rumexperimentiert und genau gefunden, wann es gelöst wurde:
Nimmt man den oberen Quellcode (aus dem 1. Post) und fügt in der "output.c" bei der Variablendeklaration noch "FILE *file; char filename[5], text[100];" hinzu, dann funktioniert es - obgleich diese Variablen nie aufgerufen / gebraucht werden.
Jetzt bin ich noch mehr verwirrt. ^^ "Vergisst" C die Bibliothek zu laden, wenn bei der Variablendeklaration keine Variablen entsprechenden Typs vorkommt? Kann ich mir nicht vorstellen ... merkwürdige Sache das.
-
ich bin verwirrt. du hast zwei source dateien gepostet. welche von beiden funktioniert nicht? oder funktionieren beide?
-
Bloodredangel schrieb:
Übrigens bin ich mir sicher, dass es an meinem Betriebssystem liegt (Ubuntu), da es auf einen SUN-BS einwandfrei läuft.
Das hat überhaupt nichts zu sagen. Auch fehlerhafter Code kann unter bestimmten Umständen "einwandfrei" laufen, weil du einfach Glück hast.
Bloodredangel schrieb:
Nimmt man den oberen Quellcode (aus dem 1. Post) und fügt in der "output.c" bei der Variablendeklaration noch "FILE *file; char filename[5], text[100];" hinzu, dann funktioniert es - obgleich diese Variablen nie aufgerufen / gebraucht werden.
Jetzt bin ich noch mehr verwirrt. ^^ "Vergisst" C die Bibliothek zu laden, wenn bei der Variablendeklaration keine Variablen entsprechenden Typs vorkommt? Kann ich mir nicht vorstellen ... merkwürdige Sache das.
C vergisst hier bestimmt nichts. Ich denke, der Hinweis vom Besserwisser auf zu kleine Puffer war schon genau richtig. Indem du die neue Variablen einführst schaffst du zusätzlichen Platz hinter deinen anderen Daten. D.h., bei einem Pufferüberlauf wird dann mit etwas Glück nichts wichtiges mehr überschrieben, sondern eben nur ein paar ungenutzte Variablen.
Lies nochmal die Manpage zu msgsnd und msgrcv. Sollte die übergebene Länge des Puffers nicht exklusive dem mtype sein? Das würde genau dein Problem erklären...
-
Wow, ich bin richtig überwältigt! oO Hätte nicht gedacht, dass ich nochmal rausbekomme wieso das passierte, aber du liegst goldrichtig. .
Wir hatten gelernt als Länge "nachricht.mtext" zu verwenden, da ich aber den Status in den struct genommen hab, muss die Länge ja auch dazu. Statt selbst zu denken hab ich da beim Nachbarn geschaut (der hinterher dieselben Probs hatte) und er löste es mit der Länge des structs. Man man man, so versteckt können Fehler sein. ^^ Und gut zu wissen, dass C "dahinterliegende" Speicherbereiche einfach mitnutzt. Das erklärt einiges *g*Fettes DANKE! Damit ist die Sache geklärt.
(Also mit "len = sizeof(nachricht.mtext) + sizeof(nachricht.status)" funktionierts.)