Provided by: manpages-fr-dev_4.26.0-1_all bug

NOM

       seccomp - Agir sur l'état de calcul sécurisé (Secure Computing State) du processus

BIBLIOTHÈQUE

       Bibliothèque C standard (libc, -lc)

SYNOPSIS

       #include <linux/seccomp.h>  /* Définition des constantes SECCOMP_* */
       #include <linux/filter.h>   /* Définition de struct sock_fprog */
       #include <linux/audit.h>    /* Définition des constantes AUDIT_* */
       #include <linux/signal.h>   /* Définition des constantes SIG* */
       #include <sys/ptrace.h>     /* Définition des constantes PTRACE_* */
       #include <sys/syscall.h>    /* Définition des constantes SYS_* */
       #include <unistd.h>

       int syscall(SYS_seccomp, unsigned int opération, unsigned int flags,
                   void *args);

       Remarque : la glibc ne fournit pas d'enveloppe pour seccomp(), imposant l'utilisation de syscall(2).

DESCRIPTION

       L'appel système seccomp() agit sur l'état de calcul sécurisé (seccomp) du processus appelant.

       Actuellement, Linux gère les valeurs d'opération suivantes :

       SECCOMP_SET_MODE_STRICT
              Les  seuls  appels  système  que  le  thread appelant est autorisé à faire sont read(2), write(2),
              _exit(2) (mais pas exit_group(2)) et sigreturn(2). Les autres appels système aboutissent à la  fin
              du  thread  appelant  ou à la fin du processus complet avec le signal SIGKILL quand il n'y a qu'un
              seul thread. Le mode de calcul sécurisé strict est utile pour les applications  de  traitement  de
              nombres  qui  peuvent  avoir  besoin  d'exécuter  un code à octets non fiable, obtenu peut-être en
              lisant un tube ou un socket.

              Remarquez que si le thread  appelant  ne  peut  plus  appeler  sigprocmask(2),  il  peut  utiliser
              sigreturn(2)  pour  bloquer  tous  les signaux, sauf ceux provenant de SIGKILL et de SIGSTOP. Cela
              veut dire que alarm(2) (par exemple) n'est pas suffisant pour  restreindre  la  durée  d'exécution
              d'un  processus.  Pour terminer de manière fiable un processus, SIGKILL doit être utilisé. On peut
              le faire en utilisant timer_create(2) avec SIGEV_SIGNAL et sigev_signo positionné à SIGKILL ou  en
              utilisant setrlimit(2) pour positionner la limite ferme de RLIMIT_CPU.

              Cette fonctionnalité n'est disponible que si le noyau a été construit avec l'option CONFIG_SECCOMP
              activée.

              La valeur de flags doit être de 0 et args doit être NULL.

              Cette opération est fonctionnellement identique à l'appel :

                  prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);

       SECCOMP_SET_MODE_FILTER
              Les  appels  système  autorisés  sont définis par un pointeur vers un filtre Berkeley Packet (BPF)
              fourni à l'aide de args. Ce paramètre est un pointeur vers une struct sock_fprog ;  il  peut  être
              conçu  pour filtrer des appels système de votre choix ainsi que des paramètres d'appel système. Si
              le filtre n'est pas valable, seccomp() échoue en renvoyant EINVAL dans errno.

              Si fork(2) ou clone(2) est autorisé par le filtre, les processus enfant seront contraints par  les
              mêmes  filtres  d'appel  système que leur parent. Si execve(2) est autorisé, les filtres existants
              seront préservés lors d'un appel à execve(2).

              Pour utiliser l'opération SECCOMP_SET_MODE_FILTER, soit le thread appelant doit avoir la  capacité
              CAP_SYS_ADMIN  dans  son  espace  de noms utilisateur, soit il doit avoir déjà le bit no_new_privs
              défini. Si ce bit n'a pas déjà été positionné par un ascendant du thread, le thread doit effectuer
              l'appel suivant :

                  prctl(PR_SET_NO_NEW_PRIVS, 1);

              Sinon, l'opération SECCOMP_SET_MODE_FILTER échoue et renvoie EACCES  dans  errno.  Cette  exigence
              garantit  qu'un processus non privilégié ne peut pas appliquer un filtre malveillant et appeler un
              programme set-user-ID ou avec d'autres privilèges en utilisant execve(2), compromettant  ainsi  le
              programme  (un  tel  filtre  malveillant  pourrait,  par  exemple, conduire setuid(2) à essayer de
              définir les identifiants utilisateur de l'appelant à des valeurs non nulles pour renvoyer plutôt 0
              sans faire d'appel système. Ainsi, le programme pourrait être bidouillé pour garder les privilèges
              du super-utilisateur à des moments où il est  possible  de  l'influencer  pour  faire  des  choses
              dangereuses vu qu'il n'a pas abandonné ses privilèges).

              Si  prctl(2)  ou  seccomp()  est  autorisé  par  le filtre rattaché, d'autres filtres peuvent être
              ajoutés. Cela augmentera le temps d'évaluation mais  permet  d'autres  réductions  de  la  surface
              d'attaque lors de l'exécution d'un thread.

              L'opération  SECCOMP_SET_MODE_FILTER  n'est  disponible  que  si  le  noyau  a  été configuré avec
              CONFIG_SECCOMP_FILTER.

              Quand flags vaut 0, cette opération est fonctionnellement identique à l'appel :

                  prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, args);

              Les paramètres reconnus de flags sont :

              SECCOMP_FILTER_FLAG_LOG (depuis Linux 4.14)
                     Toutes  les  actions  de  renvoi  des  filtres,  sauf   SECCOMP_RET_ALLOW,   doivent   être
                     journalisées.  Un  administrateur  peut outrepasser cet attribut de filtre en empêchant des
                     actions     spécifiques     d'être     journalisées      à      l'aide      du      fichier
                     /proc/sys/kernel/seccomp/actions_logged.

              SECCOMP_FILTER_FLAG_NEW_LISTENER (depuis Linux 5.0)
                     Après une installation réussie du programme de filtrage, renvoyer un nouveau descripteur de
                     fichier  de  notification  pour  l'espace utilisateur. (L'attribut close-on-exec est défini
                     pour le descripteur de  fichier.)  Quand  le  filtre  renvoie  SECCOMP_RET_USER_NOTIF,  une
                     notification sera envoyée à ce descripteur de fichier.

                     Pour   un   thread,   au   maximum   un   seul   filtre  de  seccomp  utilisant  l'attribut
                     SECCOMP_FILTER_FLAG_NEW_LISTENER peut être installé.

                     Consultez seccomp_unotify(2) pour plus de détails.

              SECCOMP_FILTER_FLAG_SPEC_ALLOW (depuis Linux 4.17)
                     Désactiver la mitigation Speculative Store Bypass.

              SECCOMP_FILTER_FLAG_TSYNC
                     Lors de l'ajout d'un filtre, synchroniser tous les autres  threads  du  processus  appelant
                     avec la même arborescence de filtres seccomp. Une « arborescence de filtres » est une liste
                     ordonnée  de  filtres rattachée à un thread (le rattachement de filtres identiques dans des
                     appels seccomp() distincts génère différents filtres depuis cette perspective).

                     Si aucun thread ne peut pas se synchroniser avec  l'arborescence  de  filtres,  l'appel  ne
                     rattachera pas le nouveau filtre seccomp et échouera en renvoyant le premier identifiant de
                     thread  qui  n'a  pas pu se synchroniser. La synchronisation échouera si un autre thread du
                     même processus est en SECCOMP_MODE_STRICT ou si  des  nouveaux  filtres  seccomp  lui  sont
                     rattachés  en  propre,  en  décalage  par  rapport  à  l'arborescence  de filtres du thread
                     appelant.

       SECCOMP_GET_ACTION_AVAIL (depuis Linux 4.14)
              Tester pour savoir si une action est prise en charge par le noyau. Cette opération  peut  aider  à
              confirmer  que  le  noyau connaît l'action de renvoi d'un filtre récemment ajouté puisque le noyau
              traite toutes les actions inconnues comme des SECCOMP_RET_KILL_PROCESS.

              La valeur de flags doit être de 0 et args doit être un pointeur  vers  une  action  de  renvoi  de
              filtre 32 bits non signé.

       SECCOMP_GET_NOTIF_SIZES (depuis Linux 5.O)
              Obtenir  la  taille  des  structures de notification de l'espace utilisateur de seccomp. Comme ces
              structures peuvent évoluer et croître avec le  temps,  cette  commande  peut  être  utilisée  pour
              déterminer quelle quantité de mémoire allouer pour envoyer et recevoir des notifications.

              La valeur de flags doit être de 0 et args doit être un pointeur vers un struct seccomp_notif_sizes
              de la forme suivante :

              struct seccomp_notif_sizes
                  __u16 seccomp_notif;      /* Taille de la structure de notification */
                  __u16 seccomp_notif_resp; /* Taille de la structure de réponse */
                  __u16 seccomp_data;       /* Taille de 'struct seccomp_data' */
              };

              Consultez seccomp_unotify(2) pour plus de détails.

   Filtres
       Lors  de  l'ajout  d'un  filtre  à  l'aide  de  SECCOMP_SET_MODE_FILTER, args pointe vers un programme de
       filtrage :

           struct sock_fprog {
               unsigned short      len;    /* Nombre d'instructions BPF */
               struct sock_filter *filter; /* Pointeur vers le tableau
                                              d'instructions BPF */
           };

       Chaque programme doit contenir une ou plusieurs instructions BPF :

           struct sock_filter {            /* Filter block */
               __u16 code;                 /* Code du filtre réel */
               __u8  jt;                   /* Jump true (sauter le vrai) */
               __u8  jf;                   /* Jump false (sauter le faux) */
               __u32 k;                    /* Champ générique multiusages */
           };

       Lors de l'exécution des instructions, le programme BPF agit sur les informations de l'appel  système  qui
       sont  rendues disponibles (c'est-à-dire qu'il utilise le mode d'adressage BPF_ABS) en tant que tampon (en
       lecture seule) ayant la forme suivante :

           struct seccomp_data {
               int   nr;                   /* Numéro de l'appel système */
               __u32 arch;                 /* Valeur AUDIT_ARCH_*
                                              (voir <linux/audit.h>) */
               __u64 instruction_pointer;  /* pointeur vers l'instruction du processeur */
               __u64 args[6];              /* Jusqu'à 6 paramètres de l'appel système */
           };

       Comme la numérotation des appels système varie entre les architectures et comme certaines (comme  x86-64)
       autorisent   du  code  de  l'espace  utilisateur  à  utiliser  les  conventions  de  l'appelant  d'autres
       architectures (et comme cette convention peut varier pendant la vie d'un processus qui utilise  execve(2)
       pour  exécuter  des  binaires  qui  utilisent différentes conventions), il est généralement nécessaire de
       vérifier la valeur du champ arch.

       Il est fortement recommandé d'utiliser une approche par liste d'autorisations autant que possible,  parce
       qu'une telle approche est plus robuste et plus simple. Une liste d'interdictions devra être mise à jour à
       chaque  fois qu'un appel système dangereux sera ajouté (ou un attribut ou une option si elles font partie
       de la liste des interdictions) et il est souvent possible de modifier la représentation d'une valeur sans
       changer sa signification, conduisant à contourner la liste d'interdictions. Voir  aussi  Mises  en  garde
       ci-dessous.

       Le  champ  arch  n'est pas unique pour toutes les conventions d'appelant. Les ABI x86-64 et x32 utilisent
       AUDIT_ARCH_X86_64 en tant que arch et elles fonctionnent sur les  mêmes  processeurs.  Au  contraire,  le
       masque  __X32_SYSCALL_BIT  est  utilisé sur le numéro d'appel système pour parler indépendamment aux deux
       ABI.

       Cela veut dire qu'une politique peut soit interdire tous les appels système avec __X32_SYSCALL_BIT,  soit
       elle  doit  les  reconnaître  avec  le  positionnement  ou pas de __X32_SYSCALL_BIT. Une liste des appels
       système à interdire qui s'appuie sur nr et qui ne contient pas de valeurs  nr__X32_SYSCALL_BIT  est
       positionné peut être contournée par un programme malveillant qui positionne __X32_SYSCALL_BIT.

       En  outre,  les  noyaux précédant Linux 5.4 autorisaient à tort nr dans les intervalles 512–547 ainsi que
       les appels système non x32 correspondants reliés (opération OU) avec __X32_SYSCALL_BIT. Par  exemple,  nr
       ==  521  et  nr  ==  (101  |  __X32_SYSCALL_BIT)  créeraient  des  appels  ptrace(2)  avec une sémantique
       potentiellement confondue entre x32 et x86_64 dans le noyau. Les politiques prévues pour fonctionner  sur
       des  noyaux  antérieurs à Linux 5.4 doivent garantir qu'elles interdisent ou qu'elles gèrent correctement
       ces appels système. Sur Linux 5.4 et plus récents, de tels appels  système  échoueront  avec  une  erreur
       ENOSYS sans rien faire.

       Le champ instruction_pointer fournit l'adresse de l'instruction en langage machine qui a effectué l'appel
       système.  Cela  pourrait  être  utile avec /proc/pid/maps pour effectuer des vérifications à partir de la
       région (projection) du programme  qui  a  fait  l'appel  système  (il  est  probablement  raisonnable  de
       verrouiller  les appels système mmap(2) et mprotect(2) pour empêcher le programme de contourner de telles
       vérifications).

       Lors de la vérification des valeurs de args, gardez en tête que  les  paramètres  sont  souvent  tronqués
       silencieusement avant d'être traités mais après la vérification seccomp. Cela arrive par exemple si l'ABI
       i386  est  utilisée  sur  un  noyau x86-64 : bien que le noyau n'ira normalement pas regarder au-delà des
       32 bits les plus faibles des paramètres, les valeurs des registres 64 bits complets seront présentes dans
       les données de seccomp. Un exemple moins surprenant est que si l'ABI x86-64 est utilisée  pour  effectuer
       un  appel  système  prenant  un  paramètre  de  type  int,  la  moitié  du  registre du paramètre la plus
       significative est ignorée par l'appel système mais visible dans les données de seccomp.

       Un filtre seccomp renvoie une valeur 32 bits en  deux  parties  :  la  plus  significative,  de  16  bits
       (correspondant  au  masque  défini  par  la  constante SECCOMP_RET_ACTION_FULL), contient une des valeurs
       « action  »  listée  ci-dessous  ;  la  moins  significative,  de  16  bits  (définie  par  la  constante
       SECCOMP_RET_DATA), contient des « data » à associer à ce code de retour.

       Si  plusieurs  filtres  existent,  ils  sont  tous  exécutés dans l'ordre inverse de leur apparition dans
       l'arbre des filtres – si bien que le filtre le plus récemment installé est exécuté en premier) (remarquez
       que tous les filtres seront appelés même si l'un des premiers appelés renvoie SECCOMP_RET_KILL, cela pour
       simplifier le code du noyau et pour fournir une petite accélération d’exécution d’ensembles de filtres en
       évitant la vérification de ce cas rare). La valeur renvoyée de l'évaluation d'un appel système donné  est
       la  première valeur vue de l'action de plus haute priorité (ainsi que ses données associées) renvoyée par
       l'exécution de tous les filtres.

       Dans l'ordre décroissant de priorité, les valeurs d'action qui  peuvent  être  renvoyées  par  un  filtre
       seccomp sont :

       SECCOMP_RET_KILL_PROCESS (depuis Linux 4.14)
              Cette  valeur  aboutit  à  la  fin immédiate du processus, avec un vidage mémoire. L'appel système
              n'est pas exécuté. Contrairement à SECCOMP_RET_KILL_THREAD ci-dessous, tous les threads du  groupe
              de  threads  sont  terminés  (pour  un  point  sur  les  groupes de thread, voir la description de
              l'attribut CLONE_THREAD de clone(2)).

              Le processus se termine parce que il a été tué par un signal SIGSYS. Même si  un  gestionnaire  de
              signal  a  été  enregistré pour SIGSYS, le gestionnaire sera ignoré dans ce cas et le processus se
              termine toujours. Le processus  parent  qui  attend  ce  processus  (en  utilisant  waitpid(2)  ou
              équivalent) reçoit wstatus qui indique que son enfant s'est terminé suite à un signal SIGSYS.

       SECCOMP_RET_KILL_THREAD (ou SECCOMP_RET_KILL)
              Cette  valeur  provoque la fin immédiate du thread qui a effectué l'appel système. L'appel système
              n'est pas exécuté. Les autres threads du même groupe de threads continueront à s'exécuter.

              Le thread s'est terminé comme tué par un signal SIGSYS. Voir SECCOMP_RET_KILL_PROCESS ci-dessus.

              Avant Linux 4.11, tout processus qui se terminait de cette  manière  ne  générait  pas  de  vidage
              mémoire (bien que SIGSYS soit documenté dans signal(7) pour avoir comme action par défaut celle de
              terminer  avec  un  vidage  mémoire).  Depuis  Linux 4.11, un processus d'un seul thread créera un
              vidage mémoire s'il se termine dans ce cadre.

              Avec l'apparition de SECCOMP_RET_KILL_PROCESS  dans  Linux  4.14,  SECCOMP_RET_KILL_THREAD  a  été
              ajouté comme synonyme de SECCOMP_RET_KILL, afin de distinguer plus clairement les deux actions.

              Remarque  :  l'utilisation de SECCOMP_RET_KILL_THREAD pour tuer un thread unique d'un processus de
              plusieurs threads va probablement mettre le processus dans un état incohérent  et  corrompre  pour
              toujours son état.

       SECCOMP_RET_TRAP
              Cette  valeur  fait  envoyer  par le noyau un signal SIGSYS adressé au thread déclencheur (l'appel
              système n'est pas exécuté). Divers champs seront positionnés dans  la  structure  siginfo_t  (voir
              sigaction(2)) associée au signal :

              -  si_signo contiendra SIGSYS.

              -  si_call_addr affichera l'adresse de l'instruction de l'appel système.

              -  si_syscall et si_arch indiqueront l'appel système qui a été tenté.

              -  si_code contiendra SYS_SECCOMP.

              -  si_errno contiendra la partie SECCOMP_RET_DATA du code de retour du filtre.

              Le  compteur  du  programme  sera  arrêté comme si l'appel système a été fait (c'est-à-dire que le
              compteur du programme ne pointera pas vers l'instruction de l'appel système). Le registre du  code
              de  retour  contiendra une valeur dépendante de l'architecture ; en cas de relance de l'exécution,
              positionnez-la sur quelque chose  adapté  à  l'appel  système  (la  dépendance  de  l'architecture
              provient du fait que son remplacement par ENOSYS écraserait des informations utiles).

       SECCOMP_RET_ERRNO
              Cette  valeur  fait  passer  la  partie  SECCOMP_RET_DATA  du  code de retour du filtre à l'espace
              utilisateur en tant que valeur errno sans exécuter l'appel système.

       SECCOMP_RET_USER_NOTIF (depuis Linux 5.0)
              Faire suivre l'appel système à un processus de superviseur attaché de l'espace utilisateur attaché
              pour permettre à ce processus de décider quoi faire de  l'appel  système.  Si  il  n'y  a  pas  de
              superviseur   attaché   (soit   parce   que  le  filtre  n'a  pas  été  installé  avec  l'attribut
              SECCOMP_FILTER_FLAG_NEW_LISTENER ou parce que le descripteur de fichier était  fermé),  le  filtre
              renvoie  ENOSYS  (c'est similaire à ce qui se produit quand un filtre renvoie SECCOMP_RET_TRACE et
              qu'il n'y a pas d'observateur). Consultez seccomp_unotify(2) pour plus de détails.

              Remarquez que le processus de superviseur ne sera pas notifié  si  un  autre  filtre  renvoie  une
              valeur d'action ayant une priorité supérieure à SECCOMP_RET_USER_NOTIF.

       SECCOMP_RET_TRACE
              Quand cette valeur est renvoyée, le noyau essaiera de notifier à un observateur basé sur ptrace(2)
              avant  d'exécuter  l'appel  système. Si aucun observateur n'est présent, l'appel système n'est pas
              exécuté et renvoie un échec en positionnant errno sur ENOSYS.

              Un   observateur    sera    notifié    s'il    demande    PTRACE_O_TRACESECCOMP    en    utilisant
              ptrace(PTRACE_SETOPTIONS). Il sera notifié d'un PTRACE_EVENT_SECCOMP et la partie SECCOMP_RET_DATA
              du  code  de  retour  du  filtre  sera  mise  à  la  disposition  de  l'observateur  à  l'aide  de
              PTRACE_GETEVENTMSG.

              L'observateur peut ignorer l'appel système en  modifiant  le  numéro  de  l'appel  système  à  -1.
              Autrement,  l'observateur  peut modifier l'appel système demandé en le passant à un numéro d'appel
              système valable. Si l'observateur demande à ignorer l'appel système, ce dernier renverra la valeur
              que l'observateur place dans le registre du code de retour.

              Avant Linux 4.8, la vérification seccomp ne sera pas refaite après que l'observateur ait reçu  une
              notification  (cela  signifie  que  sur  les  anciens  noyaux, les conteneurs basés sur seccomp ne
              doivent pas autoriser l'utilisation de ptrace(2) – même sur d'autres processus encapsulés  –  sans
              une  prudence  extrême  ;  les  ptracers  peuvent utiliser ce mécanisme pour sortir d'un conteneur
              seccomp).

              Remarquez que le processus d'un observateur ne sera pas notifié si un  autre  filtre  renvoie  une
              valeur d'action ayant une priorité supérieure à SECCOMP_RET_TRACE.

       SECCOMP_RET_LOG (depuis Linux 4.14)
              Cette valeur fait exécuter l'appel système après l'enregistrement de l'action de retour du filtre.
              Un  administrateur  peut  supplanter  la  journalisation  de  cette  action  à  l'aide  du fichier
              /proc/sys/kernel/seccomp/actions_logged.

       SECCOMP_RET_ALLOW
              Cette valeur provoque l'exécution de l'appel système.

       Si on indique un code d'action différent de ceux ci-dessus, l'action de filtre est traitée soit comme  un
       SECCOMP_RET_KILL_PROCESS  (depuis  Linux 4.14), soit comme un SECCOMP_RET_KILL_THREAD (dans Linux 4.13 et
       antérieurs).

   /proc interfaces
       Les fichiers du répertoire  /proc/sys/kernel/seccomp  offrent  des  informations  et  des  configurations
       seccomp supplémentaires :

       actions_avail (depuis Linux 4.14)
              Une  liste  ordonnée  en  lecture  seule d'actions de renvoi de filtre seccomp sous la forme d'une
              chaîne. L'ordre, de gauche à droite,  est  décroissant  pour  la  priorité.  La  liste  représente
              l'ensemble des actions de renvoi de filtre seccomp gérées par le noyau.

       actions_logged (depuis Linux 4.14)
              Une  liste  ordonnée  en lecture-écriture d'actions de renvoi de filtre seccomp autorisées pour la
              journalisation. Les écritures dans le fichier n'ont pas besoin d'être ordonnées, mais les lectures
              se feront dans le même ordre que pour actions_avail.

              Il est important de remarquer que la valeur de actions_logged n'empêche pas certaines  actions  de
              renvoi  de filtre d'être enregistrées quand le sous-système d'audit est configuré pour auditer une
              tâche. Si l'action n'est  pas  retrouvée  dans  le  fichier  actions_logged,  la  décision  finale
              d'auditer  l'action  de  cette  tâche  revient  au sous-système d'audit pour toutes les actions de
              renvoi de filtre autres que SECCOMP_RET_ALLOW.

              La chaîne « allow » n'est pas acceptée dans le fichier actions_logged car il  n'est  pas  possible
              d'enregistrer  les  actions SECCOMP_RET_ALLOW. Essayer d'écrire « allow » dans le fichier échouera
              avec l'erreur EINVAL.

   Enregistrement d'audit des actions seccomp
       Depuis Linux 4.14, le noyau offre la possibilité d'enregistrer les  actions  renvoyées  par  des  filtres
       seccomp  dans  le  compte-rendu  d'audit. Le noyau prend la décision d'enregistrer une action à partir du
       type d'action, de sa présence dans le fichier actions_logged et de l'activation de l'audit du noyau  (par
       exemple avec l'option d'amorçage du noyau audit=1). Les règles sont les suivantes :

       -  Si l'action est SECCOMP_RET_ALLOW, l'action n'est pas enregistrée.

       -  Sinon, si l'action est SECCOMP_RET_KILL_PROCESS ou SECCOMP_RET_KILL_THREAD et si elle apparaît dans le
          fichier actions_logged, l'action est enregistrée.

       -  Sinon,  si  le  filtre  a  demandé  l'enregistrement  (l'attribut  SECCOMP_FILTER_FLAG_LOG) et si elle
          apparaît dans le fichier actions_logged, l'action est enregistrée.

       -  Sinon, si l'audit du noyau est activé et si le processus doit être audité (autrace(8)),  l'action  est
          enregistrée.

       -  Sinon, l'action n'est pas enregistrée.

VALEUR RENVOYÉE

       En  cas  de  succès, seccomp() renvoie 0. En cas d'erreur, si SECCOMP_FILTER_FLAG_TSYNC a été utilisé, le
       code de retour est l'identifiant du thread à l'origine de l'échec de la synchronisation (cet  identifiant
       est  un  identifiant  de  thread du noyau du type renvoyé par clone(2) et gettid(2)). Si une autre erreur
       arrive, -1 est renvoyé et errno est positionné pour indiquer l'erreur.

ERREURS

       seccomp() peut échouer pour les raisons suivantes :

       EACCES L'appelant n'avait pas la capacité CAP_SYS_ADMIN dans son espace de noms  utilisateur  ou  n'avait
              pas positionné no_new_privs avant d'utiliser SECCOMP_SET_MODE_FILTER.

       EBUSY  Pendant  l'installation  d'un  nouveau  filtre,  l'attribut SECCOMP_FILTER_FLAG_NEW_LISTENER a été
              indiqué, mais un filtre précédent a déjà été installé avec cet attribut.

       EFAULT args n'était pas une adresse valable.

       EINVAL L'opération est inconnue ou n'est pas prise en charge par cette version ou cette configuration  du
              noyau.

       EINVAL Les flags spécifiés ne sont pas valables pour l'opération donnée.

       EINVAL L'opération  comprenait  BPF_ABS,  mais  la  position  indiquée n'était pas alignée sur une limite
              32 bits ou elle dépassait sizeof(struct seccomp_data).

       EINVAL Un mode de calcul sécurisé a déjà été défini et l'opération diffère du paramétrage existant.

       EINVAL opération indiquait SECCOMP_SET_MODE_FILTER mais le programme de filtre vers lequel pointait  args
              n'était pas valable ou sa longueur était de zéro ou dépassait BPF_MAXINSNS instructions (4096).

       ENOMEM Plus assez de mémoire.

       ENOMEM La  taille  totale  de  tous  les  programmes  de  filtre rattachés au thread appelant dépasserait
              MAX_INSNS_PER_PATH instructions (32768).  Remarquez  qu'afin  de  calculer  cette  limite,  chaque
              programme de filtre déjà existant intègre une pénalité de dépassement de 4 instructions.

       EOPNOTSUPP
              opération  indiquait  SECCOMP_GET_ACTION_AVAIL  mais  le  noyau  ne gère pas l'action de renvoi de
              filtre indiquée par args.

       ESRCH  Un autre thread a provoqué un échec pendant la synchronisation, mais son identifiant  n'a  pas  pu
              être déterminé.

STANDARDS

       Linux.

HISTORIQUE

       Linux 3.17.

NOTES

       Au  lieu  de  coder à la main des filtres seccomp comme démontré dans l'exemple ci-dessous, vous pourriez
       préférer utiliser la bibliothèque libseccomp qui fournit une interface de génération de filtres seccomp.

       Le champ Seccomp du fichier /proc/pid/status offre une  méthode  de  visualisation  du  mode  seccomp  du
       processus ; voir proc(5).

       seccomp()  fournit  un  sur-ensemble de fonctionnalités de l'opération PR_SET_SECCOMP de prctl(2) (qui ne
       prend pas en charge les flags).

       Depuis Linux 4.4, l'opération PTRACE_SECCOMP_GET_FILTER de ptrace(2) peut être utilisée pour obtenir  les
       filtres seccomp d'un processus.

   Gestion d'architecture pour le BPF seccomp
       La  gestion  d'architecture  pour  le  filtrage  de  BPF  seccomp  est  disponible  sur les architectures
       suivantes :

       -  x86-64, i386, x32 (depuis Linux 3.5)
       -  ARM (depuis Linux 3.8)
       -  s390 (depuis Linux 3.8)
       -  MIPS (depuis Linux 3.16)
       -  ARM-64 (depuis Linux 3.19)
       -  PowerPC (depuis Linux 4.3)
       -  Tile (depuis Linux 4.3)
       -  PA-RISC (depuis Linux 4.6)

   Mises en garde
       Il y a beaucoup de subtilités à prendre en compte lorsqu'on applique des filtres seccomp à un  programme,
       notamment :

       -  Certains  appels  système  traditionnels  ont  des  implémentations  dans l'espace utilisateur dans le
          vdso(7) de nombreuses architectures. Parmi les exemples remarquables,  se  trouvent  clock_gettime(2),
          gettimeofday(2)  et  time(2).  Sur  de telles architectures, le filtrage seccomp de ces appels système
          sera sans effet (il y a cependant des cas où les implémentations vdso(7) se rabattent sur le véritable
          appel système, alors les filtres seccomp verraient l'appel système).

       -  Le filtrage seccomp s'appuie sur les numéros d'appel système. Cependant, les applications  n'appellent
          généralement  pas  directement  les  appels  système,  mais  plutôt  les  fonctions  enveloppe  de  la
          bibliothèque C qui appellent à leur tour les appels système. Par conséquent, vous devez garder en tête
          ce qui suit :

          -  Les enveloppes de la glibc pour certains appels système traditionnels peuvent utiliser  des  appels
             système ayant des noms différents dans le noyau. Par exemple, la fonction enveloppe exit(2) utilise
             en  fait  l'appel  système  exit_group(2)  et  la  fonction  fork(2)  utilise en réalité les appels
             clone(2).

          -  Le comportement des fonctions enveloppe peut changer en fonction des architectures, selon la  plage
             d'appels  système  fournie  sur  ces  architectures. Autrement dit, la même fonction enveloppe peut
             appeler différents appels système selon les architectures.

          -  Enfin, le comportement des fonctions enveloppe peut changer selon les versions  de  la  glibc.  Par
             exemple,  dans  d'anciennes versions, la fonction enveloppe de la glibc de open(2) appelait l'appel
             système du même nom, mais à partir de la 2.26, l'implémentation est passée à l'appel openat(2)  sur
             toutes les architectures.

       La  conséquence des points ci-dessus est qu'il pourrait être nécessaire de filtrer un appel système autre
       que celui prévu. Plusieurs pages de manuel de la section 2 donnent des détails utiles sur les différences
       entre les fonctions enveloppe et les  appels  système  sous-jacents  dans  les  sous-sections  intitulées
       Différences entre le noyau et la bibliothèque C.

       En  outre,  remarquez  que  l'application de filtres seccomp risque même de provoquer des bogues dans une
       application, quand les filtres provoquent des échecs inattendus d'opérations légitimes que  l'application
       a  besoin  d'effectuer.  De  tels  bogues pourraient ne pas être facilement identifiés lors d'un test des
       filtres seccomp s'ils se produisent à des endroits du code rarement utilisés.

   Détails BPF spécifiques à seccomp
       Remarquez que les détails BPF suivants sont spécifiques aux filtres seccomp :

       -  Les modificateurs de taille BPF_H et BPF_B ne sont pas pris en charge : toutes les opérations  doivent
          charger et stocker des mots (4 octets) (BPF_W).

       -  Pour accéder au contenu du tampon seccomp_data, utilisez le modificateur du mode d'adressage BPF_ABS.

       -  Le  modificateur  du mode d'adressage BPF_LEN produit un opérande de mode immédiatement dont la valeur
          est la taille du tampon seccomp_data.

EXEMPLES

       Le programme ci-dessous accepte quatre paramètres ou plus. Les trois  premiers  sont  un  numéro  d'appel
       système,  un identifiant numérique d'architecture et un numéro d'erreur. Le programme utilise ces valeurs
       pour construire un filtre BPF utilisé lors de l'exécution pour effectuer les vérifications suivantes :

       -  Si le programme ne tourne pas sur l'architecture indiquée, le  filtre  BPF  fait  échouer  les  appels
          système avec l'erreur ENOSYS.

       -  Si  le programme essaie d'exécuter l'appel système ayant le numéro indiqué, le filtre BPF fait échouer
          l'appel système en positionnant errno sur le numéro d'erreur indiqué.

       Les autres paramètres de la ligne de commande indiquent le chemin et les paramètres supplémentaires  d'un
       programme  que  notre exemple doit essayer d'exécuter en utilisant execv(3) (une fonction de bibliothèque
       qui utilise l'appel système  execve(2)).  Certains  exemples  d’exécution  du  programme  sont  présentés
       ci-dessous.

       Tout  d'abord,  on  affiche  l'architecture  sur  laquelle on est (x86-64) puis on construit une fonction
       d’interpréteur qui cherche les numéros d'appels système sur cette architecture :

           $ uname -m
           x86_64
           $ syscall_nr() {     cat /usr/src/linux/arch/x86/syscalls/syscall_64.tbl | \     awk '$2 != "x32" && $3 == "'$1'" { print $1 }' }

       Quand le filtre BPF rejette un appel système (cas n° 2 ci-dessus), il fait échouer l'appel  système  avec
       le numéro d'erreur indiqué sur la ligne de commande. Dans les exemples présentés ici, nous utiliserons le
       numéro d'erreur 99 :

           $ errno 99
           EADDRNOTAVAIL 99 Ne peut pas affecter l'adresse demandée

       Dans  l'exemple  suivant,  on essaie d'exécuter la commande whoami(1), mais le filtre BPF rejette l'appel
       système execve(2), donc la commande n'est même pas exécutée :

           $ syscall_nr execve
           59
           $ ./a.out
           Utilisation : ./a.out <syscall_nr> <arch> <errno> <prog> [<args>]
           Astuce pour <arch> : AUDIT_ARCH_I386: 0x40000003
                            AUDIT_ARCH_X86_64 : 0xC000003E
           $ ./a.out 59 0xC000003E 99 /bin/whoami
           execv : Ne peut pas affecter l'adresse demandée

       Dans le prochain exemple, le filtre BPF rejette l'appel système write(2) pour que,  même  si  elle  a  pu
       démarrer, la commande whoami(1) ne puisse pas écrire de sortie :

           $ syscall_nr write
           1
           $ ./a.out 1 0xC000003E 99 /bin/whoami

       Dans  le  dernier  exemple,  le filtre BPF rejette un appel système qui n'est pas utilisé par la commande
       whoami(1), elle peut donc s'exécuter et produire une sortie :

           $ syscall_nr preadv
           295
           $ ./a.out 295 0xC000003E 99 /bin/whoami
           cecilia

   Source du programme
       #include <linux/audit.h>
       #include <linux/filter.h>
       #include <linux/seccomp.h>
       #include <stddef.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/prctl.h>
       #include <sys/syscall.h>
       #include <unistd.h>

       #define X32_SYSCALL_BIT 0x40000000
       #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

       static int
       install_filter(int syscall_nr, unsigned int t_arch, int f_errno)
       {
           unsigned int upper_nr_limit = 0xffffffff;

           /* On suppose que AUDIT_ARCH_X86_64 renvoie à l'ABI x86-64 normale
              (dans l'ABI x32, tous les appels système ont le bit 30 positionné
              dans le champ 'nr', donc les numéros sont
              >= X32_SYSCALL_BIT). */
           if (t_arch == AUDIT_ARCH_X86_64)
               upper_nr_limit = X32_SYSCALL_BIT - 1;

           struct sock_filter filter[] = {
               /* [0] Charger l'architecture depuis le tampon 'seccomp_data'
                      dans l'accumulateur. */
               BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                        (offsetof(struct seccomp_data, arch))),

               /* [1] Avancer de 5 instructions si l'architecture ne
                      correspond pas à 't_arch'. */
               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, t_arch, 0, 5),

               /* [2] Charger le numéro d'appel système depuis le tampon
                      'seccomp_data' dans l'accumulateur. */
               BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
                        (offsetof(struct seccomp_data, nr))),

               /* [3] Vérifier l'ABI - nécessaire seulement pour x86-64 si on
                      utilise une liste d'interdictions. Utiliser BPF_JGT au lieu de
                      vérifier par rapport au masque de bits pour ne pas devoir
                      recharger le numéro d'appel système. */
               BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, upper_nr_limit, 3, 0),

               /* [4] Avancer d'une instruction si le numéro d'appel système
                      ne correspond pas à 'syscall_nr'. */
               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall_nr, 0, 1),

               /* [5] Architecture et appel système correspondants : ne pas
                  exécuter l'appel système et renvoyer 'f_errno' dans
                  'errno'. */
               BPF_STMT(BPF_RET | BPF_K,
                        SECCOMP_RET_ERRNO | (f_errno & SECCOMP_RET_DATA)),

               /* [6] Cible du numéro d’appel système inadéquate :
                      autoriser d'autres appels système. */
               BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),

               /* [7] Cible de l’architecture inadéquate : tuer le processus. */
               BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
           };

           struct sock_fprog prog = {
               .len = ARRAY_SIZE(filter),
               .filter = filter,
           };

           if (syscall(SYS_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog)) {
               perror("seccomp");
               return 1;
           }

           return 0;
       }

       int
       main(int argc, char *argv[])
       {
           if (argc < 5) {
               fprintf(stderr, "Utilisation : "
                       "%s <syscall_nr> <arch> <errno> <prog> [<args>]\n"
                       "Astuce pour <arch> : AUDIT_ARCH_I386: 0x%X\n"
                       "                 AUDIT_ARCH_X86_64: 0x%X\n"
                       "\n", argv[0], AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
               exit(EXIT_FAILURE);
           }

           if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
               perror("prctl");
               exit(EXIT_FAILURE);
           }

           if (install_filter(strtol(argv[1], NULL, 0),
                              strtoul(argv[2], NULL, 0),
                              strtol(argv[3], NULL, 0)))
               exit(EXIT_FAILURE);

           execv(argv[4], &argv[4]);
           perror("execv");
           exit(EXIT_FAILURE);
       }

VOIR AUSSI

       bpfc(1), strace(1), bpf(2), prctl(2), ptrace(2), seccomp_unotify(2),  sigaction(2),  proc(5),  signal(7),
       socket(7)

       Plusieurs  pages  de  la  bibliothèque  libseccomp,  dont  : scmp_sys_resolver(1), seccomp_export_bpf(3),
       seccomp_init(3), seccomp_load(3) et seccomp_rule_add(3).

       Les fichiers Documentation/networking/filter.txt  et  Documentation/userspace-api/seccomp_filter.rst  des
       sources du noyau (ou Documentation/prctl/seccomp_filter.txt avant Linux 4.13).

       McCanne,  S.  et  Jacobson,  V. (1992)  The BSD Packet Filter : une nouvelle architecture de captation de
       paquets   au   niveau   utilisateur,   colloque   de   la    conférence    USENIX    à    l'hiver    1993
       http://www.tcpdump.org/papers/bpf-usenix93.pdf

TRADUCTION

       La   traduction   française   de   cette   page   de   manuel   a   été   créée   par  Christophe  Blaess
       <https://www.blaess.fr/christophe/>,   Stéphan   Rafin   <stephan.rafin@laposte.net>,   Thierry   Vignaud
       <tvignaud@mandriva.com>,  François  Micaux,  Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard
       <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)   <jean-luc.coulon@wanadoo.fr>,   Julien   Cristau
       <jcristau@debian.org>,      Thomas      Huriaux      <thomas.huriaux@gmail.com>,     Nicolas     François
       <nicolas.francois@centraliens.net>,    Florentin    Duneau    <fduneau@gmail.com>,     Simon     Paillard
       <simon.paillard@resel.enst-bretagne.fr>,     Denis    Barbier    <barbier@debian.org>,    David    Prévot
       <david@tilapin.org>,  Jean-Philippe  MENGUAL  <jpmengual@debian.org>   et   Jean-Pierre   Giraud   <jean-
       pierregiraud@neuf.fr>

       Cette  traduction  est  une  documentation libre ; veuillez vous reporter à la GNU General Public License
       version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel,  veuillez  envoyer  un  message  à
       debian-l10n-french@lists.debian.org.

Pages du manuel de Linux 6.9.1                    15 juin 2024                                        seccomp(2)