Libseccomp: Q : impossible d'avoir différents filtres avec SCMP_ACT_NOTIFY dans différents threads

Créé le 6 nov. 2020  ·  9Commentaires  ·  Source: seccomp/libseccomp

libseccomp stocke la notification fd dans une variable globale : state.notify_fd . Cela rend impossible l'utilisation de libseccomp pour une application multi-thread avec différents filtres dans différents threads (c'est-à-dire sans utiliser TSYNC).

libseccomp a seccomp_reset(NULL, ...) pour réinitialiser la variable globale state.notify_fd . Mais seccomp_reset() a la fâcheuse conséquence de réinitialiser state.nr_seccomp = -1 .

Ce problème a été remarqué lors de la tentative de résolution des tests unitaires dans libseccomp-golang, voir https://github.com/seccomp/libseccomp-golang/pull/59#issuecomment-723045033

cc @yvesf @rata

prioritlow question

Commentaire le plus utile

Il semble que nous soyons tous d'accord ici, donc je vais clore ce sujet. @alban si vous pensez qu'il nous manque quelque chose d'important, veuillez nous en informer et/ou rouvrir ce problème afin que nous puissions tout régler.

Merci tout le monde.

Tous les 9 commentaires

@drakenclimber conserve les prochaines versions v2.5.1 jusqu'à ce que nous obtenions des éclaircissements à ce sujet. Je ne suis pas sûr de bien comprendre encore le rapport original, mais puisque la v2.5.1 est la première version à implémenter le concept seccomp_reset(NULL, ...) , attendons juste une minute jusqu'à ce que nous puissions vérifier les choses ...

En ajoutant cela au jalon v2.5.1 simplement en tant que bloqueur pour le moment, cela peut changer au fur et à mesure que nous enquêtons sur les choses.

@drakenclimber conserve les prochaines versions v2.5.1 jusqu'à ce que nous obtenions des éclaircissements à ce sujet. Je ne suis pas sûr de bien comprendre encore le rapport original, mais puisque la v2.5.1 est la première version à implémenter le concept seccomp_reset(NULL, ...) , attendons juste une minute jusqu'à ce que nous puissions vérifier les choses ...

D'accord. Ça ira.

libseccomp stocke la notification fd dans une variable globale : state.notify_fd . Cela rend impossible l'utilisation de libseccomp pour une application multi-thread avec différents filtres dans différents threads (c'est-à-dire sans utiliser TSYNC).

Pouvez-vous développer un peu plus cette dernière phrase? Je ne suis pas sûr de comprendre ce que vous essayez de transmettre.

FWIW, la notification seccomp FD est un objet global de processus, vous ne pouvez le demander au noyau qu'une seule fois. Vous pouvez lire https://github.com/seccomp/libseccomp/issues/273 pour obtenir plus d'informations sur le problème.

libseccomp a seccomp_reset(NULL, ...) pour réinitialiser la variable globale state.notify_fd . Mais seccomp_reset() a la fâcheuse conséquence de réinitialiser state.nr_seccomp = -1 .

Pourquoi la réinitialisation de state.nr_seccomp = -1 un problème important ? Si le champ nr_seccomp est réinitialisé à -1 la prochaine fois qu'une opération est demandée qui pourrait utiliser seccomp(2) la bibliothèque vérifie si seccomp(2) est pris en charge et l'utilise s'il est disponible. Oui, cela pourrait entraîner des appels supplémentaires à seccomp(2) mais cela ne devrait pas être un problème majeur, est-ce une préoccupation pour votre cas d'utilisation ?

@alban - Question similaire de ma part. J'ai passé un peu de temps à essayer d'inventer un cas d'utilisation de filtre multi-thread et multi-seccomp (en C) et je n'ai vraiment rien pu trouver.

J'ai lu la documentation Go de os.LockOSThread() , et cela me semble logique. Mais j'ai du mal à convertir ces connaissances en une solution de filtre multi-thread et multi-seccomp.

Pourriez-vous partager un pseudo-code ou une conception de haut niveau de ce que vous pensez ? Je serais heureux de le prototyper en C alors.

Pouvez-vous développer un peu plus cette dernière phrase? Je ne suis pas sûr de comprendre ce que vous essayez de transmettre.

En travaillant sur les tests unitaires dans libseccomp-golang, j'ai réalisé que le scénario suivant était en cours de test :

  1. Dans une première exécution du test unitaire, une politique seccomp a été appliquée sans SECCOMP_FILTER_FLAG_TSYNC (c'est-à-dire qu'elle est appliquée au niveau du thread et non au niveau du processus) mais avec SECCOMP_FILTER_FLAG_NEW_LISTENER (donc libseccomp stockera le fd dans state.notify_fd ).
  2. Le même test unitaire est exécuté à nouveau dans le même processus mais dans un thread différent (en utilisant runtime.LockOSThread dans Go pour s'en assurer). Mais libseccomp réutilise le fd du filtre seccomp précédent (à partir de state.notify_fd ) au lieu d'obtenir un nouveau fd pour le nouveau filtre. Ensuite, le test échoue car nous nous attendons à recevoir les événements sur le mauvais seccomp fd.

FWIW, la notification seccomp FD est un objet global de processus, vous ne pouvez le demander au noyau qu'une seule fois. Vous pouvez lire le n° 273 pour en savoir plus sur le problème.

D'après ce que j'ai compris, le noyau nous limite à n'obtenir qu'une seule notification seccomp FD dans un arbre de filtrage. Mais dans le scénario ci-dessus, les deux threads du même processus utilisent des arborescences de filtres différentes, cela devrait donc convenir du point de vue du noyau.

Ce scénario pour utiliser différentes arborescences de filtres avec SECCOMP_FILTER_FLAG_NEW_LISTENER n'a pas été construit exprès, il est simplement apparu à la suite des tests unitaires libseccomp-golang exécutés dans le même processus. Mais comme la cause première est libseccomp utilisant une variable globale state.notify_fd qui est partagée entre les threads, j'ai pensé que je devrais ouvrir ce bogue ici pour ouvrir la discussion. Cependant, je serais bien si cela était fermé en tant que "WONTFIX" (je ne sais pas si d'autres utilisateurs de libseccomp auraient besoin d'un support pour ce genre de scénario). Dans ce cas, nous pouvons simplement écrire les tests unitaires libseccomp-golang d'une manière différente (c'est-à-dire en utilisant un processus séparé pour chaque itération de test); nous serions obligés de le faire de toute façon (pour éviter de mélanger les filtres au niveau des threads et les filtres au niveau du processus - cela serait rejeté par le noyau).

En travaillant sur les tests unitaires dans libseccomp-golang, j'ai réalisé que le scénario suivant était en cours de test :

  1. Dans une première exécution du test unitaire, une politique seccomp a été appliquée sans SECCOMP_FILTER_FLAG_TSYNC (c'est-à-dire qu'elle est appliquée au niveau du thread et non au niveau du processus) mais avec SECCOMP_FILTER_FLAG_NEW_LISTENER (donc libseccomp stockera le fd dans state.notify_fd ).
  2. Le même test unitaire est exécuté à nouveau dans le même processus mais dans un thread différent (en utilisant runtime.LockOSThread dans Go pour s'en assurer). Mais libseccomp réutilise le fd du filtre seccomp précédent (à partir de state.notify_fd ) au lieu d'obtenir un nouveau fd pour le nouveau filtre. Ensuite, le test échoue car nous nous attendons à recevoir les événements sur le mauvais seccomp fd.

Ah ha, ça a plus de sens maintenant. Je me suis souvent demandé si nous devions faire de TSYNC la valeur par défaut pour les liaisons libseccomp-golang ; étant donné l'ambiguïté du thread dans Go, cela semble être un choix beaucoup plus sûr.

D'après ce que j'ai compris, le noyau nous limite à n'obtenir qu'une seule notification seccomp FD dans un arbre de filtrage. Mais dans le scénario ci-dessus, les deux threads du même processus utilisent des arborescences de filtres différentes, cela devrait donc convenir du point de vue du noyau.

Ce scénario pour utiliser différentes arborescences de filtres avec SECCOMP_FILTER_FLAG_NEW_LISTENER n'a pas été construit exprès, il est simplement apparu à la suite des tests unitaires libseccomp-golang exécutés dans le même processus. Mais comme la cause première est libseccomp utilisant une variable globale state.notify_fd qui est partagée entre les threads, j'ai pensé que je devrais ouvrir ce bogue ici pour ouvrir la discussion. Cependant, je serais bien si cela était fermé en tant que "WONTFIX" (je ne sais pas si d'autres utilisateurs de libseccomp auraient besoin d'un support pour ce genre de scénario). Dans ce cas, nous pouvons simplement écrire les tests unitaires libseccomp-golang d'une manière différente (c'est-à-dire en utilisant un processus séparé pour chaque itération de test); nous serions obligés de le faire de toute façon (pour éviter de mélanger les filtres au niveau des threads et les filtres au niveau du processus - cela serait rejeté par le noyau).

Je serai intéressé d'avoir l' opinion de

Afin de "réparer" cela dans libseccomp, nous aurions besoin de rendre le thread libseccomp conscient, ce qui comporte un certain nombre de défis et de pièges, de sorte que je suis actuellement d'avis que ce serait une mauvaise idée. Cependant, pour des raisons d'argument, si nous rendions compte du thread libseccomp, nous pourrions également faire de l'état global interne un état spécifique au thread et/ou éventuellement un état spécifique à l'arbre de filtrage ; dans l'un ou l'autre de ces cas, je pense que l'API actuelle (y compris le seccomp_reset(NULL, ...) ) serait toujours raisonnable, donc je suis tenté de laisser les choses telles qu'elles sont avec l'API. Si quelqu'un a des inquiétudes à ce sujet, veuillez nous en informer rapidement.

@drakenclimber ? À moins d'objections à ce qui précède, je pense que nous sommes de retour pour la version 2.5.1.

Je serai intéressé d'avoir l' opinion de

Je suis d'accord. J'ai passé du temps à fouiller dans l' ensemble de correctifs et les commentaires originaux de

Cela dit, j'ai essayé de proposer un cas d'utilisation multithread et à processus unique qui comporte plusieurs invocateurs et gestionnaires de notification. Honnêtement, je ne pouvais pas concocter de manière cohérente un tel scénario. Étant donné qu'il s'agit d'un cas d'utilisation plutôt artificiel et que je n'arrive pas à trouver un cas d'utilisation réaliste, nous devrions marquer ce WONTFIX.

Un côté - j'ai pu faire en sorte que le noyau renvoie plusieurs fds de notification à un processus. En créant plusieurs pthreads et en les faisant tous charger immédiatement un filtre seccomp avec une action de notification, j'ai parfois pu obtenir deux ou trois fds de notification différents renvoyés au processus de l'espace utilisateur. Étant donné que cela est si irréaliste, je pencherais également pour marquer ce problème de noyau comme WONTFIX.

@drakenclimber ? À moins d'objections à ce qui précède, je pense que nous sommes de retour pour la version 2.5.1.

Génial. Je devrais pouvoir commencer à travailler dessus en début de semaine prochaine.

Il semble que nous soyons tous d'accord ici, donc je vais clore ce sujet. @alban si vous pensez qu'il nous manque quelque chose d'important, veuillez nous en informer et/ou rouvrir ce problème afin que nous puissions tout régler.

Merci tout le monde.

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