Libseccomp: BUG: BPF für Pseudo-Systemaufrufe nicht generieren

Erstellt am 15. Juni 2020  ·  20Kommentare  ·  Quelle: seccomp/libseccomp

Siehe Ausgabe #249, insbesondere diesen Kommentar :

Warum nach nicht vorhandenem syscall 4294957285 in tatsächlich generierten bpf suchen?

Wir sollten das nicht tun, und wir haben das auch früher nicht gemacht, aber es sieht so aus, als ob die aktuelle libseccomp hier einen Fehler hat.

Danke an @vt-alt für das Melden dieses Fehlers.

bug prioritmedium

Alle 20 Kommentare

REPRODUZIERER ZU Gunsten des verbesserten Entwurfs unten entfernt

Um es klar zu sagen, wir sollten die Pseudo-Systemaufrufe im PFC zu Debugging-Zwecken immer noch ausgeben, aber wir sollten keine (nutzlose) BPF-Filterregel ausgeben.

Vielen Dank, dass Sie das Problem aus meinem Bericht erstellt haben.

Um es klar zu sagen, wir sollten die Pseudo-Systemaufrufe im PFC zu Debugging-Zwecken immer noch ausgeben, aber wir sollten keine (nutzlose) BPF-Filterregel ausgeben.

Bitte überdenken Sie dies. Ich glaube, dies wird die Dinge nur verkomplizieren und verschleiern, wenn PFC BPF nicht widerspiegelt.

Bitte überdenken Sie dies. Ich glaube, dies wird die Dinge nur verkomplizieren und verschleiern, wenn PFC BPF nicht widerspiegelt.

Wenn der Systemaufruf im PFC fehlt, erhalten wir eine Reihe von gefälschten Fehlerberichten, die darüber sprechen, dass die Bibliothek keinen Filter für (nicht vorhandene) Systemaufrufe hinzufügt.

Für diejenigen, die das Konzept der Pseudo-Systemaufrufe verstehen, ist es eine triviale Übung, sie aus der PFC-Ausgabe zu entfernen. Erwähnenswert ist auch, dass die PFC-Ausgabe keine exakte Kopie der BPF-Ausgabe sein soll, sondern lediglich als Debugging-Tool und zur einfachen Visualisierung des generierten Filtercodes dient.

einfache Möglichkeit, den generierten Filtercode zu visualisieren

Aber dann visualisiert es keinen _generierten_ Filtercode, da im generierten Code Pseudo-Systemaufrufe fehlen sollten.

Wenn der Systemaufruf im PFC fehlt, erhalten wir eine Reihe von gefälschten Fehlerberichten, die darüber sprechen, dass die Bibliothek keinen Filter für (nicht vorhandene) Systemaufrufe hinzufügt.

Es ist viel einfacher zu verstehen, dass Pseudo-Systemaufrufe im Code nicht vorhanden sein sollten (wie in 'optimized out', weil ''solche Systemaufrufe für den Bogen nicht vorhanden sind') als der logische Unterschied (Anwesenheit und Abwesenheit von Bedingungen) in die Visualisierung von Code und dem eigentlichen Code.

Ich würde es vorziehen, dass PFC bpf widerspiegelt, als scmp_bpf_disasm da die PFC-Ausgabe viel einfacher zu lesen ist.

Ich verstehe Ihre Bedenken @vt-alt, und vielleicht machen wir das in einer zukünftigen Version mit PFC, aber ich bin der Meinung, dass das Entfernen der Pseudo-Systemaufrufe aus der PFC-Ausgabe ein Fehler ist.

@drakenclimber hast du eine starke Meinung dazu?

Reproduzierer für x86_64 überarbeitet:

#include <stdlib.h>
#include <errno.h>

#include <seccomp.h>

#include "util.h"

int main(int argc, char *argv[])
{
        int rc;
        struct util_options opts;
        scmp_filter_ctx ctx = NULL;

        rc = util_getopt(argc, argv, &opts);
        if (rc < 0)
                goto out;

        ctx = seccomp_init(SCMP_ACT_KILL);
        if (ctx == NULL)
                return ENOMEM;

        rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
        if (rc < 0)
                goto out;

        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0);
        if (rc < 0)
                goto out;
        rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(arm_fadvise64_64), 0);
        if (rc < 0)
                goto out;

        rc = util_filter_output(&opts, ctx);
        if (rc)
                goto out;

out:
        seccomp_release(ctx);
        return (rc < 0 ? -rc : rc);
}

AKTUALISIERT: ein Problem mit TSKIP behoben

Noch nicht vollständig getestet, aber dies könnte eine Lösung sein - können Sie überprüfen, ob dies für den ausgewogenen Baumoptimierungsalgorithmus @drakenclimber angemessen ist?

diff --git a/src/arch-arm.c b/src/arch-arm.c
index 3465111..4dd4b63 100644
--- a/src/arch-arm.c
+++ b/src/arch-arm.c
@@ -54,7 +54,7 @@ int arm_syscall_resolve_name_munge(const char *name)
        if (sys == __NR_SCMP_ERROR)
                return sys;

-       return sys + __SCMP_NR_BASE;
+       return (sys | __SCMP_NR_BASE);
 }

 /**
@@ -68,7 +68,7 @@ int arm_syscall_resolve_name_munge(const char *name)
  */
 const char *arm_syscall_resolve_num_munge(int num)
 {
-       return arm_syscall_resolve_num(num - __SCMP_NR_BASE);
+       return arm_syscall_resolve_num(num & (~__SCMP_NR_BASE));
 }

 const struct arch_def arch_def_arm = {
diff --git a/src/arch-x32.c b/src/arch-x32.c
index 7b97fb3..3890968 100644
--- a/src/arch-x32.c
+++ b/src/arch-x32.c
@@ -43,7 +43,7 @@ int x32_syscall_resolve_name_munge(const char *name)
        if (sys == __NR_SCMP_ERROR)
                return sys;

-       return sys + X32_SYSCALL_BIT;
+       return (sys | X32_SYSCALL_BIT);
 }

 /**
@@ -57,7 +57,7 @@ int x32_syscall_resolve_name_munge(const char *name)
  */
 const char *x32_syscall_resolve_num_munge(int num)
 {
-       return x32_syscall_resolve_num(num - X32_SYSCALL_BIT);
+       return x32_syscall_resolve_num(num & (~X32_SYSCALL_BIT));
 }

 const struct arch_def arch_def_x32 = {
diff --git a/src/gen_bpf.c b/src/gen_bpf.c
index 55a7958..ae9c3f4 100644
--- a/src/gen_bpf.c
+++ b/src/gen_bpf.c
@@ -1555,6 +1555,10 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
        for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
                if (!s_iter->valid)
                        continue;
+               /* skip pseudo-syscalls */
+               if ((s_iter->num & 0x80000000) &&
+                   (state->attr->api_tskip == 0 || s_iter->num != -1))
+                       continue;

                if (*bintree_levels > 0 &&
                    ((syscall_cnt + empty_cnt) % SYSCALLS_PER_NODE) == 0)

Ich verstehe Ihre Bedenken @vt-alt, und vielleicht machen wir das in einer zukünftigen Version mit PFC, aber ich bin der Meinung, dass das Entfernen der Pseudo-Systemaufrufe aus der PFC-Ausgabe ein Fehler ist.

@drakenclimber hast du eine starke Meinung dazu?

Nicht wirklich, aber ich denke, die Wurzel des Problems liegt darin, dass die PFC-Ausgabe auf verschiedene Arten verwendet wird:

  1. Wie oben erwähnt, ist es für neue Benutzer eine einfache Möglichkeit, ihren Filter grob zu überprüfen
  2. Fortgeschrittenere Benutzer erwarten, dass es eine enge Annäherung an den tatsächlichen BPF-Filter ist

Vielleicht könnten wir der PFC-Logik ein --no-pseudo-syscalls Flag hinzufügen? Dann kann es für Anfänger gleich bleiben, aber fortgeschrittene Benutzer können den BPF besser annähern.

_AKTUALISIERT: Problem mit TSKIP behoben_

Noch nicht vollständig getestet, aber dies könnte eine Lösung sein - können Sie überprüfen, ob dies für den ausgewogenen Baumoptimierungsalgorithmus @drakenclimber angemessen ist?

Wird besorgt. Ich möchte sehen, ob ich einen automatisierten Test durchführen kann, der dieses Szenario reproduziert.

_AKTUALISIERT: Problem mit TSKIP behoben_
Noch nicht vollständig getestet, aber dies könnte eine Lösung sein - können Sie überprüfen, ob dies für den ausgewogenen Baumoptimierungsalgorithmus @drakenclimber angemessen ist?

Wird besorgt. Ich möchte sehen, ob ich einen automatisierten Test durchführen kann, der dieses Szenario reproduziert.

Und natürlich beginne ich mit dem Reproduktionstest, den Sie oben haben. Vielen Dank!

_AKTUALISIERT: Problem mit TSKIP behoben_

Noch nicht vollständig getestet, aber dies könnte eine Lösung sein - können Sie überprüfen, ob dies für den ausgewogenen Baumoptimierungsalgorithmus @drakenclimber angemessen ist?

Der Binärbaum berechnet im Voraus, wann der Akkumulator geändert werden muss, und so weiß er die jge Logik einzufügen. Das Herausziehen von Systemaufrufen (wie im obigen Vorschlag) beim Erstellen des Filters durchbricht diese Logik.

Ich habe meine Änderungen auch noch nicht vollständig getestet :), aber ich bin mir ziemlich sicher, dass wir so etwas brauchen werden, damit der Binärbaum mit der Entfernung von Pseudo-Systemaufrufen funktioniert. Ich habe damit einen BPF-Binärbaum generiert und es sieht vernünftig aus. Wenn wir uns einer produktionsreifen Lösung nähern, werde ich sie vollständig überprüfen.

@@ -1532,11 +1532,31 @@ static int _gen_bpf_syscalls(struct bpf_state *state,
                _sys_sort(db_secondary->syscalls, &s_head, &s_tail, optimize);

        if (optimize == 2) {
+               /* since pseudo-syscalls are removed from the filter, we need
+                * to calculate the syscall count by hand
+                */
+               for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
+                       if (!s_iter->valid)
+                               continue;
+
+                       /* skip pseudo-syscalls */
+                       if ((s_iter->num & 0x80000000) &&
+                           (state->attr->api_tskip == 0 || s_iter->num != -1))
+                               continue;
+
+                       syscall_cnt++;
+               }
+
                rc = _gen_bpf_init_bintree(&bintree_hashes, &bintree_syscalls,
-                                          bintree_levels, db->syscall_cnt,
+                                          bintree_levels, syscall_cnt,
                                           &empty_cnt);
                if (rc < 0)
                        goto out;
+
+               /* reset the syscall_cnt variable because later in this
+                * function it's used as a counter
+                */
+               syscall_cnt = 0;
        }

Dies könnte intelligenter/schneller gemacht werden, wenn wir eine Variable in der db Struktur haben, die die "gültige" Systemaufrufanzahl verfolgt.

Vielleicht könnten wir der PFC-Logik ein Flag --no-pseudo-syscalls hinzufügen?

Wohin würde diese Flagge gehen? Ich glaube nicht, dass wir dies als Build-Time-Option wollen. Ich nehme an, wir könnten eine Filteroption hinzufügen, aber ich bin nicht wirklich begeistert davon. Ich würde dafür stimmen, bei den Pseudo-Systemaufrufen im PFC zu bleiben, sie aber (offensichtlich) vorerst aus dem BPF zu entfernen, und wenn wir dies irgendwann in der Zukunft erweitern müssen, können wir dies tun.

Ich habe meine Änderungen auch noch nicht vollständig getestet :), aber ich bin mir ziemlich sicher, dass wir so etwas brauchen werden, damit der Binärbaum mit der Entfernung von Pseudo-Systemaufrufen funktioniert. Ich habe damit einen BPF-Binärbaum generiert und es sieht vernünftig aus. Wenn wir uns einer produktionsreifen Lösung nähern, werde ich sie vollständig überprüfen.

Ich vermutete, dass dies die Baumoptimierung brechen würde.

@drakenclimber Wenn man bedenkt, dass dies die Baumsortierung viel stärker beeinflusst als die Standardoptimierung, möchten Sie dieses Problem

Eine Sache, die wir meiner Meinung nach trotzdem tun sollten, sind die Änderungen in "arch-arm.c" und "arch-x32.c", da es sinnvoller ist.

Vielleicht könnten wir der PFC-Logik ein Flag --no-pseudo-syscalls hinzufügen?

Wohin würde diese Flagge gehen? Ich glaube nicht, dass wir dies als Build-Time-Option wollen. Ich nehme an, wir könnten eine Filteroption hinzufügen, aber ich bin nicht wirklich begeistert davon. Ich würde dafür stimmen, bei den Pseudo-Systemaufrufen im PFC zu bleiben, sie aber (offensichtlich) vorerst aus dem BPF zu entfernen, und wenn wir dies irgendwann in der Zukunft erweitern müssen, können wir dies tun.

Ich gebe zu, dass ich getippt habe, bevor ich dachte. ;)

Ja, es müsste eine Filteroption sein und das fühlt sich falsch an. Ich stimme zu; lass uns wie oben beschrieben vorgehen. Wenn wir weiterhin Fragen haben, können wir es erneut besuchen.

Ich habe meine Änderungen auch noch nicht vollständig getestet :), aber ich bin mir ziemlich sicher, dass wir so etwas brauchen werden, damit der Binärbaum mit der Entfernung von Pseudo-Systemaufrufen funktioniert. Ich habe damit einen BPF-Binärbaum generiert und es sieht vernünftig aus. Wenn wir uns einer produktionsreifen Lösung nähern, werde ich sie vollständig überprüfen.

Ich vermutete, dass dies die Baumoptimierung brechen würde.

@drakenclimber Wenn man bedenkt, dass dies die Baumsortierung viel stärker beeinflusst als die Standardoptimierung, möchten Sie dieses Problem

Eine Sache, die wir meiner Meinung nach trotzdem tun sollten, sind die Änderungen in "arch-arm.c" und "arch-x32.c", da es sinnvoller ist.

Sicher. Ich kann dieses besitzen.

@drakenclimber "> Wie oben erwähnt, ist es für neue Benutzer eine einfache Möglichkeit, ihren Filter grob zu überprüfen."

"Pseudo syscall" existiert nicht im Kernel und ist auch kein bekanntes Konzept. Es ist eine reine Erfindung von libseccomp und wird hier nicht erklärt. Nur angegeben, dass es sich um negative Zahlen handelt und sie erscheinen, wenn der angegebene Systemaufruf für die Architektur nicht existiert. Wie unterscheidet sich dies von einem nicht vorhandenen Systemaufruf? Zu welchem ​​Zweck sind sie negativ? Das Konzept des Pseudo-Systemaufrufs ist für neue Benutzer wirklich verwirrend.

Ich kann nicht glauben, dass neue Benutzer nicht vorhandene Systemaufrufe in ihren Filtern überprüfen möchten.

Lassen Sie mich noch einen Punkt hinzufügen. All dies liegt im Bereich der Sicherheit, wo nur ein sorgfältiges und detailliertes Verständnis funktioniert. Sie schaffen neue obskure Konzepte (von Pseudo-Systemaufrufen) und den Unterschied zwischen Darstellungen (bpf und pfc). Ist das wirklich für neue Benutzer gedacht, um sie noch mehr zu verwirren?

@vt-alt vielen Dank, dass Sie Ihre Bedenken geäußert haben, aber für die Version v2.5.0 werden wir die Pseudo-Systemaufrufe aus dem BPF-Filter unterdrücken und sie weiterhin im PFC-Filter anzeigen. Ich bin mir bewusst, dass Sie dieser Entscheidung möglicherweise nicht zustimmen können, aber ich bitte Sie, diese Entscheidung zu respektieren. In zukünftigen Versionen werden wir den Zweck hinter den Pseudo-Systemaufrufen (es dient der Unterstützung mehrerer ABIs) besser erklären und in den Manpages dokumentieren; Ich habe dafür ein Thema erstellt (Link unten), Sie sind willkommen und werden ermutigt, an dieser Diskussion und allen daraus resultierenden PRs teilzunehmen. Es ist auch möglich, dass wir in Zukunft unseren Ansatz zum PFC-Filter überarbeiten, aber ich möchte hier nichts versprechen.

Nochmals vielen Dank, dass Sie uns auf das BPF-Problem aufmerksam gemacht haben; Sie haben geholfen, die nächste libseccomp-Version zu verbessern!

Schließen über #264.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen