Projekt zur Portierung des Pledge-Isolationsmechanismus auf Linux

Der Autor der Cosmopolitan-Standard-C-Bibliothek und der Redbean-Plattform hat die Implementierung des pledge()-Isolationsmechanismus für Linux angekündigt. Pledge wurde ursprünglich vom OpenBSD-Projekt entwickelt und ermöglicht es Ihnen, Anwendungen selektiv den Zugriff auf nicht verwendete Systemaufrufe zu verbieten (für die Anwendung wird eine Art weiße Liste von Systemaufrufen erstellt, andere Aufrufe sind verboten). Im Gegensatz zu den in Linux verfügbaren Systemaufrufbeschränkungsmechanismen wie seccomp war der Pledge-Mechanismus ursprünglich so einfach wie möglich konzipiert.

Die gescheiterte Initiative, Anwendungen in der OpenBSD-Basisumgebung mithilfe des Systrace-Mechanismus zu isolieren, zeigte, dass die Isolierung auf der Ebene einzelner Systemaufrufe zu komplex und zeitaufwändig war. Als Alternative wurde ein Pledge vorgeschlagen, das es ermöglichte, Isolationsregeln zu erstellen, ohne auf Details einzugehen und vorgefertigte Zugriffsklassen zu manipulieren. Die angebotenen Klassen sind beispielsweise stdio (Eingabe/Ausgabe), rpath (schreibgeschützte Dateien), wpath (Dateien schreiben), cpath (Dateien erstellen), tmppath (mit temporären Dateien arbeiten), inet (Netzwerk-Sockets), unix ( Unix-Sockets), dns (DNS-Auflösung), getpw (Lesezugriff auf die Benutzerdatenbank), ioctl (ioctl-Aufruf), proc (Prozessverwaltung), exec (Prozessstart) und id (Zugriffsrechteverwaltung).

Regeln für die Arbeit mit Systemaufrufen werden in Form von Anmerkungen angegeben, einschließlich einer Liste zulässiger Klassen von Systemaufrufen und einer Reihe von Dateipfaden, auf die zugegriffen werden darf. Nach dem Erstellen und Starten der geänderten Anwendung übernimmt der Kernel die Überwachung der Einhaltung der festgelegten Regeln.

Für FreeBSD wird eine separate Implementierung von Pledge entwickelt, die sich durch die Fähigkeit auszeichnet, Anwendungen zu isolieren, ohne Änderungen an ihrem Code vorzunehmen, während in OpenBSD der Pledge-Aufruf auf eine enge Integration mit der Basisumgebung und das Hinzufügen von Anmerkungen zum Code jeder einzelnen Anwendung abzielt Anwendung.

Die Entwickler des Pledge-Ports für Linux haben sich FreeBSD zum Vorbild genommen und, anstatt Änderungen am Code vorzunehmen, ein Add-on-Dienstprogramm pledge.com vorbereitet, mit dem Sie Einschränkungen anwenden können, ohne den Anwendungscode zu ändern. Um beispielsweise das Curl-Dienstprogramm nur mit Zugriff auf die Systemaufrufklassen stdio, rpath, inet und threadstdio auszuführen, führen Sie einfach „./pledge.com -p ‚stdio rpath inet thread‘ curl http://example.com“ aus.

Das Pledge-Dienstprogramm funktioniert auf allen Linux-Distributionen ab RHEL6 und erfordert keinen Root-Zugriff. Darüber hinaus wird auf Basis der Cosmopolitan-Bibliothek eine API zur Verwaltung von Einschränkungen im Programmcode in der Sprache C bereitgestellt, die es unter anderem ermöglicht, Enklaven zur gezielten Zugriffsbeschränkung in Bezug auf bestimmte Anwendungsfunktionen zu erstellen.

Die Implementierung erfordert keine Änderungen am Kernel – Versprechenseinschränkungen werden in SECCOMP-BPF-Regeln übersetzt und mithilfe des nativen Linux-Systemaufrufisolationsmechanismus verarbeitet. Beispielsweise wird der Aufruf pledge("stdio rpath", 0) in einen BPF-Filter static const struct sock_filter kFilter[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall, 0, 14 - 1) konvertiert ), / * L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), /* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 4 - 3, 0), /* L3* / BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 10, 0, 13 - 4), /* L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), /* L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~0x80800), /* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 8 - 7, 0), /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 0, 13 - 8) , /* L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), /* L9*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 12 - 10, 0), /*L10*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 12 - 11, 0), /*L11*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 17, 0, 13 - 11), /*L12*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), /*L13*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L14*/ /* nächster Filter */ };

Source: opennet.ru

Kommentar hinzufügen