Vollversagen bei OpenSSH: Is a directory

Nehmt es mir nicht übel, aber anders als ein komplettes Versagen auf ganzer Linie kann man den Fall bei OpenSSH nicht bezeichnen, zumal es um einen kleinen, aber sinnvollen Bugfix geht.

Vollversagen bei OpenSSH: „Is a directory“

Damit Ihr versteht um was es geht, müssen wir zurückreisen ins Jahr 2010. Damals wurde ein Bugreport im Bugtracker von OpenSSH veröffentlicht: https://bugzilla.mindrot.org/show_bug.cgi?id=1768

Von dem wußte ich aber nichts, als ich 2015 über das Problem gestolpert bin. Das Problem sieht wie folgt aus:

scp testdatei user@servername:/topdir/subdir/

Wenn es „subdir“ als Directory gibt, dann wird testdatei dahin kopiert und alles ist gut. Wenn es „subdir“ aber nicht gibt, dann würde man ja wohl erwarten, eine Fehlermeldung zu bekommen, aus der genau das hervorgeht, oder? Tja, wie soll ich sagen, ähm…nein!

Actual results:

scp: /usr/doesnotexist/: Is a directory

Wow.. oder? Das komplette Gegenteil von dem was man annehmen würde 🙂 Diese Aussage bekommt jeder, der sich OpenSSH selbst aus den original Sourcen kompiliert, denn, obwohl der Fehler schon 2010 gemeldet wurde und 2015 Jakub Jelen von Red Hat einen kompletten Patch geschrieben hat und das seit Fedora 20 und RHEL8 an alle „Nutzer“ in einem „Feldtest“ ausgerollt wurde, sieht sich das Projekt hinter OpenSSH nicht dazu in der Lage.

Eingeführt wurde der Bug übrigens um das Jahr 2005 herum. Damit sind es streng genommen schon 15 Jahre, die der Bug da vor sich hin dümpelt. Da ich Fedora nutze, habe  ich das Problem nicht mehr und viele andere Distros haben den RH Patch übernommen, aber traurig ist das schon, oder?

Leider mußte ich gerade feststellen, daß die neue Fehlermeldung auch nicht gerade viel besser als die alte ist:

scp: /tmp/ugdjkfh/: Not a directory

Das stimmt zwar inhaltlich, gibt aber den wahren Ursprung meiner Meinung nach nur unzureichend wieder 😉 Daher war ich mal so frei, Jakub darauf hinzuweisen, zumal ich den Bug da auch bei RH reportet hatte, vielleicht bekommt man nach 10 Jahren dann doch nochmal ein „Does not exist“ 😀 Wobei man als Server ja unterscheiden können muß zwischen „directory gibts nicht“ und „Du User, darfst da nicht reinschreiben“ unterscheiden wenn so eine Anfrage kommt, sonst könnte ein User niedriger Privilegierung die Verzeichnisstruktur einfach durchtesten. Ok, er könnte das viel einfach, wenn er eingeloggt wäre, aber ggf. hat der Account nur SFTP Zugang, ohne Interaktiven Shellzugang zu haben. Wäre ja denkbar.

Wie man sieht, doch nicht ganz trivial so eine saubere Fehlermeldung 😉

Wenn Ihr jemanden im OpenSSH Team kennt, könnt Ihr Ihn ja mal auf dieses Problem ansprechen. Übrigens erinnert mich das ganz stark an meinen Bugreport an ProFTP, weil deren 20 Jahre alte CHROOT Anweisung den Fall, daß da einer das Ziel per Symlink umgeleitet hat, nicht abgedeckt hatte. Das wurde auch Jahrelang geblockt bis es dann doch wer geschafft hatte, die Entwickler umzustimmen. Leider durfte ich mit dem 20 Jahre Bug-Jubiläumsvortrag nicht auf dem CCC sprechen. Dabei wollte ich nur son 15 Minuten Vortragsfenster im Nebenraum haben. Ich hatte denen sogar einen Patch für das Problem geschickt. Das wäre bestimmt lustig geworden, wenn die ProFTP Devs sich auf der Vortragsliste gesehen hätten 😀 Vielleicht packe ich Euch den Vortrag als PDF mal auf die Seite.

PHP-CGI verbraucht zuviel Speicher

Dieser Beitrag ist aus der Kategorie:

„Was kann da schon schief gehen“

Speicher ist billig, aber doch endlich und nicht beliebig nachrüstbar.  Es kann also Situationen geben, wo man Speicher einsparen muß, weil andere der irrigen Meinung, waren, das mit dem Speicherverbrauch  wäre kein Problem.

Aber der Reihe nach:  Was ist überhaupt das Problem ?

PHP als CGI ausgeführt, verbraucht pro Start > 400 MB Speicher fürs Nichtstun.

Beispiel:  „php-cgi -a“ startet PHP ohne irgend was zu machen.

In einer zweiten Konsole läßt man sich mit pmap anzeigen, wer in dem Prozess was an Speicher belegt:

pmap {pid of process}

Beispielausgabe ( gekürzt : Warum kommt später )

[root@xxx]# pmap 5408
5408:   php-cgi -a
0000560d00b44000   3724K r-x– php-cgi
0000560d010e6000    536K r—- php-cgi
0000560d0116c000     16K rw— php-cgi

00007fce773f8000     28K r-x– libcrypt-2.23.so
00007fce773ff000   2044K —– libcrypt-2.23.so
00007fce775fe000      4K r—- libcrypt-2.23.so
00007fce775ff000      4K rw— libcrypt-2.23.so

total           420372K

Genau, 410 MB und nicht eine Anweisung ausgeführt. 3.7 MB gehen für den PHP-Interpretercode selbst drauf, ok. 2 MB gehen alleine für die libcrypt drauf.

Und jetzt der Grund wieso die Ausgabe gekürzt ist: PHP benutzt 75 Libs => ~ 160 MB Speicherverbrauch … bei jedem Script!

Bei der Analyse ist aber aufgefallen, daß auch eine Locale eingebunden wird:

-rw-r–r– 1 root root 110562112 22. Dez 12:01 /usr/lib/locale/locale-archive
-rw-r–r– 1 root root         0 22. Dez 12:01 /usr/lib/locale/locale-archive.tmpl

Auch bekannt als 107 MB und diese Datei wird in jeden PHP Prozess geladen,  der läuft. Keine Gnade.

Locale  – was sind das ?

„Locals“ sind keine Eingeborenen, sondern nur die Informationen über jene, also Zahlensysteme, Schreibrichtung, Datumsformat, Gewichte, Längen usw. . Wer mal sehen will, welche auf seinem Linux installiert sind, gibt das ein : locale -a

Da kommen Sachen von Sprachen, wo man nicht mal sagen kann, wo die passenden Länder sind 😉

Irgendwann hat Red Hat mal entschieden, daß die einfach alle Sprachen des Planeten ausliefern, weil dann der User nicht mehr machen muß. Stimmt.

Auf einem Desktopsystem ok. Aber auf einem Server ist das nicht ok und deswegen muß das auf ein gesundes Maß gedrückt werden. Das macht man mit  : /usr/sbin/build-locale-archive -v -l „de:en:ru:jp“

„Oh… geht ja gar nicht“ ????

Doch geht, aber nur mit Trick Siebzehn aus der „Erschiesst den Trottel Ecke“.

Die obige Locale-Archiv-Datei kommt mit dem Paket „glibc-all-langpacks“ auf den Server. Damit kommt aber auch ein TEMPLATE File mit, aus dem man sich genau das Archiv selbst bauen kann, wenn man eben nicht alles haben will.

Ihr habt’s erfaßt, das wäre zu einfach gewesen 🙁

Die Templatedatei ist nämlich LEER und damit nicht zu gebrauchen. Ihr Fragt Euch jetzt : „Wie bekommt man so ein Template?“ hmm.. Tja.. aus dem Repo jedenfalls nicht und doch, bekommt man. Jetzt wird es lustig, wir kopieren das vorhandene Archiv als Template für sich selbst ! Ja, richtig, mit der Faust durchs Auge: In your Face Red Hat!

Also eingegeben:

cp locale-archive locale-archive.tmpl
/usr/sbin/build-locale-archive -v -l „de:en:ru:jp“
locale -a

und schon ist das File keine 107 MB  mehr sondern nur noch 7 MB und auch das halte ich für extrem viel Schrott für 4 Sprachen. Aber jetzt lädt das php nur noch 7 MB rein. Das macht in der Endabrechnung dann 25% weniger RAM Verbrauch.

Als nächstes muß man rausfinden, wieso die Libs jeweils 2 MB verbrennen, wenn die nur 70k groß sind. Aber das ist eine andere Geschichte aus dem |-: La-La-La-Land 😐 .