Libseccomp: BOGUE : ne génère pas de BPF pour les pseudo-syscalls

Créé le 15 juin 2020  ·  20Commentaires  ·  Source: seccomp/libseccomp

Voir le numéro #249, plus précisément ce commentaire :

Pourquoi rechercher un appel système 4294957285 inexistant dans le bpf réellement généré ?

Nous ne devrions pas, et nous n'avions pas l'habitude de le faire, mais il semble que la libseccomp actuelle ait un bogue ici.

Merci à @vt-alt pour avoir signalé ce bogue.

bug prioritmedium

Tous les 20 commentaires

REPRODUCTEUR SUPPRIMÉ EN FAVEUR D'UN PROJET AMÉLIORÉ CI-DESSOUS

Pour être clair, nous devrions toujours émettre les pseudo-appels système dans le PFC, à des fins de débogage, mais nous ne devrions pas émettre de règle de filtre BPF (inutile).

Merci d'avoir créé le problème à partir de mon rapport.

Pour être clair, nous devrions toujours émettre les pseudo-appels système dans le PFC, à des fins de débogage, mais nous ne devrions pas émettre de règle de filtre BPF (inutile).

Veuillez repenser ceci. Je pense que cela ne fera que compliquer et obscurcir les choses si PFC ne reflète pas BPF.

Veuillez repenser ceci. Je pense que cela ne fera que compliquer et obscurcir les choses si PFC ne reflète pas BPF.

Si l'appel système est absent du PFC, nous recevrons un certain nombre de faux rapports de bogues expliquant comment la bibliothèque ne parvient pas à ajouter un filtre pour les appels système (inexistants).

Pour ceux qui comprennent le concept des pseudo-appels système, c'est un exercice trivial de les supprimer de la sortie PFC. Il convient également de mentionner que la sortie PFC n'est pas destinée à être une copie exacte de la sortie BPF, elle est là simplement comme un outil de débogage et un moyen facile de visualiser le code de filtre généré.

moyen facile de visualiser le code de filtre généré

Mais, alors, il ne visualisera pas le code de filtre _généré_ puisque dans le code généré, les pseudo-appels système devraient être absents.

Si l'appel système est absent du PFC, nous recevrons un certain nombre de faux rapports de bogues expliquant comment la bibliothèque ne parvient pas à ajouter un filtre pour les appels système (inexistants).

Il est beaucoup plus facile de comprendre que les contrôles de pseudo syscall ne doivent pas être présents dans le code (comme dans 'optimized out', car ''il n'y a pas de tels syscalls pour l'arch'), que la différence logique (présence et absence de conditionnels) dans la visualisation du code et le code réel.

Je préférerais que PFC reflète bpf que d'utiliser scmp_bpf_disasm car la sortie PFC est beaucoup plus facile à lire.

Je comprends votre inquiétude @vt-alt, et peut-être que dans une future version, nous le ferons avec PFC, mais à mon avis, supprimer les pseudo-appels système de la sortie PFC est une erreur.

@drakenclimber avez-vous des opinions bien arrêtées à ce sujet ?

Reproducteur révisé pour x86_64 :

#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);
}

MISE À JOUR : correction d'un problème avec TSKIP

Pas encore entièrement testé, mais cela peut être une solution - pouvez-vous vérifier que cela est raisonnable pour l'algorithme d'optimisation d'arbre équilibré @drakenclimber ?

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)

Je comprends votre inquiétude @vt-alt, et peut-être que dans une future version, nous le ferons avec PFC, mais à mon avis, supprimer les pseudo-appels système de la sortie PFC est une erreur.

@drakenclimber avez-vous des opinions bien arrêtées à ce sujet ?

Pas vraiment, mais je pense que la racine du problème est que la sortie PFC est utilisée de plusieurs manières divergentes :

  1. Comme mentionné ci-dessus, c'est un moyen facile pour les nouveaux utilisateurs de vérifier approximativement leur filtre
  2. Les utilisateurs plus avancés s'attendent à ce qu'il s'agisse d'une approximation proche du filtre BPF réel

Peut-être pourrions-nous ajouter un indicateur --no-pseudo-syscalls à la logique PFC ? Ensuite, il peut rester le même pour les utilisateurs débutants, mais les utilisateurs avancés peuvent obtenir une meilleure approximation du BPF.

_UPDATED : correction d'un problème avec TSKIP_

Pas encore entièrement testé, mais cela peut être une solution - pouvez-vous vérifier que cela est raisonnable pour l'algorithme d'optimisation d'arbre équilibré @drakenclimber ?

Ça ira. Je veux voir si je peux faire un test automatisé qui reproduira ce scénario.

_UPDATED : correction d'un problème avec TSKIP_
Pas encore entièrement testé, mais cela peut être une solution - pouvez-vous vérifier que cela est raisonnable pour l'algorithme d'optimisation d'arbre équilibré @drakenclimber ?

Ça ira. Je veux voir si je peux faire un test automatisé qui reproduira ce scénario.

Et bien sûr, je vais commencer par le test de reproduction que vous avez ci-dessus. Merci!

_UPDATED : correction d'un problème avec TSKIP_

Pas encore entièrement testé, mais cela peut être une solution - pouvez-vous vérifier que cela est raisonnable pour l'algorithme d'optimisation d'arbre équilibré @drakenclimber ?

L'arbre binaire précalcule quand l'accumulateur doit être modifié, et c'est ainsi qu'il sait insérer la logique jge . Retirer des appels système (comme la proposition ci-dessus) pendant la construction du filtre rompt cette logique.

Je n'ai pas encore complètement testé mes modifications non plus :), mais je suis presque sûr que nous aurons besoin de quelque chose comme ça pour faire fonctionner l'arbre binaire avec la suppression des pseudo-appels système. J'ai généré un arbre binaire BPF en utilisant ceci et cela semble raisonnable. À mesure que nous nous rapprochons d'une solution prête pour la production, je la vérifierai pleinement.

@@ -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;
        }

Cela pourrait être rendu plus intelligent/plus rapide si nous avons une variable dans la structure db qui suit le nombre d'appels système "valides".

Peut-être pourrions-nous ajouter un indicateur --no-pseudo-syscalls à la logique PFC ?

Où irait ce drapeau ? Je ne pense pas que nous voulons cela comme une option de temps de construction. Je suppose que nous pourrions ajouter une option de filtre, mais je ne suis pas vraiment enthousiasmé par cela. Je voterais pour rester avec les pseudo-appels système dans le PFC mais en les supprimant du BPF (évidemment) pour l'instant, et si nous devons augmenter cela à un moment donné dans le futur, nous le pouvons.

Je n'ai pas encore complètement testé mes modifications non plus :), mais je suis presque sûr que nous aurons besoin de quelque chose comme ça pour faire fonctionner l'arbre binaire avec la suppression des pseudo-appels système. J'ai généré un arbre binaire BPF en utilisant ceci et cela semble raisonnable. À mesure que nous nous rapprochons d'une solution prête pour la production, je la vérifierai pleinement.

Je soupçonnais que cela allait casser l'optimisation de l'arbre.

@drakenclimber étant donné que cela a un impact bien plus important sur le tri des arbres que l'optimisation standard, voulez-vous résoudre ce problème ? N'hésitez pas à voler autant ou aussi peu du code que je copie et colle ci-dessus que cela a du sens.

Une chose que je pense que nous devrions faire malgré tout sont les changements dans "arch-arm.c" et "arch-x32.c" car cela a plus de sens.

Peut-être pourrions-nous ajouter un indicateur --no-pseudo-syscalls à la logique PFC ?

Où irait ce drapeau ? Je ne pense pas que nous voulons cela comme une option de temps de construction. Je suppose que nous pourrions ajouter une option de filtre, mais je ne suis pas vraiment enthousiasmé par cela. Je voterais pour rester avec les pseudo-appels système dans le PFC mais en les supprimant du BPF (évidemment) pour l'instant, et si nous devons augmenter cela à un moment donné dans le futur, nous le pouvons.

J'avoue que j'ai tapé avant de penser. ;)

Oui, il faudrait que ce soit une option de filtre et cela ne semble pas correct. Je suis d'accord; faisons comme vous l'avez décrit ci-dessus. Si nous continuons à recevoir des questions, nous pourrons y revenir.

Je n'ai pas encore complètement testé mes modifications non plus :), mais je suis presque sûr que nous aurons besoin de quelque chose comme ça pour faire fonctionner l'arbre binaire avec la suppression des pseudo-appels système. J'ai généré un arbre binaire BPF en utilisant ceci et cela semble raisonnable. À mesure que nous nous rapprochons d'une solution prête pour la production, je la vérifierai pleinement.

Je soupçonnais que cela allait casser l'optimisation de l'arbre.

@drakenclimber étant donné que cela a un impact bien plus important sur le tri des arbres que l'optimisation standard, voulez-vous résoudre ce problème ? N'hésitez pas à voler autant ou aussi peu du code que je copie et colle ci-dessus que cela a du sens.

Une chose que je pense que nous devrions faire malgré tout sont les changements dans "arch-arm.c" et "arch-x32.c" car cela a plus de sens.

Sûr. Je peux posséder celui-ci.

@drakenclimber "> Comme mentionné ci-dessus, c'est un moyen facile pour les nouveaux utilisateurs de vérifier approximativement leur filtre"

"Pseudo syscall" n'existe pas dans le noyau et ce n'est pas non plus un concept bien connu. C'est purement l'invention de libseccomp et ce n'est pas expliqué ici. Seulement indiqué qu'il s'agit de nombres négatifs et qu'ils apparaissent lorsqu'un appel système n'existe pas pour l'architecture. En quoi est-ce différent d'un appel système inexistant ? Dans quel but sont-ils négatifs ? Le concept de pseudo syscall est vraiment déroutant pour les nouveaux utilisateurs.

Je ne peux pas croire que les nouveaux (plus) utilisateurs veuillent voir les appels système inexistants vérifiés dans leurs filtres.

Permettez-moi d'ajouter un point de plus. Tout cela dans le domaine de la sécurité, où seule une compréhension minutieuse et détaillée fonctionne. Vous créez de nouveaux concepts obscurs (de pseudo syscalls) et la différence entre les représentations (bpf et pfc). Est-ce vraiment destiné aux nouveaux utilisateurs, pour les embrouiller davantage ?

@vt-alt merci d'avoir exprimé votre inquiétude, mais pour la version 2.5.0, nous allons supprimer les pseudo-appels système du filtre BPF et continuer à les afficher dans le filtre PFC. Je reconnais que vous pouvez être en désaccord avec cette décision mais je vous prie de bien vouloir respecter cette décision. Dans les versions futures, nous ferons un meilleur travail en expliquant le but derrière les pseudo-appels système (c'est pour la prise en charge de plusieurs ABI) et en le documentant dans les pages de manuel ; J'ai créé un problème pour cela (lien ci-dessous), vous êtes les bienvenus et encouragés à participer à cette discussion et à tout PR qui en résulte. Il est également possible que nous révisions notre approche du filtre PFC à l'avenir, mais je ne veux rien promettre ici.

Encore une fois, merci d'avoir attiré notre attention sur le problème BPF; vous avez aidé à améliorer la prochaine version de libseccomp !

Fermeture via #264.

Cette page vous a été utile?
0 / 5 - 0 notes