Libseccomp: RFE: Erweiterung der SCMP_FLTATR_API_SYSRAWRC-Unterstützung auf die Benachrichtigungs-API

Erstellt am 13. Nov. 2020  ·  5Kommentare  ·  Quelle: seccomp/libseccomp

Die Implementierung von seccomp_notify_receive() verwendet nur:

        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_RECV, req) < 0)
                return -ECANCELED;

Unabhängig vom Fehler in errno wird -ECANCELED zurückgegeben.

Beim Debuggen mit strace habe ich herausgefunden, dass das ioctl wegen des Signals SIGURG EINTR zurückgegeben hat:

1448850 ioctl(7, SECCOMP_IOCTL_NOTIF_RECV <unfinished ...>
1448230 getpid()                        = 1448217
1448230 tgkill(1448217, 1448850, SIGURG) = 0
1448850 <... ioctl resumed>, 0x7fc65d49ecd0) = -1 EINTR (Interrupted system call)

Das Signal SIGURL wird von der Golang-Laufzeit generiert, siehe Details in https://go-review.googlesource.com/c/go/+/232862/
Laut diesem Bericht sollte der Systemaufruf nur erneut ausgegeben werden, wenn EINTR abgerufen wird.
Idealerweise sollte sich libseccomp darum kümmern, damit es für Benutzer transparent ist.

Als Problemumgehung habe ich versucht, den Systemaufruf erneut auszugeben, indem ich seccomp_notify_receive() in meinem Programm aufrief, und dasselbe in seccomp_notify_respond() zu tun, da es dasselbe Muster hat:

        if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0)
                return -ECANCELED;

Aber manchmal bekomme ich den Rückgabewert errno = ENOENT:

1497880 ioctl(12, SECCOMP_IOCTL_NOTIF_SEND, 0x7f718fd28e10) = -1 ENOENT (No such file or directory)

libseccomp erlaubt mir nicht, zwischen ENOENT (der Zielprozess wurde kurz vor dem Aufruf SECCOMP_IOCTL_NOTIF_SEND unterbrochen) und EINTR (der seccomp-Agent wurde durch das SIGURG-Signal unterbrochen) zu unterscheiden.

Außerdem kann ich errno nicht von Golang lesen, daher kann ich keine Problemumgehung haben.

enhancement prioritmedium

Hilfreichster Kommentar

Aber die neuen Funktionen ... verwenden _rc_filter() und nicht _rc_filter_sys() ...

Ah ... tut mir leid. Tatsächlich geht es tiefer als die API-Ebene, schauen Sie in "system.c" und Sie werden sehen, dass die libseccomp-Aufrufe auf Systemebene diese nicht bis zu den Funktionen auf API-Ebene weitergeben. Wenn wir uns die Manpages ansehen, scheinen wir keine Behauptungen über SCMP_FLTATR_API_SYSRAWRC für die Benachrichtigungs-API aufzustellen (siehe seccomp_load(3) für ein Gegenbeispiel).

Ich werde dies als RFE erneut öffnen, da wir derzeit keine Behauptungen über diese Funktion aufstellen.

@drakenclimber Ich denke, das ist Material von v2.6.x (möglicherweise v2.5.2), da ich die Version von v2.5.1 nicht verlangsamen möchte. Wenn Sie anderer Meinung sind, lassen Sie es mich wissen.

Alle 5 Kommentare

Hallo @Alban.

Sehen Sie sich SCMP_FLTATR_API_SYSRAWRC in der seccomp_attr_set(3) -Manpage an:

Ein Flag, um anzugeben, ob libseccomp anstelle des Standardwerts -ECANCELED Systemfehlercodes an den Aufrufer zurückgeben soll. Standardmäßig aus (Wert == 0).

Wir erzwingen in diesem Fall -ECANCELED , um eine stabile Rückgabecodezusage in der libseccomp-API über verschiedene Kernel-/libc-Versionen hinweg sicherzustellen. Wir bieten SCMP_FLTATR_API_SYSRAWRC für Aufrufer an, die immer noch den tatsächlichen Kernel/libc-Rückgabecode sehen möchten, seien Sie jedoch gewarnt, dass wir keinen stabilen Rückgabecode garantieren, wenn Sie dieses Attribut aktivieren.

Ich werde dieses Thema als NOTABUG schließen, aber zögern Sie nicht, dies hier weiter zu diskutieren, wenn Sie weitere Fragen haben. Wir können wieder öffnen, wenn es so aussieht, als gäbe es ein echtes Problem, das angegangen werden muss.

Hallo @pcmoore , danke für die schnelle Antwort.

Wir bieten SCMP_FLTATR_API_SYSRAWRC für Aufrufer an, die dennoch den tatsächlichen Kernel/libc-Rückgabecode sehen möchten

Aber die neuen Funktionen

  • seccomp_notify_receive
  • seccomp_notify_respond
  • seccomp_notify_id_valid

verwenden _rc_filter() und nicht _rc_filter_sys() , also sollte SCMP_FLTATR_API_SYSRAWRC keinen Effekt haben, wenn ich mich nicht irre.

Aber die neuen Funktionen ... verwenden _rc_filter() und nicht _rc_filter_sys() ...

Ah ... tut mir leid. Tatsächlich geht es tiefer als die API-Ebene, schauen Sie in "system.c" und Sie werden sehen, dass die libseccomp-Aufrufe auf Systemebene diese nicht bis zu den Funktionen auf API-Ebene weitergeben. Wenn wir uns die Manpages ansehen, scheinen wir keine Behauptungen über SCMP_FLTATR_API_SYSRAWRC für die Benachrichtigungs-API aufzustellen (siehe seccomp_load(3) für ein Gegenbeispiel).

Ich werde dies als RFE erneut öffnen, da wir derzeit keine Behauptungen über diese Funktion aufstellen.

@drakenclimber Ich denke, das ist Material von v2.6.x (möglicherweise v2.5.2), da ich die Version von v2.5.1 nicht verlangsamen möchte. Wenn Sie anderer Meinung sind, lassen Sie es mich wissen.

Danke!

Für die Aufzeichnung habe ich die Problemumgehung auf der Golang-Seite gefunden, um ENOENT und EINTR mit diesem Codemuster unterscheiden zu können:

-   if retCode := C.seccomp_notify_respond(C.int(fd), resp); retCode != 0 {
-       return errRc(retCode)
+   for {
+       retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
+       if errno == syscall.EINTR {
+           continue
+       }
+       if errno == syscall.ENOENT {
+           return errno
+       }
+       if retCode != 0 {
+           return errRc(retCode)
+       }
+       break
    }

Damit scheint es mit libseccomp-2.5.0 gut zu funktionieren,

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen