Inhalt Übungen zu Systemnahe Programmierung in C (SPiC) Linux Fehlerbehandlung Sebastian Maier (Lehrstuhl Informatik 4) Aufgabe: concat Übung 7 Anhang Hands-on: Buffer Overflow Sommersemester 2017 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 2 – 23 Inhalt Terminal - historisches (etwas vereinfacht) Linux Terminal Arbeiten unter Linux Arbeitsumgebung Manual Pages Als die Computer noch größer waren: Fehlerbehandlung Als das Internet noch langsam war: Seriell 1 Netzwerk DFÜ Aufgabe: concat Anhang 1 Übungen zu SPiC (SS 2017) Server Farben, Positionssprünge, etc. werden durch spezielle Zeichenfolgen ermöglicht Hands-on: Buffer Overflow Lehrstuhl Informatik 4 Computer 2 – 23 Televideo 925 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 3 – 23 Terminal - Funktionsweise Terminal - Standardkanäle umleiten Drei Standardkanäle für Ein- und Ausgaben stdout Ausgabe in eine Datei schreiben 1 stdin stdout stderr stdout wird häufig direkt mit stdin anderer Programme verbunden Prozess 1 ⇒ Fehlermeldungen werden weiterhin am Terminal ausgegeben Übersicht > Standardausgabe stdout in Datei schreiben stdout Ausgaben >> Standardausgabe stdout an existierende Dateien anhängen stderr Fehlermeldungen 2> Fehlerausgabe stderr in Datei schreiben Standardverhalten < Standardeingabe stdin aus Datei einlesen Eingaben kommen von der Tastatur Ausgaben & Fehlermeldungen erscheinen auf dem Bildschirm 1 Übungen zu SPiC (SS 2017) | Ausgabe eines Befehls direkt an einen anderen Befehl weiterleiten 4 – 23 Übungen zu SPiC (SS 2017) Shell - Programme beenden Wechseln in ein Verzeichnis mit cd (change directory) Per Signal: CTRL-C (Kann vom Programm ignoriert werden) cd /proj/i4spic/<login>/aufgabeX Von einer anderen Konsole aus: killall cworld beendet alle Programme mit dem Namen “cworld” Von der selben Konsole aus: 5 – 23 CTRL-Z hält den aktuell laufenden Prozess an killall cworld beendet alle Programme mit dem namen cworld ls ⇒ Programme anderer Benutzer dürfen nicht beendet werden Datei oder Ordner kopieren mit cp (copy) 1 Lehrstuhl Informatik 4 Shell - Wichtige Kommandos Verzeichnisinhalt auflisten mit ls (list directory) 1 cat ordner.txt | grep tmp | wc -l Vorteil von stderr stdin Eingaben Lehrstuhl Informatik 4 find . > ordner.txt fg setzt den angehaltenen Prozess fort cp /proj/i4spic/pub/aufgabeX/vorgabe.h /proj/i4spic/<login>/⤦ Ç aufgabeX Wenn nichts mehr hilft: killall -9 cworld Datei oder Ordner löschen mit rm (remove) 1 2 3 rm test1.c # Ordner mit allen Dateien löschen rm -r aufgabe1 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 6 – 23 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 7 – 23 Arbeitsumgebung Übersetzen & Ausführen Unter Linux: Programm mit dem GCC übersetzen Kate, gedit, Eclipse cdt, Vim, Emacs, .... Zugriff aus der Windows-Umgebung über SSH (nur Terminalfenster): Editor unter Linux via SSH: 1 2 gcc -pedantic -Wall -Werror -O2 -std=c99 -D_XOPEN_SOURCE=500 -o ⤦ Ç cworld cworld.c Aufrufoptionen des Compilers, um Fehler schnell zu erkennen mcedit, nano, emacs, vim -pedantic liefert Warnungen in allen Fällen, die nicht 100% dem verwendeten C-Standard entsprechen -Wall warnt vor möglichen Fehlern (z.B.: if(x = 7)) -Werror wandelt Warnungen in Fehler um Editor unter Windows: AVR-Studio ohne Projekt Notepad++ -O2 führt zu Optimierungen des Programms -std=c99 setzt verwendeten Standard auf C99 -D_XOPEN_SOURCE=500 fügt unter anderem die POSIX Erweiterungen hinzu, die in C99 nicht enthalten sind -o cworld legt Namen der Ausgabedatei fest (Standard: a.out) Dateizugriff über das Netzwerk Übersetzen und Test unter Linux (z.B. via Putty) Ausführen des Programms mit ./cworld 2 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 8 – 23 Manual Pages Inhalt Das Linux-Hilfesystem aufgeteilt nach verschiedenen Sections Linux 1 2 3 5 7 Kommandos Systemaufrufe Bibliotheksfunktionen Dateiformate (spezielle Datenstrukturen, etc.) verschiedenes (z.B. Terminaltreiber, IP, . . . ) # man [section] Begriff man 3 printf Aufgabe: concat Hands-on: Buffer Overflow Suche von man-Pages zu einem Stichwort: man -k Stichwort Übungen zu SPiC (SS 2017) 9 – 23 Anhang Suche nach Sections: man -f Begriff Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) Fehlerbehandlung Bibliotheksfunktionen Kommandozeilenparameter man-Pages werden normalerweise mit der Section zitiert: printf(3) 1 2 Abgaben werden von uns mit diesen Optionen getestet Lehrstuhl Informatik 4 10 – 23 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 10 – 23 Fehlerursachen Fehlerbehandlung Fehler können aus unterschiedlichsten Gründen im Programm auftreten Gute Software erkennt Fehler, führt eine angebrachte Behandlung durch und gibt eine aussagekräftige Fehlermeldung aus Systemressourcen erschöpft Kann das Programm trotz des Fehlers sinnvoll weiterlaufen? Beispiel 1: Ermittlung des Hostnamens zu einer IP-Adresse für Log ⇒ malloc(3) schlägt fehl Fehlerhafte Benutzereingaben (z.B. nicht existierende Datei) ⇒ Fehlerbehandlung: IP-Adresse im Log eintragen, Programm läuft weiter ⇒ fopen(3) schlägt fehl Beispiel 2: Öffnen einer zu kopierenden Datei schlägt fehl Transiente Fehler (z.B. nicht erreichbarer Server) ⇒ Fehlerbehandlung: Kopieren nicht möglich, Programm beenden ⇒ Oder den Kopiervorgang bei der nächsten Datei fortsetzen ⇒ Entscheidung liegt beim Softwareentwickler ⇒ connect(2) schlägt fehl Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) Lehrstuhl Informatik 4 11 – 23 Fehler in Bibliotheksfunktionen Erweiterte Fehlerbehandlung Fehler treten häufig in Funktionen der C-Bibliothek auf Signalisierung von Fehlern normalerweise durch Rückgabewert erkennbar i.d.R. am Rückgabewert (Manpage!) Fehlerursache wird meist über die globale Variable errno übermittelt Bekanntmachung im Programm durch Einbinden von errno.h Bibliotheksfunktionen setzen errno nur im Fehlerfall Fehlercodes sind immer > 0 Fehlercode für jeden möglichen Fehler (siehe errno(3)) char *mem = malloc(...); /* malloc gibt im Fehlerfall */ if(NULL == mem) { /* NULL zurück */ fprintf(stderr, "%s:%d: malloc failed with reason: %s\n", __FILE__, __LINE__-3, strerror(errno)); perror("malloc"); /* Alternative zu strerror + fprintf */ exit(EXIT_FAILURE); /* Programm mit Fehlercode beenden */ } Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 12 – 23 Nicht bei allen Funktionen möglich, z.B. getchar(3) 1 2 3 int c; while ((c=getchar()) != EOF) { ... } /* EOF oder Fehler? */ Rückgabewert EOF sowohl im Fehlerfall als auch bei End-of-File Fehlercodes können mit perror(3) und strerror(3) ausgegeben bzw. in lesbare Strings umgewandelt werden 1 2 3 4 5 6 7 Übungen zu SPiC (SS 2017) 13 – 23 Erkennung im Fall von I/O-Streams mit ferror(3) und feof(3) 1 2 3 4 5 6 7 int c; while ((c=getchar()) != EOF) { ... } /* EOF oder Fehler? */ if(ferror(stdin)) { /* Fehler */ ... } Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 14 – 23 1 2 3 4 5 6 Kommandozeilenparameter Inhalt ... int main(int argc, char *argv[]){ strcmp(argv[argc - 1], ... ) ... return EXIT_SUCCESS; } Linux Fehlerbehandlung Aufgabe: concat Aufgabenstellung Dynamische Speicherverwaltung Umgang mit Strings Übergabeparameter: main() bekommt vom Betriebssystem Argumente argc: Anzahl der Argumente argv: Vektor aus Strings der Argumente (Indices von 0 bis argc-1) Anhang Rückgabeparameter: Rückgabe eines Wertes an das Betriebssystem Zum Beispiel Fehler des Programms: return EXIT_FAILURE; Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) Hands-on: Buffer Overflow 15 – 23 Lehrstuhl Informatik 4 Aufgabe: concat 15 – 23 Dynamische Speicherverwaltung 1 2 Zusammensetzen der übergebenen Kommandozeilenparameter zu einer Gesamtzeichenfolge und anschließende Ausgabe void *malloc(size_t size); void free(void *ptr); malloc(3) allokiert Speicher auf dem Heap Bestimmung der Gesamtlänge Dynamische Allokation eines Buffers Schrittweises Befüllen des Buffers Ausgabe der Zeichenfolge auf dem Standardausgabekanal Freigabe von dynamisch allokiertem Speicher reserviert mindestens size Byte Speicher liefert Zeiger auf diesen Speicher zurück 1 2 3 4 5 Implementierung eigener Hilfsfunktionen: 1 2 3 Übungen zu SPiC (SS 2017) size_t str_len(const char *s) char *str_cpy(char *dest, const char *src) char *str_cat(char *dest, const char *src) malloc(3) kann fehlschalgen ⇒ Fehlerüberprüfung notwendig char* s = (char *) malloc(strlen(...) + 1); if(s == NULL){ perror("malloc"); exit(EXIT_FAILURE); } Speicher muss später mit free(3) wieder freigegeben werden Wichtig: Korrekte Behandlung von Fehlern (!) 1 free(s); Was ist ein Segfault? Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 16 – 23 ⇒ Zugriff auf Speicher der dem Prozess nicht zugeordnet ist ≠ Speicher der reserviert ist Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 17 – 23 y Umgang mit Strings (1) Umgang mit Strings (2) bptr "hallo" ≡ • h a l l o size_t strlen(const char *s) \0 Bestimmung der Länge einer Zeichenkette s (ohne abschließendes Null-Zeichen) Rückgabewert: Länge Dokumentation: strlen(3) Repräsentation von Strings Zeiger auf erstes Zeichen der Zeichenfolge null-terminiert: Null-Zeichen kennzeichnet Ende ⇒ strlen(s) != Speicherbedarf char *strcpy(char *dest, const char *src) Kopieren einer Zeichenkette src in einen Buffer dest (inkl. Null-Zeichen) Rückgabewert: dest Dokumentation: strcpy(3) Gefahr: Buffer Overflow (⇒ strncpy(3)) printf(3) Formatierungsstrings %s String %d Dezimalzahl %c Character %p Pointer ... Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) char *strcat(char *dest, const char *src) Anhängen einer Zeichenkette src an eine existierende Zeichenkette im Buffer dest (inkl. Null-Zeichen) Rückgabewert: dest Dokumentation: strcat(3) Gefahr: Buffer Overflow (⇒ strncat(3)) 18 – 23 Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) Inhalt Arbeiten im Terminal Linux Navigieren & Kopieren: 1 Fehlerbehandlung 2 3 4 Aufgabe: concat cp /proj/i4spic/pub/aufgabeX/vorgabe.h /proj/i4spic/<login>/⤦ Ç aufgabeX # oder cd /proj/i4spic/<login>/aufgabeX cp /proj/i4spic/pub/aufgabeX/vorgabe.h . Kompilieren: 1 Anhang Arbeiten im Terminal Debuggen Valgrind Übungen zu SPiC (SS 2017) gcc -pedantic -Wall -Werror -O2 -std=c99 -D_XOPEN_SOURCE=500 -o ⤦ Ç cworld cworld.c Bereits eingegebene Befehle: Pfeiltaste nach oben Besondere Pfadangaben: . aktuelles Verzeichnis .. übergeordnetes Verzeichnis ˜ Home-Verzeichnis des aktuellen Benutzers Hands-on: Buffer Overflow Lehrstuhl Informatik 4 19 – 23 19 – 23 ⇒ Eine Verzeichnisebene nach oben wechseln: cd .. Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 20 – 23 1 Debuggen Valgrind gcc -g -pedantic -Wall -Werror -O0 -std=c99 -D_XOPEN_SOURCE=500 -⤦ Ç o cworld cworld.c Informationen über: Speicherlecks (malloc/free) Zugriffe auf nicht gültigen Speicher -g aktiviert das Einfügen von Debug-Symbolen -O0 deaktiviert Optimierungen Standard-Debugger: gdb 1 gdb ./cworld 1 cgdb --args ./cworld arg0 arg1 ... Ideal zum Lokalisieren von Segmentation Faults (SIGSEGV) Aufrufe: valgrind ./cworld valgrind --leak-check=full --show-reachable=yes --track-origins⤦ Ç =yes ./cworld „schönerer” Debugger: cgdb Kommandos b(reak): Breakpoint setzen r(un): Programm bei main() starten n(ext): nächste Anweisung (nicht in Unterprogramme springen) s(tep): nächste Anweisung (in Unterprogramme springen) p(rint) <var>: Wert der Variablen var ausgeben ⇒ Debuggen ist (fast immer) effizienter als Trial-and-Error! Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 21 – 23 Lehrstuhl Informatik 4 Inhalt Übungen zu SPiC (SS 2017) 22 – 23 Hands-on: Buffer Overflow Passwortgeschütztes Programm Linux 1 2 3 4 Fehlerbehandlung Aufgabe: concat 1 2 3 4 5 6 7 8 9 10 Anhang Hands-on: Buffer Overflow # Usage: ./print_exam <password> $ ./print_exam spic Correct Password Printing exam... Ungeprüfte Verwendung von Benutzereingaben ⇒ Buffer Overflow long check_password(const char *password) char buff[8]; long pass = 0; } strcpy(buff, password); // buffer overflow if(strcmp(buff, "spic") == 0){ pass = 1; } return pass; Mögliche Lösungen Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 22 – 23 Prüfen der Benutzereingabe und/oder dynamische Allokation des Buffers Sichere Bibliotheksfunktionen verwendeten ⇒ z. B. strncpy(3) Lehrstuhl Informatik 4 Übungen zu SPiC (SS 2017) 23 – 23