Häufig gestellte Fragen

Kann ich Threads verwenden?

Ja, Threads werden in Sandbox2 unterstützt.

Alle Threads müssen in einer Sandbox ausgeführt werden

Aufgrund der Funktionsweise von Linux wird die seccomp-bpf-Richtlinie nur auf den aktuellen Thread angewendet. Das bedeutet, dass die Richtlinie nicht auf andere vorhandene Threads angewendet wird, zukünftige Threads sie jedoch übernehmen:

  • Wenn Sie Sandbox2 im ersten Modus verwenden, in dem die Sandbox vor execve() aktiviert wird, übernehmen alle Threads die Richtlinie und es gibt kein Problem. Dies ist der bevorzugte Modus für die Sandbox.
  • Wenn Sie den zweiten Modus verwenden, in dem der Executor set_enable_sandbox_before_exec(false) hat und der Sandboxee dem Executor mitteilt, wann er mit SandboxMeHere() in einer Sandbox ausgeführt werden soll, muss der Filter auf alle Threads angewendet werden. Andernfalls besteht das Risiko, dass die Sandbox verlassen wird: Schädlicher Code kann von einem Thread in einer Sandbox zu einem Thread außerhalb der Sandbox migrieren.

Wie sollte ich meinen Sandboxee kompilieren?

Im Vergleich zu einer statisch verknüpften ausführbaren Datei führt das Kompilieren des Sandboxee zu einer dynamisch verknüpften ausführbaren Datei zu einer erheblichen Zunahme der Systemaufrufe (z.B. open/openat, mmap, usw.), die auf die Zulassungsliste gesetzt werden müssen. Alle diese zusätzlichen Systemaufrufe sind aufgrund des dynamischen Linker-Aufrufs zur Laufzeit erforderlich, um die freigegebenen Bibliotheken zu laden.

Bei statisch verknüpften Sandboxees müssen zwar weniger Systemaufrufe auf die Zulassungsliste gesetzt werden, es gibt aber auch Sicherheitsrisiken. Die ASLR-Heap-Entropie wird von 30 auf 8 Bit reduziert, was Exploits erleichtert.

Dies ist ein Dilemma, das sich im Wesentlichen auf Folgendes reduzieren lässt:

  • Dynamisch: Gute Heap-ASLR, potenziell schwieriger, die anfängliche Code ausführung zu erreichen, aber mit einer weniger effektiven Sandbox-Richtlinie, aus der es potenziell einfacher ist, auszubrechen.
  • Statisch: Schlechte Heap-ASLR, potenziell einfacher, die anfängliche Code-Ausführung zu erreichen, aber eine effektivere Sandbox-Richtlinie, aus der es potenziell schwieriger ist, auszubrechen.

In der Vergangenheit unterstützten statisch verknüpfte Binärdateien keinen positionsunabhängigen Code (pie). Außerdem hat Bazel pie standardmäßig hinzugefügt. Um einen strengen Systemaufruffilter zu definieren, mussten Sie den Standardwert von Bazel überschreiben.

Compiler haben sich im Laufe der Jahre verbessert und unterstützen jetzt die Option static-pie. Mit dieser Option wird ein Compiler angewiesen, positionsunabhängigen Code zu generieren. Im Vergleich zu pie umfasst dies jetzt auch alle statisch verknüpften Bibliotheken. Aus Sicherheitssicht reduziert static-pie die ASLR Entropie immer noch (von 30 auf 14 Bit), aber das ist eine Verbesserung gegenüber der vorherigen Situation ohne pie.

Da Bazel pie standardmäßig hinzufügt und „static“ damit nicht kompatibel ist, können Sie das Linker-Optionen-Flag verwenden, um das -static-pie Linker-Flag an die cc_binary Regel zu übergeben und den Standardwert zu überschreiben:

  linkstatic = 1,
  linkopts=["-static-pie"],

Ein Beispiel für diese Optionen finden Sie im statischen Beispiel BUILD: static_bin.cc ist statisch mit static-pie verknüpft, was eine sehr strenge Systemaufrufrichtlinie ermöglicht. Dies funktioniert auch gut für die Sandbox von Binärdateien von Drittanbietern.

Kann ich 32-Bit-x86-Binärdateien in einer Sandbox ausführen?

Sandbox2 kann nur die gleiche Architektur in einer Sandbox ausführen, mit der es kompiliert wurde.

Außerdem wurde die Unterstützung für 32-Bit-x86 aus Sandbox2 entfernt. Wenn Sie versuchen, mit einem 64-Bit-x86-Executor eine 32-Bit-x86-Binärdatei oder eine 64-Bit-x86-Binärdatei mit 32-Bit-Systemaufrufen (über int 0x80) in einer Sandbox auszuführen, wird in beiden Fällen ein Sandbox-Verstoß generiert, der durch das Architekturlabel [X86-32] identifiziert werden kann.

Der Grund für dieses Verhalten ist, dass sich die Systemaufrufnummern zwischen den Architekturen unterscheiden. Da die Systemaufrufrichtlinie in der Architektur des Executors geschrieben ist, wäre es gefährlich, eine andere Architektur für den Sandboxee zuzulassen. Tatsächlich könnte dies dazu führen, dass ein scheinbar harmloser Systemaufruf zugelassen wird, der in Wirklichkeit einen anderen, schädlicheren Systemaufruf bedeutet, der die Sandbox für einen Ausbruch öffnen könnte.

Gibt es Beschränkungen für die Anzahl der Sandboxes, die ein Executor-Prozess anfordern kann?

Für jede Sandboxee-Instanz (neuer Prozess, der vom Forkserver abgeleitet wurde) wird ein neuer Thread erstellt. Hier liegt die Beschränkung.

Kann ein Executor die Erstellung von mehr als einer Sandbox anfordern?

Nein. Es gibt eine 1:1-Beziehung. Eine Executor-Instanz speichert die PID des Sandboxee, verwaltet die Comms-Instanz zur Sandbox-Instanz usw.

Warum erhalte ich „Function not implemented“ in forkserver.cc?

Sandbox2 kann nur auf relativ neuen Kernels ausgeführt werden. Derzeit ist der Kernel 3.19 die Mindestanforderung, das kann sich aber in Zukunft ändern. Der Grund dafür ist, dass wir relativ neue Kernel-Funktionen verwenden, darunter User-Namespaces und seccomp mit dem TSYNC-Flag.

Wenn Sie in der Produktion arbeiten, sollte das kein Problem sein, da fast die gesamte Flotte einen ausreichend neuen Kernel verwendet. Wenn Sie Probleme damit haben, wenden Sie sich bitte an uns.

Wenn Sie Debian oder Ubuntu verwenden, können Sie Ihren Kernel ganz einfach aktualisieren:

sudo apt-get install linux-image-<RECENT_VERSION>