Provided by: manpages-fr-dev_4.13-4_all bug

NOM

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

SYNOPSIS

       #include <linux/seccomp.h>
       #include <linux/filter.h>
       #include <linux/audit.h>
       #include <linux/signal.h>
       #include <sys/ptrace.h>

       int seccomp(unsigned int operation, unsigned int flags, void *args);

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'operation 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  envoient  un  signal
              SIGKILL. Le mode de calcul sécurisé strict est utile pour les applications fonctionnant à coups de
              chiffres  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 opération n'est disponible que si le noyau a été configuré avec CONFIG_SECCOMP.

              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 enfants 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_TSYNC
                     Lors de l'ajout d'un filtre, synchroniser tous les autres threads du processus appelant sur
                     la  même  arborescence  de  filtres  seccomp. Une « arborescence de filtres » est une liste
                     ordonnée de filtres rattachés à un thread (le rattachement de filtres identiques  dans  des
                     appels seccomp() distincts génère différents filtres depuis cette perspective).

                     Si  un  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 filtres seccomp lui sont rattachés, en
                     décalage par rapport à l'arborescence de filtres du thread appelant.

              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_SPEC_ALLOW (depuis Linux 4.17)
                     Désactiver la mitigation Speculative Store Bypass.

       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é.

   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 appellé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 particulier). 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é essayé.

              –  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é sitôt l'appel système 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_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 le noyau 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).

   Interfaces /proc
       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  de  s'enregistrer 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 était utilisé, le
       code de retour est l'identifiant du thread  qui  a  fait  échouer  la  synchronisation  (il  s'agit  d'un
       identifiant  de  thread  du  noyau  du  type  renvoyé  par clone(2) et gettid(2)). Si d'autres erreurs se
       produisent, -1 est renvoyé et errno est positionné pour indiquer la cause de 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.

       EFAULT args n'était pas une adresse valable.

       EINVAL L'operation  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'operation donnée.

       EINVAL L'operation 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'operation diffère du paramétrage existant.

       EINVAL operation  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
              operation 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é.

VERSIONS

       L'appel système seccomp() est apparu pour la première fois dans Linux 3.17.

CONFORMITÉ

       L'appel système seccomp() est une extension Linux non standard.

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 un
       fichier des 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 :

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

       [2] 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ées
       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 <errno.h>
       #include <stddef.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <linux/audit.h>
       #include <linux/filter.h>
       #include <linux/seccomp.h>
       #include <sys/prctl.h>

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

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

           /* Supposer qu'AUDIT_ARCH_X86_64 signifie l'ABI x86-64 normale
              (dans l'ABI x32, tous les appels système ont 30 bits positionnés
              dans le champ 'nr', ce qui veut dire que 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] Revenir 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 à partir du 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] Revenir 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 (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),
                              strtol(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), 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

COLOPHON

       Cette page fait partie de la publication 5.10 du projet man-pages Linux. Une description du projet et des
       instructions pour signaler des anomalies et la dernière version de cette page  peuvent  être  trouvées  à
       l'adresse https://www.kernel.org/doc/man-pages/.

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> et Jean-Philippe MENGUAL <jpmengual@debian.org>

       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.

Linux                                            1 novembre 2020                                      SECCOMP(2)