Die Verwaltung und Kontrolle von Dateisystemzugriffen gehört zu den komplexesten Herausforderungen im Bereich der Betriebssystementwicklung. Insbesondere bei sicherheitskritischen Anwendungen und Serverumgebungen ist es von großer Bedeutung, Zugriffe nicht nur effizient, sondern vor allem sicher zu steuern. OpenBSD, bekannt für seinen Fokus auf Sicherheit und Stabilität, bringt nun neue Ansätze ins Spiel, um die Systemaufrufe rund um openat(2) und seine Verwandten praxisnäher und nutzbringender zu gestalten. Die Weiterentwicklung zielt darauf ab, die oft als ineffektiv oder gar nutzlos wahrgenommenen *at(2)-Funktionen signifikant aufzuwerten. Dabei wird vor allem auf eine bessere Eingrenzung von Verzeichniszugriffen gesetzt, was wichtige Auswirkungen auf die Entwicklung von sicherheitsorientierter Software haben kann.
Das Konzept hinter openat(2) ist schon seit seinen Anfängen darauf ausgelegt, Dateisystemzugriffe gezielter und effizienter zu gestalten. Über einen zuvor geöffneten Verzeichnis-Dateideskriptor können relative Pfade gesucht und geöffnet werden, was gegenüber einem klassischen open()-Aufruf Vorteile bei der Sperrverwaltung und Performance mit sich bringen soll. In der Praxis haben sich jedoch wesentliche Probleme gezeigt, die dieses Potenzial stark begrenzen. Zunächst einmal behandelt openat(2) gemäß POSIX-Spezifikation Pfade absolut und relativ unterschiedlich. Ein absoluter Pfad wie beispielsweise /etc/passwd wird unabhängig vom übergebenen Verzeichnis-Dateideskriptor geöffnet.
Dies führt dazu, dass Sicherheitsmechanismen, die auf relative Pfadangaben setzen, bei absoluten Pfaden wirkungslos bleiben. Zudem erlaubt der Aufruf Verzeichnistraversierung nach oben („..“), was es ermöglicht, die Kontextbegrenzung durch das Ausgangsverzeichnis zu umgehen. Ein Angreifer könnte somit aus einer vermeintlich eingeschränkten Umgebung ausbrechen und auf übergeordnete Verzeichnisse zugreifen.
Als Reaktion darauf haben FreeBSD und Linux teilweise auf Flag-Erweiterungen im Systemaufruf reagiert, die eine „Upwards Traversal“-Sperre implementieren. Der Ansatz ist jedoch oft unpraktisch, da alle *at(2)-Aufrufe entsprechend mit Flags versehen werden müssen, was sowohl Fehlerquellen als auch Mehraufwand für Entwickler bedeutet. Der Vorschlag aus der OpenBSD-Community geht einen anderen Weg und versucht, das Problem konzeptionell anders zu lösen, um sowohl Sicherheit als auch Benutzerfreundlichkeit zu erhöhen. Die Idee ist, spezielle Verzeichnis-Dateideskriptoren einzuführen, die per Definition kein Traversieren oberhalb des geöffneten Verzeichnisses erlauben, also quasi eine natürliche „Containment“-Grenze im Dateisystem darstellen. Durch das Hinzufügen neuer Flags wie O_BELOW bei der Erstellung solcher Deskriptoren oder F_BELOW per fcntl()-Funktion kann ein Entwickler ein Verzeichnis gezielt „abschotten“.
Alle absoluten Pfadangaben, die versuchen, außerhalb der vom O_BELOW-Drektorium definierten Grenze zuzugreifen, schlagen dann fehl. Gleiches gilt für relative Pfade, die nach oben aus dem Verzeichnis heraustreten wollen. Diese Einschränkung des Pfadzugriffs bringt eine Reihe von Vorteilen mit sich. Zum einen erhöht sie die Sicherheit, indem sie verhindert, dass Programme versehentlich oder böswillig auf sonst nicht vorgesehene Ressourcen zugreifen. Es entsteht eine Art von „minimaler Jails“-Mechanismus, ohne dass die komplexen oder risikobehafteten traditionellen chroot()-Systemaufrufe verwendet werden müssen.
Insbesondere für Nicht-Root-Nutzer eröffnet das neue Verfahren damit bislang nicht mögliche Kontroll- und Abgrenzungsmöglichkeiten. Aus Entwicklersicht bedeutet das einen Paradigmenwechsel in der Art, wie Pfadoperationen gedacht und umgesetzt werden. Software kann jetzt sicher davon ausgehen, dass operationen im Kontext eines O_BELOW-geöffneten Verzeichnisses niemals außerhalb dieses Bereichs stattfinden. Somit reduzieren sich Fehlerquellen aufgrund falsch verstandener Pfadmechanismen. Zusätzlich sind Fehlersuchen wesentlich einfacher, da das Betriebssystem den wahren Umfang der Zugriffsrechte aktiv einschränkt und Verstöße unmittelbar mit Fehlercodes zurückmeldet.
Im Gegensatz zu anderen Schutzmaßnahmen wie unveil(), die ebenfalls aus dem OpenBSD-Projekt stammen, ist dieser Ansatz ressourcenschonender. Die Verwaltung erfolgt hauptsächlich über Dateideskriptorflags, sodass der Kernel nicht aufwendig Referenzen auf Knoten im Dateisystem verwalten muss. Dies begünstigt Performance und reduziert den Verwaltungsaufwand, was sich vor allem bei Anwendungen mit vielen gleichzeitigen Dateizugriffen bemerkbar machen dürfte. Ein weiterer interessanter Effekt ist, wie sich diese neue Methode wie eine „lightweight chroot()-Alternative“ verhält. Indem der Prozess durch fchdir() in den Kontext des O_BELOW-Verzeichnisses gewechselt wird, kann die Laufzeitumgebung effektiv an das Verzeichnis gebunden werden.
Gleichzeitig bleiben typische Risiken wie Verwirrungen durch absolute Pfade oder Library-Verhalten minimiert, da das offene Verzeichnis sauber eingeschränkt ist. Diese Möglichkeit könnte sich vor allem für Dienste und Daemons etablieren, die heute auf chroot() setzen, um ihr Dateisystemminimierungsziel zu erreichen, ohne dabei Systeme kompliziert abzusichern oder Root-Rechte zu benötigen. Natürlich erfordert diese Änderung auch Anpassungen in existierendem Code, gerade im Umgang mit Verzeichniseinträgen wie „.“ und „..
“. Entwickelnde müssen sich darauf einstellen, dass Operationen auf „..“ nicht mehr erfolgreich sein werden und im Fehlerfall behandelt werden müssen. Das fordert gewisse Disziplin und möglicherweise Anpassungen bei Pfadmanipulationen.
Allerdings steht dem ein deutlich verbesserter Schutz gegenüber, der vielen sicherheitsbewussten Anwendungen entgegenkommt. Die Diskussion innerhalb der OpenBSD-Tech-Community dokumentiert auch die noch laufenden Tests und Evaluierungen dieser neuen Mechanismen. So veröffentlichte der Initiator selbst, Theo de Raadt, kurze Zeit später bereits Regressionstests, um die Stabilität der Implementierung zu prüfen. Obwohl es sich um ein Draft handelt, ist das Potenzial groß, dass die Funktionalität zeitnah im stabilen OpenBSD-Kernel Einzug hält und damit viele praktische Vorteile für Anwender, Entwickler und Systemadministratoren bringt. Zusammenfassend kann festgehalten werden, dass die Neuausrichtung der openat(2)-Systemaufrufe in OpenBSD eine stärkere Fokussierung auf sichere, kontrollierte und nachvollziehbare Dateisystemzugriffe zum Ziel hat.
Die Idee, Verzeichnis-Deskriptoren per Definition zu beschränken und so ein natürliches Containment zu schaffen, schafft für den Entwickler Werkzeuge, die bislang entweder sehr kompliziert umzusetzen waren oder aufwendig administriert werden mussten. Dabei bleibt die Prozesstrennung und Performance erhalten und die Komplexität auf einem handhabbaren Level. Dieses Konzept birgt großes Potenzial für zukünftige Anwendungen, insbesondere in sicherheitskritischen Umgebungen, wo Verzeichniszugriffsrechte strikt kontrolliert werden müssen. Auch im Bereich Containerisierung und Virtualisierung könnten solche Mechanismen zur leichteren Isolation von Dateisystembereichen beitragen. OpenBSD bestätigt mit diesem Schritt einmal mehr seine Rolle als innovatives Betriebssystem, das Sicherheit und Stabilität nicht nur predigt, sondern aktiv vorantreibt.