Libseccomp: F: Es können keine unterschiedlichen Filter mit SCMP_ACT_NOTIFY in verschiedenen Threads verwendet werden

Erstellt am 6. Nov. 2020  ·  9Kommentare  ·  Quelle: seccomp/libseccomp

libseccomp speichert die Benachrichtigung fd in einer globalen Variablen: state.notify_fd . Dies macht es unmöglich, libseccomp für eine Multithread-Anwendung mit verschiedenen Filtern in verschiedenen Threads (dh ohne Verwendung von TSYNC) zu verwenden.

libseccomp hat seccomp_reset(NULL, ...) um die globale Variable state.notify_fd . Aber seccomp_reset() hat die unglückliche Konsequenz, state.nr_seccomp = -1 .

Dieses Problem wurde beim Versuch festgestellt, Unit-Tests in libseccomp-golang aufzulösen, siehe https://github.com/seccomp/libseccomp-golang/pull/59#issuecomment -723045033

cc @yvesf @rata

prioritlow question

Hilfreichster Kommentar

Es hört sich so an, als ob wir uns hier alle einig sind, also werde ich dieses Thema schließen. @alban Wenn Sie der Meinung sind, dass wir etwas Wichtiges vermissen, Ordnung bringen können.

Danke an alle.

Alle 9 Kommentare

@drakenclimber hält die kommenden v2.5.1-Releases zurück, bis wir diesbezüglich eine Klärung erhalten. Ich bin mir nicht sicher, ob ich den Originalbericht noch vollständig verstanden habe, aber da v2.5.1 die erste Version ist, die das seccomp_reset(NULL, ...) Konzept implementiert, warten wir einen Moment, bis wir die Dinge überprüfen können ...

Wenn wir dies dem v2.5.1-Meilenstein nur als Blocker für jetzt hinzufügen, kann sich dies ändern, wenn wir die Dinge untersuchen.

@drakenclimber hält die kommenden v2.5.1-Releases zurück, bis wir diesbezüglich eine Klärung erhalten. Ich bin mir nicht sicher, ob ich den Originalbericht noch vollständig verstanden habe, aber da v2.5.1 die erste Version ist, die das seccomp_reset(NULL, ...) Konzept implementiert, warten wir einen Moment, bis wir die Dinge überprüfen können ...

Vereinbart. Wird besorgt.

libseccomp speichert die Benachrichtigung fd in einer globalen Variablen: state.notify_fd . Dies macht es unmöglich, libseccomp für eine Multithread-Anwendung mit verschiedenen Filtern in verschiedenen Threads (dh ohne Verwendung von TSYNC) zu verwenden.

Können Sie den letzten Satz etwas näher ausführen? Ich bin mir nicht sicher, ob ich verstehe, was Sie zu vermitteln versuchen.

FWIW, die seccomp-Benachrichtigung FD ist ein prozessglobales Objekt, Sie können es nur einmal vom Kernel anfordern. Sie können https://github.com/seccomp/libseccomp/issues/273 lesen, um weitere Hintergrundinformationen zu diesem Problem zu erhalten.

libseccomp hat seccomp_reset(NULL, ...) um die globale Variable state.notify_fd . Aber seccomp_reset() hat die unglückliche Konsequenz, state.nr_seccomp = -1 .

Warum ist das Zurücksetzen von state.nr_seccomp = -1 ein erhebliches Problem? Wenn das Feld nr_seccomp auf -1 wird, wenn das nächste Mal eine Operation angefordert wird, die seccomp(2) verwenden könnte, prüft die Bibliothek, ob seccomp(2) unterstützt wird und verwendet es, wenn es verfügbar ist. Ja, dies könnte zu zusätzlichen Aufrufen von seccomp(2) aber das sollte kein großes Problem darstellen. Ist dies ein Problem für Ihren Anwendungsfall?

@alban - Ähnliche Frage von mir. Ich habe ein wenig Zeit damit verbracht, einen sinnvollen Anwendungsfall für Multi-Threaded, Multi-Seccomp-Filter (in C) zu erfinden, und konnte wirklich nichts finden.

Ich habe die Go-Dokumentation von os.LockOSThread() gelesen und es macht für mich Sinn. Aber ich habe Mühe, dieses Wissen in eine Multithread-, Multi-Seccomp-Filter-Lösung umzuwandeln.

Könnten Sie einen Pseudo-Code oder ein High-Level-Design Ihrer Gedanken teilen? Ich würde es dann gerne in C prototypisieren.

Können Sie den letzten Satz etwas näher ausführen? Ich bin mir nicht sicher, ob ich verstehe, was Sie zu vermitteln versuchen.

Während der Arbeit an den Unit-Tests in libseccomp-golang stellte ich fest, dass das folgende Szenario getestet wurde:

  1. Bei einer ersten Ausführung des Komponententests wurde eine seccomp-Richtlinie ohne SECCOMP_FILTER_FLAG_TSYNC angewendet (d.h. sie wird auf Thread-Ebene und nicht auf Prozessebene angewendet), sondern mit SECCOMP_FILTER_FLAG_NEW_LISTENER (also speichert libseccomp die fd in state.notify_fd ).
  2. Der gleiche Komponententest wird im gleichen Prozess, aber in einem anderen Thread erneut ausgeführt (mit runtime.LockOSThread in Go, um dies sicherzustellen). Aber libseccomp verwendet den fd des vorherigen seccomp-Filters (von state.notify_fd ) wieder, anstatt einen neuen fd für den neuen Filter zu erhalten. Dann schlägt der Test fehl, weil wir erwarten, die Ereignisse auf dem falschen seccomp fd zu empfangen.

FWIW, die seccomp-Benachrichtigung FD ist ein prozessglobales Objekt, Sie können es nur einmal vom Kernel anfordern. Sie können #273 lesen, um mehr Hintergrundinformationen zu diesem Thema zu erhalten.

Soweit ich verstanden habe, beschränkt uns der Kernel darauf, nur eine seccomp-Benachrichtigung FD in einem Filterbaum zu erhalten. Aber im obigen Szenario verwenden die beiden Threads desselben Prozesses unterschiedliche Filterbäume, sodass dies aus der Kernel-Perspektive in Ordnung sein sollte.

Dieses Szenario, in dem verschiedene Filterbäume mit SECCOMP_FILTER_FLAG_NEW_LISTENER wurde nicht absichtlich erstellt, sondern entstand nur als Folge der libseccomp-golang-Unit-Tests, die im selben Prozess ausgeführt wurden. Aber da die Hauptursache darin besteht, dass libseccomp eine globale Variable state.notify_fd , die von Threads gemeinsam genutzt wird, dachte ich, ich sollte diesen Fehler hier öffnen, um die Diskussion zu eröffnen. Es wäre jedoch in Ordnung, wenn dies als "WONTFIX" geschlossen wird (ich weiß nicht, ob andere libseccomp-Benutzer Unterstützung für diese Art von Szenario benötigen). In diesem Fall können wir die libseccomp-golang-Komponententests einfach anders schreiben (dh mit einem separaten Prozess für jede Testiteration); wir müssten das sowieso tun (um zu vermeiden, dass Thread-Level-Filter und Prozess-Level-Filter vermischt werden - das würde vom Kernel abgelehnt).

Während der Arbeit an den Unit-Tests in libseccomp-golang stellte ich fest, dass das folgende Szenario getestet wurde:

  1. Bei einer ersten Ausführung des Komponententests wurde eine seccomp-Richtlinie ohne SECCOMP_FILTER_FLAG_TSYNC angewendet (d.h. sie wird auf Thread-Ebene und nicht auf Prozessebene angewendet), sondern mit SECCOMP_FILTER_FLAG_NEW_LISTENER (also speichert libseccomp die fd in state.notify_fd ).
  2. Der gleiche Komponententest wird im gleichen Prozess, aber in einem anderen Thread erneut ausgeführt (mit runtime.LockOSThread in Go, um dies sicherzustellen). Aber libseccomp verwendet den fd des vorherigen seccomp-Filters (von state.notify_fd ) wieder, anstatt einen neuen fd für den neuen Filter zu erhalten. Dann schlägt der Test fehl, weil wir erwarten, die Ereignisse auf dem falschen seccomp fd zu empfangen.

Ah ha, das macht jetzt mehr Sinn. Ich habe mich oft gefragt, ob wir TSYNC zum Standard für die libseccomp-golang-Bindungen machen sollten; Angesichts der Mehrdeutigkeit des Threads in Go scheint es eine viel sicherere Wahl zu sein.

Soweit ich verstanden habe, beschränkt uns der Kernel darauf, nur eine seccomp-Benachrichtigung FD in einem Filterbaum zu erhalten. Aber im obigen Szenario verwenden die beiden Threads desselben Prozesses unterschiedliche Filterbäume, sodass dies aus der Kernel-Perspektive in Ordnung sein sollte.

Dieses Szenario, in dem verschiedene Filterbäume mit SECCOMP_FILTER_FLAG_NEW_LISTENER wurde nicht absichtlich erstellt, sondern entstand nur als Folge der libseccomp-golang-Unit-Tests, die im selben Prozess ausgeführt wurden. Aber da die Hauptursache darin besteht, dass libseccomp eine globale Variable state.notify_fd , die von Threads gemeinsam genutzt wird, dachte ich, ich sollte diesen Fehler hier öffnen, um die Diskussion zu eröffnen. Es wäre jedoch in Ordnung, wenn dies als "WONTFIX" geschlossen wird (ich weiß nicht, ob andere libseccomp-Benutzer Unterstützung für diese Art von Szenario benötigen). In diesem Fall können wir die libseccomp-golang-Komponententests einfach anders schreiben (dh mit einem separaten Prozess für jede Testiteration); wir müssten das sowieso tun (um zu vermeiden, dass Thread-Level-Filter und Prozess-Level-Filter vermischt werden - das würde vom Kernel abgelehnt).

Ich bin daran interessiert, die Meinung von @drakenclimber dazu zu

Um dies in libseccomp zu "korrigieren", müssten wir den libseccomp-Thread bewusst machen, der mit einer Reihe von Herausforderungen und Fallstricken einhergeht, so dass ich derzeit der Meinung bin, dass dies eine schlechte Idee wäre. Wenn wir jedoch den libseccomp-Thread bewusst machen, könnten wir aus Gründen der Argumentation auch den internen globalen Zustand zu einem Thread-spezifischen Zustand und/oder möglicherweise zu einem Filterbaum-spezifischen Zustand machen; In beiden Fällen denke ich, dass die aktuelle API (einschließlich der seccomp_reset(NULL, ...) ) immer noch vernünftig wäre, daher bin ich versucht, die Dinge mit der API so zu belassen, wie sie sind. Wenn jemand diesbezüglich Bedenken hat, lassen Sie es uns bitte bald wissen.

@drakenclimber? Abgesehen von irgendwelchen Einwänden gegen das oben Gesagte denke ich, dass wir wieder bei der Version 2.5.1 sind.

Ich bin daran interessiert, die Meinung von @drakenclimber dazu zu

Ich stimme zu. Ich habe einige Zeit damit verbracht, das ursprüngliche Patchset und die Kommentare von @tych0 sowie den

Vor diesem Hintergrund habe ich versucht, einen Multithread-Einzelprozess-Anwendungsfall mit mehreren Benachrichtigungsaufrufern und -handlern zu entwickeln. Ehrlich gesagt, konnte ich mir ein solches Szenario nicht zusammenhängend ausdenken. Da dies ein ziemlich konstruierter Anwendungsfall ist und ich keinen realistischen Anwendungsfall herausfinden kann, sollten wir diesen WONTFIX markieren.

Abgesehen davon konnte ich den Kernel dazu bringen, mehrere Benachrichtigungs-fds an einen Prozess zurückzugeben. Indem ich mehrere Pthreads erstellte und sie alle sofort einen seccomp-Filter mit einer Benachrichtigungsaktion laden ließ, konnte ich gelegentlich zwei oder drei verschiedene Benachrichtigungs-FDs an den User-Space-Prozess zurückgeben. Da dies so unrealistisch ist, würde ich dazu neigen, dieses Kernelproblem ebenfalls als WONTFIX zu markieren.

@drakenclimber? Abgesehen von irgendwelchen Einwänden gegen das oben Gesagte denke ich, dass wir wieder bei der Version 2.5.1 sind.

Groß. Anfang nächster Woche sollte ich mit der Arbeit beginnen können.

Es hört sich so an, als ob wir uns hier alle einig sind, also werde ich dieses Thema schließen. @alban Wenn Sie der Meinung sind, dass wir etwas Wichtiges vermissen, Ordnung bringen können.

Danke an alle.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

pcmoore picture pcmoore  ·  23Kommentare

pcmoore picture pcmoore  ·  20Kommentare

drakenclimber picture drakenclimber  ·  18Kommentare

drakenclimber picture drakenclimber  ·  10Kommentare

grubeli picture grubeli  ·  3Kommentare