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.
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
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,
Hilfreichster Kommentar
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 (sieheseccomp_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.