 Hallo, mein Name ist Wolfgang Hotwagner. Ich arbeite am Austrian Institute of Technology in der Research Engineer in dem Center für Digital Safety and Security. Und ich rede heute ein bisschen über containerfähige Linux Kernel Rookets. Bevor ich zum ITEC gekommen bin, war ich 13 Jahre Linux Admin. Und als Linux Admin hat man einen gewissen Respekt für Linux Kernel Rookets. Und frei nach dem Motto Know Your Enemy habe ich schon 2006 mein erstes Rooket programmiert. Und als ich dann 2017 irgendwie davor gestanden bin, irgendwie eine Bachelorarbeit zu schreiben, dachte ich mir, ich roll das einfach wieder auf dieses alte Rooket. Und das ist jetzt der Großteil von dem, der hier ist aus dieser Bachelorarbeit. Als Inspiration war natürlich das Frag Magazine, das coolste Magazine ever. Da gab es schon Artikeln über Rookets, über alle möglichen Formen von Rookets. Und ich kann die Artikeln wirklich sehr empfehlen. Sie sind jetzt immer noch spannend, wenn auch nicht mehr ganz so aktuell mitten können. 2006 war ich in Berlin beim CCC und habe da einen Vortrag gesehen von Johanna, ich hoffe, ich spreche es richtig aus, Rudovska. Und sie hat das Blue Pill Rooket vorgestellt. Dieses Rooket war ein Rooket, das das System in eine virtuelle Maschine gepackt hat. Und das Rooket hat außerhalb dieser virtuellen Maschine gearbeitet. Ziemlich cool, ziemlich stealthy. 2016 hat Michael Leibowitz, ich glaube, auf der Blackhead, wenn ich mich nicht täusche, das Horse Pill Rooket vorgestellt, das das Gleiche gemacht hat, nur mit Container. Das heißt, das hat das System in einen Container versetzt. Und bis jetzt ist mir noch kein Rooket untergekommen, das eigentlich mit Containersystemen irgendwie umgehen kann. Somit habe ich einmal diese Arbeit gestartet. Was sind Rookets? Wenn ein Angreifer erfolgreich war bei seinem Ziel, will er sein Zugriff sicherstellen, er will wieder reinkommen, sich versteckt bleiben und installiert dazu am besten ein Rooket. Es gab laut Internet Recherche, bitte, schon in den 80er Jahren das erste Rooket. Das hat einfach nur irgendwie die Logs gekleinnt. Es gibt verschiedene Rookets unter Linux. User Mode Rookets und Kern Mode Rookets, die einfachsten User Mode Rookets ersetzen einfach Binarys. Also keine Ahnung, will man das PS, einen Prozess nicht zeigt, dann patche ich einfach PS. Will ich das Netzdat, irgendeine Netzwerkverbindung nicht zeigt, dann patche ich einfach Netzdat. Eine andere Art von User Space Rooket ist einfach LD Preload. Das hockt einfach Library Functions und ich kann dann zum Beispiel Read Tier hocken und Read Tier einfach mein eigenes Read Tier so programmieren, dass es gewisse Dateien nicht anzeigt. Und dann gibt es Linux Kern Rookets. Und wie geht es jetzt? Ja, Container, Container sind super blieb, seit Docker, nur was genau ist ein Container. Jetzt vor kurzem gab es in LWN Magazine irgendwie die Diskussion, was ein Container eigentlich ist. Der Kern bietet Funktionen zu misulieren von Prozessen, verschiedenste Funktionen, nur es ist nicht klar definiert, was jetzt ganz genau ein Container ist. Die einzelne Container-Lösung kann das jetzt anders implementieren. Im Normalfall wird ein Prozess in einen Prozess-Namespace, in ein PRD-Namespace gegeben, es gibt auch andere Namespaces und das passiert dann mit der Funktion Clone oder Anshare. Wer genauer über Container Bescheid wissen will, den empfehle ich diesen Blog, das Blog von einer Hackerin namens Lissi. Sie hat ein Container-Programm in C geschrieben mit 500 Zeilen Code. Sehr inspirierend und sehr cool, wenn man die vergehen will in Containersystemen. Es kommen unterschiedliche Technologien zum Einsatz bei Container. Es gibt Namespaces, die einfach Prozesse oder User oder Netze irgendwie isolieren und trennen. Es gibt C Groups, die einfach die Ressourcen limitieren können. Es gibt Capabilities, die unprivilegierten Prozessen einfach gewisse Permissions gibt. Es gibt SecComp, das einfach die Süßkolz beschränken kann für einen Prozess. Das sind ungefähr so die Technologien, die man dann verwendet, um irgendwie ein Container zu starten. Namespaces sind dabei wirklich eine elementare Geschichte. Es gibt die unterschiedlichsten Namespaces. Ich hoffe, diese Liste ist noch aktuell, weil sie ist noch aus dem Jahr 2017 und da ist C Group Namespace gerade dazugekommen. Es kann sein, dass es jetzt noch einen weiteren gibt. Mir ist, ich weiß nicht davon. Verwendet durch mein Rookkit hauptsächlich den PAD Namespace, den Mount Namespace und den Net Namespace, weil sie einfach für das, was ich machen will, am spannendsten sind. Ich komme dazu noch. Der PAD Namespace. Der ist so spannend, weil man hat einen Prozess, der läuft in einem Namespace. Zum Beispiel in den Net Namespace. Das WIR-System ist ja genauso in einem Namespace zu beginnen. Dieser Prozess startet einen weiteren Prozess, der in einen neuen Namespace gestartet wird, zum Beispiel mit Klon, mit dem Klon Süßkoll. Dann hat dieser neue Prozess zwei PADs. Eine im Parent Namespace und eine im Klein Namespace. Und es kann passieren, dass im Klein Namespace PAD1 ist und der Parent mit einem anderen Prozess auch die PAD1 hat. Abgebildet werden Prozess-IDs bzw. Prozesse oder Tasks wie alles unter Linux, alles ist file, alles ist eine Datei, im Proz-Datei-System. Das heißt, wir hätten dann im Proz-Datei-System vom PAD Namespace eine Datei namens 1. Dieses Proz-Filesystem brauchen wir dann später, um Prozesse zu verstecken. Und wir sind da jetzt auch schon einen weiteren Namespace. Nicht unmittelbar, eingezeichnet in meiner hübschen Grafik, sondern wir sind da in diesem Ding. Dieses Proz ist natürlich anders, wie das Proz vom Parent. Das heißt, wir haben da auch den Mount Namespace. Ja, Colonel Rukitz. Ein User, wie kontrolliert von seinem Administrator, der ist ein Super-User und bei einem kompromittierten System gibt es dann den Super-Duper-User. Und das ist eben der Hacker, der im Colonel sitzt. Rukitz, habe ich schon gesagt, haben die unterschiedlichsten Aufgaben verstecken von Dingen, Logs vermeiden, Hinterdürre bereitstellen. Das Rukitz selbst verstecken ist ein so ein Ding, aber in den meisten Fällen oder in den meisten mir bekannten Fällen ist es eine Kombination aus einem User-Space-Programm und einem Colonel-Space-Programm. Das heißt, die meisten Rukitz, die man so irgendwo auf GitHub oder sonst irgendwo findet, hat in irgendeiner Form und eben das Colonel-Modul. Die übliche Methode, wie man einem Prozess verstecken kann für alle, die es nicht wissen, ist einfach, ich habe es vorhin schon gesagt, im Brotz-Filesystem werden eben die Prozesse abgebildet. Das heißt, wir haben da zum Beispiel Prozess mit der PID 1 und einem mit PID 7. Und wenn der Colonel jetzt sagt, hey, diese Datei gibt es nicht, also einfach diese Datei ausblendet, dann ist es für die meisten Tools so, okay, die gibt es nicht. Und so kann ich sehr effizient ein Prozess verstecken. Es gibt unterschiedliche Methoden, das im Colonel zu tun. Ich kann einfach den System-Cold-Table patchen, das heißt, das ist der Table, wo einfach Function-Point das drin sind zu den einzelnen System-Colds. Ich kann das einfach austauschen mit meiner eigenen Function und kann so eben zum Beispiel GetDance, was der System-Cold für ReadDia wäre, patchen und könnte so diese PID 1 aus dem Brotz ausblenden. Es gibt noch weitere Methoden, zum Beispiel den Interrupt-Description-Table-Patchen ist ähnlich. Man kann das virtuelle File-System patchen, zudem komme ich auch noch und Cahook, um ehrlich zu sein, ich habe keine Ahnung, wie Cahook funktioniert. Ich habe es nur gesehen, wenn es ein Rap-Teil auf GitHub zu finden ist, wenn das eine neue Methode ist, ich habe keine Ressourcen dazu gefunden, ich konnte nicht wirklich recherchieren, tut mir leid. Infektions-Möglichkeiten gibt es mehrere. Es gibt Ins-Mod, einfach das Modul-Laden. Ich kann das Colonel-Binary einfach austauschen und rebooten. Es gab eine Zeit, das Problem, dass Def-Mem oder Def-K-Mem einfach zu patchen war, und ich habe einfach mein Binary direkt in der Memory geschrieben, das macht zum Beispiel das Roo-Kids-Suckit und ja, ich habe das Def-Mem extra nochmal aufgeschrieben, das funktioniert jetzt nicht mehr, die Colonel-Entwickler haben da reagiert und haben den Memory, der da erreichbar ist, limitiert und begrenzt und somit ist das nicht mehr möglich, was ich eigentlich geschrieben habe, ist diese CV-Eder aufgekommen und die konnte diese Restriction umgehen. Es gab eine Sicherheitslücke im Colonel, die konnte diese Restriction umgehen und bei solchen Bucks kann natürlich so ein Roo-Kids ein Revival überleben. Und vor kurzem gab es ja Thunder Clap mit Direct Memory Access, ich habe keine Ahnung in welchen Memory man da überall reinschreiben kann, aber das könnte auch so was Ähnliches sein, das wäre vielleicht eine neue Forschung. Zu meinem Roo-Kid mein Roo-Kid war natürlich nur ein Labor, ich wollte damit einfach nur mal rein programmieren, mal reinschauen in den Linux-Kern und mal sehen, was mit den bekannten Methoden beim Containersystem anders ist und habe dann einfach mal reinschieben. Ich habe mal gewisse Anforderungen gesetzt beziehungsweise mein Scope ein bisschen limitiert, weil so ein Roo-Kid wenn man dann einmal anfängt, das kann es sehr aushalten und man kommt immer mehr auf Ideen drauf und man könnte immer mehr machen, aber ich habe es auf jeden Fall in irgendeiner Form begrenzen müssen. Es sollen natürlich Container berücksichtigen, das ist das originelle an diesem Roo-Kid. Das Modul soll versteckt sein, das Modul ist straightforward. Es soll Prozesse verstecken können. Es soll eine Privilege Escalation ermöglichen. Es soll einen Ausbruch aus den Container ermöglichen, das war besonders wichtig. Es soll ohne Kleinen da auskommen. Warum? Container sind meistens ziemlich limitiert und es gibt vielleicht viele Container in einem System und ich will mit dem Roo-Kid sprechen können ohne irgendeine Anwendung. Ich will nichts drauf installieren müssen, das soll einfach funktionieren. Und es soll in Memory. Das war einfach nur der Einfachheit halber, weil ich mich nicht um die Persistierung kümmern muss. Also, dass es nach einem Roo-Kid, nach einem Reboot, wiederladet. Ja, System Calls verändern, ich habe schon gesagt, man kann ein System Call Table batchen und einfach einmal eine PID nicht anzeigen, indem man Get Dance zum Beispiel patcht und das wäre zum Beispiel ein Beispiel von einem Code, der System Calls patcht, nicht der ganze Code, aber man sieht ungefähr, worauf es hinausläuft. Ich habe hier einen Function-Pointer, der einfach nur den alten originalen System Call speichert und ich habe einen Function-Pointer, der den neuen meine böse Function speichert beziehungsweise damit ersetzt sich eigentlich das Setuit. Und man sieht schon, im Code, das ist im Übrigen eine typische Backdoor, mit der kann ich eine Privilege Escalation erreichen, indem ich einfach den aktuellen Task UID 0 GroupID 0 Setuit 0 und weiter setz. Ich kann auch Capabilities setzen oder SecComp entsprechend setzen. Und man sieht schon, es wird bei der IV-Prage, wenn ich das pro Container, wenn ich jetzt sage, ich will jetzt nur einen bestimmten User in einen bestimmten Container jetzt automatisch Rotrechte geben, dann muss ich mich darum kümmern, in welchen Namespace er ist. Das heißt, ich muss wissen, in welchen PID Namespace dieser Prozess ist. Und ich muss in diesen Prozess, in diesen Namespace dann die PID für den jeweiligen Prozess finden. Und wenn man sich das dann genauer anschaut, müsste man, wenn man jetzt sagt, ich will auch das irgendwie managen, müsste man eine Struktur angeben, die einfach den PID Namespace drehen hat und ein Area mit PIDs, die zum Verstecken sind, sodass ich für jeden Namespace eben eine Liste an PIDs habe. Das wird sehr, sehr komplex, wenn man das so macht. Und ich komme dann später noch mal darauf zurück. Aber ich habe es so gemacht zuerst. Man kann auch das virtuelle File System patchen. Das ist auch eine super schicke Möglichkeit, das Dinge zu verstecken. Das tolle an File System patchen ist, dass es sehr spezifisch auf einem Container ist. Das heißt, ich kann sagen, ich will jetzt eine Datei nur in diesem einen Container verstecken. Ich nehme dazu den Mount Namespace, wo diese Datei ist und patcht da die File-Operationen. Das heißt, die Funktionen, die zum Beispiel bei einem Read Tier aufgerufen werden würden. Und das gleiche wieder, ich blende dann einfach in dieser Funktion gewisse Dateien, die ich verstecken will, aus. Das wäre ein Beispiel. Man sieht, dass ich hier dann eben wieder den PID Namespace brauche, indem ich das verstecken will. Und ich muss dann in diesem PID Namespace das Mount Namespace finden, wo dann das Brots drin ist. In so einem typischen in dieser typischen VFS Mount Struktur ist dann einfach das Route File System, das Brots File System zu finden. Es hat sich, es hat sich rausgestellt, dass Dinge, die ich nur in einem Container machen will, für das besonders das virtuelle File System patchen, weil ich das einmal mache und dann automatisch diese Funktion aufgerufen werde. Das heißt, ich erspare mir diese If-Anweisung und das Suchen von Namespace und zugehöriger PID. Das System Call Table patchen wiederum eignet sich besonders gut für globale Operationen. In meinem Fall habe ich die API, mit dem ich mit dem RouteKit rede, über System Call patchen gemacht. Weil das ist global, das funktioniert in jedem Namespace gleich. Das funktioniert auch beim Wirten oder beim initialen Namespace. Das funktioniert überall. Ausbruch aus dem Container. Ich habe da wirklich viel versucht, extrem viel versucht. Ich habe die Task Struktur hergenommen, einen anderen PID Namespace gegeben. Ich habe den User Namespace geändert. Ich habe wirklich alles gemacht und für alle meine Versuche gab es dann eigentlich einen Kernel Panic. Und ich habe dann viel gesucht und gesucht und gesucht und bin dann zu einer Funktion, die heißt Call User Mode Helper Exec. Und die Funktion ermöglicht, dass man aus dem Kernel raus einfach startet. Und ich habe das implementiert und habe keine Kernel Panic mehr bekommen, aber einen Speicherfehler. Und das hat damit zu tun, dass ich diese Funktion starte aus einem System Call und diese Funktion dauert zu lange und in einem Interrupt Handler sollte man solche Funktionen nicht starten. Der Kernel hat irgendeine Protection und kommt daneben mit einem Speicherfehler. Es gibt einen Workaround oder den richtigen Weg, wie man das verwendet. Man kann einen Worker starten. In dem Worker startet man dann einen neuen Kernel Thread und darin wird dann das ausgeführt. Und alles ist okay und alles ist wunderbar und es funktioniert. Ich habe dann jetzt so irgendwie mein eigenes Exec geschrieben. Wenn da ein spezieller Name gestartet wird, dann wird das global im ganzen System aufgerufen. Das heißt, ich bekomme kein Feedback, ob dieser Call funktioniert hat. Ich sehe auch keinen Output davon, aber es funktioniert in jedem Container und es startet auf jeden Fall meine Funktion im globalen System. Ich brauche auch keine kleinen Software dafür. Vier Wochen vor meiner Präsentation hole ich also nochmal meinen Code draus, den ich 2017 geschrieben habe und kann darauf, dass ich damals die virtuelle Maschine gelöscht habe. Und ich habe zwar Git verwendet, aber größtenteils meinen Code habe ich brav committed, nicht gepusht. Also musste eine neue Version her. Und ich habe schon gesagt, es ist super, super, super mühsam mit dem PIDs und das Managen, in welchen Container ich im Prozess verstecken. Und das war, ich war total unmotiviert, ich wollte es nicht machen und ich kam dann mit einer neuen Lösung. Wenn ich einen Prozess verstecken will, dann will ich ihn nicht selektiv im globalen System oder in einem Container oder in einem Untercontainer von einem Container machen. Nein, ich will ihn überall verstecken. Und ich habe jetzt einfach die Taskstruktur hergenommen und habe dann meine eigenen Flex einfach da reingeschrieben in die aktuelle Taskstruktur und habe somit einfach meinen Task markiert, der soll versteckt werden. Es ist super effizient. Ich habe dann einfach nur mehr Systemcalls gewendet. Beim Master Version 1 habe ich das virtuelle File System zum Verstecken von Prozessen hergenommen. Und was ein bisschen mühsam ist, auch zum Programmieren. Und jetzt konnte ich es ziemlich einfach mit einem Systemcall machen. Und es funktioniert trotzdem sehr effizient. Ich habe auch angefangen, einen Dateitransfer zu machen. Das heißt, ich habe schon gesagt, man kann mit meiner Containerausbruchfunktion Commons im globalen System starten. Nur, will ich eine Reverse Shell machen und weiß ich nicht, ob es NetCad gibt oder ob es EnCad gibt und so weiter. Das wäre doch super praktisch, wenn ich einfach die Container files hochladen kann ins globale System. Das ist leider nicht fertig. Ich habe die letzten zwei Tage damit verbracht, es irgendwie fertigzustellen. Nur es gab viel zu aufregende Talks und bin dann einfach nicht weitergekommen. Ja, dann schauen wir uns den Master Inaction an. Hier haben wir einmal einen Container. Dann einen Listener vom Angreifer und hier noch das globale System. Ja, sofort. Also, wir nehmen an, der Angreifer ist schon im System und hat seine Files schon hochgeladen. Das ist ein Standard Ubuntu Container und es gibt kein LS-Mod und es gibt auch kein Ins-Mod. Darum habe ich den Loader selbst geschrieben. So, standardmäßig ist das Modul geladen und auch sichtbar. Jetzt versteckt man es einmal. Ich habe dazu einfach ein Kill System Call geheitcheckt und es ist weg. Dann sollte es hier eben ein Base geben mit der PID 1. Hat im Übrigen nichts zu tun mit dem globalen System PID 1. Wir können schauen, ob wir da die Shell finden. Sie hat im Globalen oder im Namespace vom Initialen System die PID 1.214. Und ich werde sie jetzt einfach einmal verstecken. Auch dafür habe ich ein eigenes Kill und wir schauen nochmal im Container weg und wir schauen da auch weg. Wollen wir natürlich noch ein Ins-Globales-System führen einfach eine Biverse-Shell aus. Ja, genau. Schauen wir irgendwie noch ein Beweis, dass wir wirklich da sind. Und weil Ostern ist, gibt es auch ein E-Stack. So weit, so gut. Ich war jetzt viel zu schnell und habe bestimmt einiges vergessen, aber ich habe nicht so viel zu vergessen. Nach der Version 2 von meinem Rook-Kit sind natürlich viele neue Dinge aufgekommen, zu denen ich jetzt auch noch komme. Aber ich habe auf jeden Fall lessons learned gehabt. Lessons learned im Sinne von es gibt schon einige spannende Dinge, die zu beachten sind, wenn man in ein Rook-Kit für ein Containersystem schreibt. Zu meinen eigentlich für globale Anweisungen oder für alles, was überall funktionieren soll. Das virtuelle File-System-Patchen ist natürlich, wenn es irgendwie spezifisch sein soll, optimal Tasksflächen und Code minimieren, ist wirklich praktisch, ist wirklich essentiell. Das hat mir viel Arbeit erspart und es hat auch viele Fehlerquellen rausgegeben und Fehler in einem Kernmodul das will man nicht haben, weil es endet meistens mit einer Code-Penic. Ja, Call-User-Motor-Helper-Exec ist sehr gut geeignet für den Ausbruch aus einem Container und da ich habe ja dieses Beispiel von diesen Fehler im Docker, wenn euch aufgefallen ist, ich konnte im Container Ins-Mod aufrufen, nicht wirklich, es gab ja kein Ins-Mod, ich habe meinen eigenen Loder verwendet. Aber das lag daran, dass einfach die Capabilities-Sys-Module bei einem Container zugewiesen waren und das erlaubt einfach das Laden von Modulen. Ich habe das nicht frei erfunden, dieses Szenario, sondern es gab es vor Kurzem bei Play with Docker. Wenn jemand von dieser Sicherheitslücke gehört hat, ich sehe niggende Köpfe, da war es genau das. Sicherheitsforscher haben eben bei Play with Docker, das ist ein Service, wo man sich anmelden kann und mit Docker ein bisschen spielen kann, da einen Container gestartet und da einfach mal ein bisschen gepenntestet und rausgefunden, dass sie da Kernmodule laden können. Und haben dann einfach ein Kernmodul geschrieben, dass genau Call-User-Mode-Exec gestartet hat und mit dem haben sie dann eine Reverse-Stelle erreicht. Also es ist tatsächlich Szenarien denkbar, dass genau solche Sicherheitslücken auftreten können. Und da ist dann so ein Rookit super gefährlich. Zum Ausblick, wie gesagt, es hat viele Fragen aufgeworfen. Ich habe den Dateitransfer schon erwähnt, den wollte ich unbedingt noch irgendwie hinkriegen vor diesen Vortrag, aber ich habe es leider nicht mehr geschafft. Dieser Netzwerk-Namespace hat mich irgendwie noch gejuckt, weil wenn ich in einem Container eine Netzwerkverbindung starte, dann sehe ich mit Netset zum Beispiel nur in dem Container diese Verbindung. Das heißt, im Parent-Container sehe ich diese Verbindung nicht. Der Netzwerk-Namespace ist da ein bisschen anders wie der PID-Namespace. Beim PID-Namespace sehe ich die PID auch im initialen Namespace. Beim Netzwerk-Namespace nicht. Das heißt, Verbindungen, die ich aufmache, sehe ich dann nur im Container. Würde ich jetzt irgendeine Monitoring-Softere starten, müsste man sie natürlich auch in jeden Container starten, wenn sie Netzwerkverbindungen auch überwacht. Oder mir etwas einfallen lassen, dass ich das trotzdem mit einem TCP-Dump oder ähnlichen. Und das hat mir irgendwie zum Nachdenken gegeben, ob es vielleicht möglich ist, diesen Netzwerk-Namespace auszunutzen, um Netzwerkverbindungen zu verstecken. Weil die üblichen Methoden, wie man in einem Root-Kit oder in einem Kernel-Root-Kit in dem man einfach Slash, Brot-Slash, Net-Slash, TCP oder so alle Zugriffe auf diese Datei patcht und einfach die Verbindung, die da ausgelesen wird und die wir verstecken, nicht anzeigen. Also vielleicht ist mit dem Netzwerk-Namespace da irgendwie eine Möglichkeit auf eine andere Form ein Netzwerk zu verstecken. Direct-Memory-Excess zum Kernel-Space-Patchen kann ich gerne sehen und würde mich wirklich interessieren, ob das möglich ist. User-Namespace, den habe ich bis jetzt überhaupt aus Sach gelassen, könnte auch irgendwie spannend sein, vielleicht um User zu verstecken. Und mein Wissen hoffe ich, dass ich in der Anomalie-Erkennung einsetzen kann. Ich bin bei der AIT in einem Team, wo wir Anomalie-Erkennung auf Linux-Systemen irgendwie arbeiten und das Wissen um solche Root-Kits und um diese Techniken kann mir da einfach weiterhelfen. Dankeschön. Gibt es irgendwelche Fragen? Hast du dir auch K-Probes mit BPF angeschaut, weil im Moment scheint das so im Moment das zu sein, mit dem man Root-Kits schreibt für den Kernel, damit so sehr gut verstecken kann. Mit was bitte? K-Probes ist ähnlich wie K-Hooks, mit einem Kernel schon drin. Ja, habe ich mir nicht angeschaut. Ich habe Root-Kits gesehen, die das gemacht haben, habe ich aber nicht angeschaut. Könnte im Übrigen spannender sein, weil im Kernel ändert sich relativ viel und relativ schnell relativ viel. Und Dinge, die in einer vorigen Version funktioniert hat, wird in der nächsten Version dann wieder nicht funktionieren. Man ist natürlich dann immer hinterher, hinter den Kernel-Versionen und in der nächsten Version. Okay, dann Dankeschön.