Grundlagen des Android Binder Frameworks 

Das Android Binder Framework dient als Eckpfeiler der Inter-Prozess-Kommunikation (IPC) in Android und ermöglicht sichere und effiziente Interaktionen zwischen Apps und Systemdiensten in einer Multiprozessumgebung. Binder unterstützt wichtige Betriebssystemfunktionen wie Service Discovery, Remote Procedure Calls und Datenpaketierung über UID-isolierte Prozesse hinweg und ersetzt weniger sichere Alternativen wie Sockets oder Shared Memory. Sein Treiber auf Kernel-Ebene erzwingt Prozessgrenzen und übermittelt gleichzeitig die Identität des Aufrufenden (UID/PID), wodurch er zu einem integralen Bestandteil des Berechtigungsmodells von Android und der SELinux-Richtlinien wird.

  

Schutzmechanismen moderner Betriebssysteme 

Die Prozessisolierung bildet ein grundlegendes Sicherheitsprinzip in modernen Betriebssystemen und adressiert die Herausforderung, mehrere Prozesse gleichzeitig ausführen zu können, ohne dass diese sich gegenseitig stören oder beeinträchtigen. Ohne Isolierung könnten fehlerhafte, bösartige oder kompromittierte Prozesse willkürlich aus dem Speicher und den Ressourcen anderer Prozesse lesen, in diese schreiben oder sie beschädigen. Dies könnte zu Datenlecks, Systemabstürzen oder einer vollständigen Kompromittierung des Rechners führen. Moderne Betriebssysteme lösen dieses Problem, indem sie jedem Prozess einen eigenen virtuellen Adressraum zuweisen. Dieser wird durch Hardware-Mechanismen wie Seitentabellen und Speicherverwaltungseinheiten (MMUs) durchgesetzt, sodass Prozesse nicht direkt auf den Speicher anderer Prozesse zugreifen können.  

Wie können dann zwei separate Programme miteinander kommunizieren, ohne die Sicherheit des Systems zu gefährden?  

In modernen Computern laufen zahlreiche Prozesse gleichzeitig. Jeder Prozess ist mit seinem eigenen zugewiesenen Speicherplatz isoliert. Sehr oft ist es notwendig, dass verschiedene Prozesse Informationen miteinander austauschen oder ihre Aktionen koordinieren.  

Obwohl dies wie eine einfache Anforderung klingt, bringt es eine Vielzahl unterschiedlicher Herausforderungen mit sich, wie zum Beispiel:  

  • Wie wird ein Zielprozessüberneue Dateninformiert?
  • Welcher Prozess sendet diese Daten? 
  • Ist dieser Prozess berechtigt, diese Art von Daten zu senden? 
  • Wo sind diese neuen Daten verfügbar? 
  • Kann der Zielprozess die neuen Daten berechnen und verarbeiten? 
  • Was passiert, wenn zwei Prozesse gleichzeitig Daten in denselben Speicherbereich schreiben wollen? 
  • Wie kann sichergestellt werden, dass die Daten während der Übertragung nicht beschädigt oder manipuliert werden?


Vom Linux-Kernel zur Sandbox: Prozessisolierung in Android 

Seit der Einführung von Multitasking-Betriebssystemen müssen Prozesse voneinander isoliert werden. Eine uneingeschränkte Interprozess-Kommunikation gefährdet das System als Ganzes. Es kompromittiert nicht nur die Sicherheit der einzelnen Prozesse, es ermöglicht es auch für einen einzelnen fehlerhaften Prozess, diesen fehlerhaften Zustand an das gesamte System weiterzuleiten, was im schlimmsten Fall zu einem Systemabsturz führen kann.  

Wie funktioniert also die Prozessisolierung und, was noch wichtiger ist, wie funktioniert sie in Android? Da Android auf dem Linux-Kernel basiert, gilt die Linux-Prozessarchitektur auch für Android. Jedem Prozess in einem Linux-System wird eine eindeutige Prozess-ID (PID) zugewiesen. Der Kernel verwendet diese PID, um den Prozess zu verwalten und sicherzustellen, dass jedem Prozess ein eigener virtueller Adressraum zugewiesen ist. Die Speicherverwaltungseinheit stellt außerdem sicher, dass jeder Prozess nur auf den ihm zugewiesenen Speicherplatz zugreifen kann. Ein Zugriff auf den Speicher eines anderen Prozesses ist verboten und wird blockiert. Android erweitert diese Konzepte durch die Zuweisung einer UID. Für jede auf einem Android-Gerät installierte Anwendung wird der neu installierten App eine eindeutige Benutzer-ID (UID) zugewiesen. So läuft jede Android-App als separater Linux-Benutzer.  

Jede App, ihre Prozesse und Dateien sind daher voneinander isoliert. Die Isolierung dieser Daten wird, zusammen mit anderen Dingen, oft auch als Sandbox bezeichnet. Darüber hinaus wurde seit Android 4.3 SELinux (Security-Enhanced Linux) eingeführt, um das Sandboxing-Modell zu stärken. SELinux arbeitet nach dem Prinzip der obligatorischen Zugriffskontrolle (MAC), bei der standardmäßig alle Zugriffe verweigert werden, sofern sie nicht ausdrücklich erlaubt sind. Selbst Root-Benutzerrechte können diese Einschränkungen nicht umgehen. Diese systemweiten Sicherheitsrichtlinien kontrollieren alle Prozesse. Diese Isolierung bringt jedoch auch einen Nachteil mit sich.  


Indirekte Kommunikation von Prozessen 

Prozesse müssen miteinander kommunizieren. Wenn Prozesse nicht miteinander kommunizieren könnten, wären moderne Anwendungen viel eingeschränkter. Ein Beispiel ist die Kameraanwendung auf einem Android-Telefon. Man stelle sich eine Scan-App vor, mit der man einen QR-Code scannen kann. Die Anwendung könnte entweder eine eingeschränkte Kamerafunktionalität in sich selbst implementieren oder einfach eine vorhandene Kameraanwendung verwenden, die in der Regel auf modernen Geräten vorinstalliert ist. In der Regel wird die letztere Lösung genutzt. Um auf die Kameraanwendung zugreifen zu können, muss der Prozess der QR-Scanner-App mit dem Prozess der Kameraanwendung kommunizieren können. Darüber hinaus muss die Kamera-App in der Lage sein, Daten, also das Foto des QR-Codes, an die QR-Scanner-App zurückzusenden. Aber wie können zwei isolierte Prozesse miteinander kommunizieren?


Rückblick: Sicherheitsrisiken der Prozesskommunikation

Obwohl die QR-Scanner-App und die Kamera eher moderne Beispiele sind, ist der Bedarf an der Fähigkeit isolierter Prozesse, miteinander zu kommunizieren, viel älter, ebenso wie die verschiedenen Lösungen. Der erste Ansatz bestand in der Verwendung eines dedizierten gemeinsamen Speicherbereichs. Unter Linux wurde häufig das Verzeichnis /tmp für den Datenaustausch zwischen Prozessen verwendet. Dieser Ansatz wies jedoch im Vergleich zu modernen Standards keinerlei Sicherheitsmerkmale auf. Es gab keine Schutz- oder Autorisierungsmechanismen für die Daten. Daher konnte jeder Prozess, auch solche, für die die Daten ursprünglich nicht bestimmt waren, die dort gespeicherten Daten lesen oder sogar verändern. 


Abbildung 1 : Zwei separate Prozesse, die auf einen gemeinsamen Speicherbereich zugreifen (vereinfacht) 

Das bedeutet nicht, dass dieser Ansatz nicht mehr verwendet wird. In Android gibt es tatsächlich einen gemeinsamen Speicherbereich, in dem Anwendungen Dateien speichern können, sodass andere Apps darauf zugreifen können. Allerdings handelt es sich dabei nicht um Daten, die Prozesse austauschen müssen, um ordnungsgemäß zu funktionieren. Wie bereits erwähnt, war der gemeinsame Speicherplatz für den Datenaustausch zwischen Prozessen nur der erste Ansatz. Es gab viele verschiedene Nachfolgeversuche, darunter die UNIX-Pipes, die auch nach wie vor noch verwendet werden. Heute verwendet Android ein komplexeres System für die Interaktion zwischen Prozessen. Dieses System heißt Binder. 


Ist das Android Binder Framework nur ein Mittelsmann? 

Das Android Binder Framework ermöglicht eine direktere Kommunikation zwischen zwei isolierten Prozessen auf sicherere Weise. Anstatt einen gemeinsamen Speicherplatz zu nutzen, erfolgt die Interaktion also direkt. Aber wie? Kehren wir zum Beispiel mit der QR-Code-Scanner-App zurück. Die Scanner-App fordert ein Foto von der Kamera-App an. Vereinfacht dargestellt fungiert das Android Binder Framework derzeit als eine Art Vermittler für die Anfragen und Antworten der Inter-Prozess-Kommunikation (IPC). 


Abbildung 2 : Zwei Anwendungen interagieren miteinander mithilfe von Binder 


Derzeit erfolgt jede Inter-Prozess-Kommunikation (IPC) innerhalb von Android über dieses Binder-Programm. Aber was genau ist dieses Android Binder Framework? Ist es eine weitere Anwendung, die auf jedem Android-Gerät vorinstalliert ist? 

Die Antwort lautet nein. Es geht viel tiefer!


Referenzen

Dieser Artikel wurde verfasst von