Fragen? Antworten! Siehe auch: Alternativlos
CVE-2013-4458 Stack overflow in getaddrinfo with large number of results for AF_INET6 has been fixed
Das ist remote code execution via unvertrauenswürdiger, unverschlüsselter Daten aus dem Internet. GANZ gruselig. Man würde denken, die libc ist der stabilste, sicherste Teil des Codes. Der ordentlich auditierte Code. Aber offensichtlich nicht. Auch die anderen Bugs sind gruselig, aber für die muss man schon auf dem System sein, um die ausnutzen zu können. Mein Lieblingsbug ist der hier:CVE-2013-4788 The pointer guard used for pointer mangling was not initialized for static applications resulting in the security feature being disabled.
Das ist ein typischer Ulrich Drepper. Als der noch glibc-Maintainer war, fand er, dass statisches Linken alt und scheiße ist und nicht mehr unterstützt gehört. Als er dann "Pointer mangling" einbaute, hat er es daher nur für dynamische Programme getan. Denn hey, wer linkt heutzutage noch statisch!1!!
Bei dieser Pointer-Verschlüsselung handelt es sich um eine Buffer Overflow Mitigation, also eine Maßnahme, die im Falle von Buffer Overflows die Ausnutzung erschweren soll. Die traditionalle Methode sind Stack Canaries, das sind "zufällige" Werte auf dem Stack. Und bevor man potentiell im Rahmen eines Buffer Overflows überschriebene Werte übernimmt, prüft man, ob der Kanarienvogel noch lebt, wie damals in den Minen. In der glibc wurde ein anderer Weg gewählt, nämlich dass die Pointer "verschlüsselt" werden. Dafür wird statt des tatsächlichen Wertes ein XOR mit einem "zufälligen" Wert und eine Rotation gemacht. Die Idee ist, dass der Angreifer das dann zwar überschrieben kann, aber da er den XOR-Wert nicht kennt, kann er nicht wissen, welchen Wert er da hinschreiben muss. Und der Wert ändert sich mit jedem Programmaufruf. Außer halt wenn man glibc nimmt und statisch linkt.
Was soll ich sagen. Kein Arbeitgeber passt so perfekt zu Ulrich wie Goldman Sachs. (Danke, Hannes)
Na gut, denke ich mir, guck ich mal in NEWS rein, das ist ja genau die Datei, wo man sowas erwähnt. Was steht da? Gar nichts zum Code in elf oder dem dynamischen Linker. Naja, wäre ja keinen Blog-Eintrag wert, es weiß ja jeder, was für ein Pfuscher das ist, aber dann fand ich das hier von 2004, und da fordert er ja explizit darauf auf, daß man anderswo über ihn meckern soll, und gerne dafür Blogs aufmachen soll. Nun, dafür ist er mir zu unwichtig, daß ich da noch nen Blog aufmachen würde für, aber hey, he had it coming. Ulrich Drepper ist für mich der Anti-Programmierer, der kann noch weniger als dieser Python-Schnösel oder dieser Ruby-Knallkopf. Ich traue den Kerberos- und X11-Leuten mehr Sachkenntnis zu als ihm. Wenn ich einen nennen sollte, der Linux am meisten schadet, ich müsste nicht lange nachdenken. Und bei Redhat ist der Mann auch prächtig aufgehoben, die haben sich gegenseitig verdient.
Hach wie ich das hasse, anderer Leute Bugs fixen zu müssen.
Update: das Problem ging bei mir weg, als ich in sysdeps/i386/i486/bits/atomic.h die Zeile
#if __GNUC_PREREQ (4, 1)gegen
#if __GNUC_PREREQ (4, 2)tauschte. Saubere Qualitätssicherung, Jungs, das habt ihr wirklich prima gemacht. Pah, wenn man eine neue libc rausbringt, warum sollte man da schon prüfen, ob das mit dem aktuellen gcc funktioniert. Wo kämen wir da hin. Linux muss spannend bleiben!
Aber wartet, kommt noch besser! Die Testsuite fällt auf die Fresse. Fehlermeldung:
iconv_prog: malloc.c:2575: do_check_chunk: Assertion `((char*)p) < min_address || ((char*)p) > max_address' failed.Hach, prima!
Zuerst muss man dafür Cross-binutils bauen, das sind Assembler und Linker und so, das ist auch normalerweise gar kein Problem.
./configure --prefix=/opt/cross --target=x86_64-linux --enable-static --disable-sharedund gut ist. Statisch deshalb, weil ich in /opt/cross auch Crosscompiler für zig andere Plattformen habe, um zu gucken, ob die diet libc noch mit allen Plattformen sauber baut. Wenn man da den Default nimmt, und ein Cross-Binutils für Alpha-Linux installiert, dann geht danach der Assembler für AMD64 nicht mehr, weil der die selbe Shared Library laden will, die aber von AMD64 nichts weiß. OK, damit kann ich leben. Fällt man einmal drauf rein, lernt man, gut ist.
Der nächste Schritt ist der Crosscompiler. Hier kommt die erste echt Hürde, denn der Crosscompiler baut normalerweise für C, C++, Java, Objective C, allen möglichen Schund Compiler. Die kommen alle mit Laufzeitumgebungen, die nicht kompilieren, weil sie eine funktionierende libc erwarten. Die haben wir nicht, wir bauen ja gerade den Compiler, mit dem wir sie dann übersetzen wollen. Daher sieht bei gcc die Configure-Zeile so aus:
./configure --prefix=/opt/cross --target=x86_64-linux --enable-static --disable-shared --enable-languages=c --disable-nlsDas --enable-static hier bezieht sich auf libgcc; wenn gcc die wie normal dynamisch zu bauen versucht, schlägt das mangels libc fehl. Aber auch so gibt es Ärger, weil libgcc von der Zielplattform die libc-Header haben will. Das finde ich persönlich ja einen groben Verlierer, ja geradezu den Stirnklatscher überhaupt. An der Stelle hat man normalerweise verloren. Übliche Notfall-Ansätze sind "Debian-Paket bzw Fedora-RPM der glibc der Zielplattform ziehen, von Hand die Header auspacken, und an die richtige Stelle (/opt/cross/x86_64-linux/include) kopieren". Wieso nicht einfach /usr/include nehmen? Weil bei der glibc die Header von der Plattform abhängen! Nicht so bei der dietlibc, und so habe ich für meine Crosscompiler immer die dietlibc-Header gesymlinkt, und dann ging das gut (mal abgesehen von Bizarro-Plattformen wie IA64, der will da Dateien und Symbole haben, von denen ich noch nie gehört habe, irgendwelcher libc-Support fürs Stack Unwinding… *grusel*).
Normalerweise höre ich an der Stelle auf, denn wenn ich einen Crosscompiler habe, kann ich damit die dietlibc übersetzen. Heute habe ich mich aber so über das Gentoo auf meinem Desktop geärgert, daß ich mir vorgenommen habe, meine Linux-Distro "Fefix" mal für AMD64 zu crosscompilen. Schritt 1: glibc. Und was soll ich euch sagen, glibc ist nicht crosscompilefähig! Der versucht, sizeof(long double) rauszufinden, indem er ein Programm übersetzt und ausführt. Das geht natürlich nicht. Gut, in configure fest 16 reingehackt (die Alternative ist, einen config.cache manuell zu erstellen, in dem das drin steht), und was sehen meine entzündeten Augen?
checking for libgd… no [libgd?!?!?…]WTF?! C cleanup handling? Und gcc 4.1.1 soll das nicht unterstützen?! ARGH! Na gucken wir uns doch mal das Testprogramm an:
checking for ANSI C header files… no [doh!]
checking for sys/types.h… no
checking for sys/stat.h… no
checking for stdlib.h… no
checking for string.h… no
checking for memory.h… no
checking for strings.h… no
checking for inttypes.h… no
checking for stdint.h… no
checking for unistd.h… no
checking for long double… no
checking size of long double… (cached) 16 [Warum macht er das überhaupt, wenn er glaubt, daß es kein long double gibt?!]
running configure fragment for sysdeps/x86_64/elf
checking for x86-64 TLS support… yes
running configure fragment for nptl/sysdeps/pthread
checking for forced unwind support… yes
checking for C cleanup handling… no
#include <stdio.h>Na und woran scheitert es wohl? RICHTIG! Kein stdio.h! Denn ich kompiliere ja gerade die libc, DAMIT ICH DIESES HEADER-FILE KRIEGE! Lieber Herr Drepper, warum erhängen Sie sich nicht einfach an der nächsten Eiche? Das würde uns allen viel Ärger sparen. Danke.
void cl (void *a) { }
int
main ()
{
int a __attribute__ ((cleanup (cl)));
puts ("test")
;
return 0;
}
Ich überlege, ob ich mal einen Wettbewerb ausschreibe, wer die beste Implementation von strfry und memfrob für libcompat in der diet libc macht… Das wäre im Übrigen alles nur halb so lächerlich, wenn Herr Drepper nicht strlcpy und strlcat den Zutritt in die glibc verweigert hätte, und als Alternative ernsthaft folgendes vorschlägt:
*((char *) mempcpy (dst, src, n)) = '\0';
But wait, there's more! zu strfry gibt es auch noch ein Security Advisory (das ich allerdings für hirnrissig halte, das könnte man genau so gut bei strlen bemängeln), und der absolute Oberhammer ist dieser Debilian Bugreport. Un-fucking-believable. Wenn es ein Code-Killfile gäbe, Ulrich Drepper wäre drin.
Oh, und wo wir gerade beim glibc-Bashing sind: man kann bei der glibc Callbacks definieren, um bei printf neue Format-Zeichen zu definieren. Und nun ratet mal, welche Qualitätssoftware dieses großartige Feature benutzt: richtig, reiserfsprogs. Die definieren damit z.B. einen Callback, um ein Tupel von zwei Zahlen auszugeben IIRC. Unfaßbar. Aber hey, reiserfs benutzt ja eh niemand, oder? Oder?!
Vielleicht sollte ich echt mal eine Webseite aufmachen, und dort ein Coder-Killfile unterhalten. Drepper, die Reiserfs-Jungs, Schilling, … da kämen aber nur die besonders harten Fälle hin. Ich will ja auch noch zu anderen Sachen kommen.