Provided by: manpages-fr_4.21.0-2_all bug

NOM

       user_namespaces — Présentation des espaces de noms utilisateur sous Linux

DESCRIPTION

       Pour une présentation générale des espaces de noms, consultez namespaces(7).

       Les  espaces de noms utilisateur isolent les identifiants et attributs liés à la sécurité, en particulier
       les identifiants d'utilisateurs et de groupes (consultez credentials(7)), le répertoire racine, les clefs
       (consultez keyctl(2)) et les capacités (consultez capabilities(7)). Les identifiants d'utilisateur et  de
       groupe  d'un  processus  peuvent  être différents selon que l'on se trouve à l'intérieur ou à l'extérieur
       d'un espace de noms utilisateur.  Un  processus  peut  notamment  avoir  un  identifiant  sans  privilège
       particulier  en  dehors  d'un  espace de noms et avoir l'identifiant 0 à l'intérieur d'un espace de noms.
       Autrement dit, le processus dispose de tous les privilèges pour des opérations effectuées  dans  l'espace
       de  noms,  tandis  qu'il  n'en  a  aucun  pour  les  opérations  réalisées  en dehors de l'espace de noms
       utilisateur.

   Espaces de noms imbriqués, appartenance aux espaces de noms
       Les espaces de noms utilisateur  peuvent  être  imbriqués.  Cela  signifie  que  chaque  espace  de  noms
       utilisateur  — à  l'exception de l'espace de noms initial (« root ») — a un espace de noms parent et peut
       avoir éventuellement un ou plusieurs espaces de noms utilisateur enfant.  L'espace  de  noms  utilisateur
       parent  est  l'espace de noms du processus qui a créé l'espace de noms utilisateur au moyen de unshare(2)
       ou de clone(2) invoqué avec l'attribut CLONE_NEWUSER.

       Le noyau impose (à partir de Linux 3.11) une limite de 32 niveaux d'imbrication pour les espaces de  noms
       utilisateur.  Si un appel à unshare(2) ou à clone(2) provoque le dépassement de cette limite, la commande
       échoue en renvoyant l'erreur EUSERS.

       Chaque processus est membre d'exactement un espace de noms utilisateur. Un processus créé par fork(2)  ou
       par clone(2) sans l'attribut CLONE_NEWUSER est membre du même espace de noms que son processus parent. Un
       processus  mono-threadé  peut  rejoindre un autre espace de noms en utilisant setns(2) s'il dispose de la
       capacité CAP_SYS_ADMIN dans cet espace de noms ; cette action lui octroie un ensemble de  capacités  dans
       cet espace de noms.

       Un appel à clone(2) ou à unshare(2) avec l'attribut CLONE_NEWUSER place le nouveau processus enfant (pour
       clone(2)) ou l'appelant (pour unshare(2)) dans le nouvel espace de noms utilisateur créé par l'appel.

       L’opération  ioctl(2)  NS_GET_PARENT peut être utilisée pour découvrir les relations de parenté entre les
       espaces de noms utilisateur. Consultez ioctl_ns(2).

   Capacités
       Le processus enfant créé par clone(2) avec l'attribut CLONE_NEWUSER s’initialise avec un nouvel  ensemble
       de  capacités  dans le nouvel espace de noms utilisateur. De même, un processus qui crée un nouvel espace
       de noms au moyen de unshare(2) ou qui rejoint un espace de noms existant à l’aide de setns(2)  reçoit  un
       ensemble  de capacités dans cet espace de noms. D’un autre côté, le processus n’a aucune capacité dans le
       parent (dans le cas de clone(2)) ou dans le  précédent  espace  de  noms  utilisateur  (dans  le  cas  de
       unshare(2)  et  setns(2)),  même  si  le  nouvel  espace  de  noms  utilisateur  est  créé ou rejoint par
       l’utilisateur racine (c’est-à-dire un processus avec l’ID utilisateur 0 dans l’espace de noms racine).

       Remarquez qu'un appel à execve(2) déclenche la réévaluation des capacités  selon  la  méthode  habituelle
       (consultez  capabilities(7)),  de  sorte  que  le processus perdra ses capacités, sauf si son identifiant
       utilisateur vaut 0 dans l'espace de noms ou si le fichier exécutable a un masque de  capacités  héritable
       non  vide.  Pour  en savoir plus, consultez les commentaires sur le mappage entre utilisateurs et groupes
       ci-dessous.

       Un appel à clone(2) ou unshare(2) en utilisant l'attribut  CLONE_NEWUSER  ou  un  appel  à  setns(2)  qui
       déplace  l’appelant  dans  d’autres  jeux  d’espaces  de  noms  utilisateur  positionne  les  indicateurs
       « securebits » (consultez capabilities(7)) à leurs valeurs par défaut (tous les  indicateurs  désactivés)
       dans  l’enfant  (pour  clone(2))  ou  l’appelant  (pour  unshare(2) ou setns(2)). Remarquez que parce que
       l’appelant n’a plus de capacités dans son espace de noms utilisateur après un appel à setns(2), il  n’est
       pas  possible  à  un  processus  de  réinitialiser  ses indicateurs « securebits » tout en conservant son
       appartenance à un espace de noms utilisateur en utilisant une paire d’appels setns(2)  pour  se  déplacer
       vers  un  autre  espace  de  noms  utilisateur  et  ensuite retourner vers son espace de noms utilisateur
       original.

       Les règles pour déterminer si un processus a ou n’a pas de capacités dans un espace de  noms  utilisateur
       particulier sont comme suit :

       -  Un  processus  dispose d'une capacité dans un espace de noms utilisateur s'il est membre de cet espace
          de noms et si cette capacité est activée dans son jeu de capacités.  Un  processus  peut  obtenir  une
          nouvelle  capacité  dans  son  jeu de capacités de plusieurs façons. Il peut, par exemple, exécuter un
          programme set-user-ID ou un exécutable avec des capacités de  fichier  associées.  Il  peut  également
          obtenir  des  capacités  à  l’aide  de  l'action  de  clone(2),  unshare(2)  ou setns(2) comme indiqué
          précédemment.

       -  Si un processus dispose d'une capacité dans un espace de noms  utilisateur,  alors  il  a  cette  même
          capacité dans tous les espaces de noms enfant (et les espaces descendants supprimés).

       -  Lorsqu'un espace de noms est créé, le noyau enregistre l'identifiant utilisateur effectif du processus
          de  création  comme  étant le « propriétaire » de l'espace de noms. Un processus qui se trouve dans le
          parent d'un espace de noms utilisateur et qui a un identifiant utilisateur effectif qui correspond  au
          propriétaire  de l'espace de noms dispose de toutes les capacités dans cet espace de noms. En vertu de
          la règle précédente, cela signifie que ce processus a également toutes les  capacités  dans  tous  les
          descendants  supprimés  de  cet  espace  de  noms.  L’opération  NS_GET_OWNER_UID d’ioctl(2) peut être
          utilisée pour découvrir l’ID d’utilisateur du propriétaire de l’espace de noms. Consultez ioctl_ns(2).

   Effet des capacités à l’intérieur d’un espace de noms utilisateur
       Un processus qui possède des capacités dans un espace de noms utilisateur a  la  possibilité  d'effectuer
       des  opérations  (nécessitant des privilèges) seulement sur les ressources gérées par cet espace de noms.
       En d’autres mots, avoir une capacité dans un espace de  noms  permet  à  un  processus  de  réaliser  des
       opérations  privilégiées sur des ressources gérées par des espaces de noms (non utilisateur) possédés par
       (associés avec) l’espace de noms utilisateur (consultez la sous-section suivante).

       D’un autre coté, il existe beaucoup d’opérations  privilégiées  affectant  les  ressources  qui  ne  sont
       associées  à  aucun  type  d’espace  de  noms,  par exemple, modifier l’heure du système (c’est-à-dire le
       calendrier) (régi par CAP_SYS_TIME), charger un module du noyau (régi par  CAP_SYS_MODULE)  et  créer  un
       périphérique  (régi  par  CAP_MKNOD).  Seuls  les processus avec privilèges dans l’espace de noms initial
       peuvent réaliser de telles opérations.

       Avoir CAP_SYS_ADMIN dans un espace de noms utilisateur qui possède  un  espace  de  noms  de  montage  de
       processus  permet  à ce processus de créer des remontages (bind mount) et de monter les types suivants de
       système de fichiers :

           -  /proc/ (depuis Linux 3.8)
           -  /sys (depuis Linux 3.8)
           -  devpts (depuis Linux 3.9)
           -  tmpfs(5) (depuis Linux 3.9)
           -  ramfs (depuis Linux 3.9)
           -  mqueue (depuis Linux 3.9)
           -  bpf (depuis Linux 4.4)
           -  overlayfs (depuis Linux 5.11)

       Avoir CAP_SYS_ADMIN dans l’espace de noms utilisateur qui possède un espace de noms cgroup  de  processus
       permet  (depuis  Linux 4.6)  à  ce  processus de monter un système de fichiers cgroup version 2 ou cgroup
       version 1  appelés  hiérarchies  (c’est-à-dire  des   systèmes   de   fichiers   cgroup   avec   l’option
       « none,name= »).

       Avoir  CAP_SYS_ADMIN  dans  un  espace de noms utilisateur qui possède un espace de noms PID de processus
       permet (depuis Linux 3.8) à ce processus de monter des systèmes de fichiers /proc.

       Remarquez cependant que le montage de systèmes  de  fichiers  basés  sur  les  blocs  peut  être  réalisé
       seulement par un processus ayant CAP_SYS_ADMIN dans l’espace de noms utilisateur initial.

   Liens entre les espaces de noms utilisateur et les autres espaces de noms
       À partir de Linux 3.8, les processus sans privilèges peuvent créer des espaces de noms utilisateur et les
       autres espaces de noms peuvent être créés avec simplement la capacité CAP_SYS_ADMIN dans l'espace de noms
       utilisateur de l'appelant.

       Lorsqu'un  espace  de  noms  autre  qu'utilisateur est créé, il appartient à l'espace de noms utilisateur
       auquel appartenait à ce moment là le processus à l'origine de la création de  cet  espace  de  noms.  Les
       opérations  privilégiées  sur des ressources régies par un espace de noms non utilisateur nécessitent que
       le processus aient les capacités requises dans l’espace de noms utilisateur qui possède l’espace de  noms
       non utilisateur.

       Si  CLONE_NEWUSER est indiqué en complément de l'attribut CLONE_NEW* lors d'un appel simple à clone(2) ou
       à unshare(2), l'espace de noms utilisateur est garanti d'être créé en premier. Cela donne des  privilèges
       à l’enfant (dans le cas de clone(2)) ou à l'appelant (dans le cas de unshare(2)) dans les espaces de noms
       subsistants  créés  par  l'appel.  Il  est ainsi possible à un appelant sans privilèges d'indiquer ce jeu
       d'attributs.

       Lorsqu'un nouvel espace de noms (autre qu’un espace de noms utilisateur) est créé à l’aide de clone(2) ou
       unshare(2), le noyau enregistre l'espace de noms utilisateur du processus créateur comme le  propriétaire
       du  nouvel  espace  de  noms. (Cette association ne peut pas être changée). Lorsqu'un processus du nouvel
       espace de noms effectue ensuite une opération privilégiée sur une ressource globale isolée  par  l'espace
       de  noms,  les  vérifications  de  permissions sont réalisées en fonction des capacités du processus dans
       l'espace de noms utilisateur que le noyau a associé au nouvel espace  de  noms.  Par  exemple,  supposons
       qu’un  processus  essaie  de modifier le nom d’hôte (sethostname(2)), une ressource régie par l’espace de
       noms UTS. Dans ce cas le noyau déterminera quel espace de noms utilisateur possède l’espace de  noms  UTS
       du  processus  et vérifiera si le processus à la capacité requise (CAP_SYS_ADMIN) dans cet espace de noms
       utilisateur.

       L’opération NS_GET_USERNS d’ioctl(2) peut être utilisée  pour  découvrir  l’espace  de  noms  utilisateur
       possédant l’espace de noms non utilisateur. Consultez ioctl_ns(2).

   Correspondance des identifiants d'utilisateur et de groupe : uid_map et gid_map
       Lorsqu'un  espace  de  noms  utilisateur  est  créé,  il  s'initialise  sans établir de mappage entre ses
       identifiants utilisateurs (identifiants de groupes) et ceux de l'espace  de  noms  parent.  Les  fichiers
       /proc/pid/uid_map  et  /proc/pid/gid_map présentent (à partir de Linux 3.5) le mappage entre identifiants
       utilisateur et groupe à l'intérieur de l'espace de noms utilisateur pour le processus pid.  Ces  fichiers
       peuvent  être  consultés  pour  prendre  connaissance  des mappages dans un espace de noms utilisateur et
       peuvent être modifiés (une seule fois) pour définir les mappages.

       Les paragraphes suivants décrivent uid_map en détails. gid_map est parfaitement analogue, chaque instance
       de « identifiant utilisateur » étant remplacée par « identifiant groupe ».

       Le fichier uid_map présente le mappage entre les identifiants utilisateur de l'espace de noms utilisateur
       du processus pid et ceux de l'espace de  noms  utilisateur  du  processus  qui  a  ouvert  uid_map  (mais
       consultez  la  réserve  concernant ce point exposée ci-dessous). En d'autres termes, des processus qui se
       trouvent dans différents espaces de noms verront des valeurs différentes lors de la lecture d'un  fichier
       uid_map  selon  les  mappages des identifiants utilisateur pour l'espace de noms utilisateur du processus
       qui effectue la lecture.

       Chaque ligne du fichier uid_map affiche un mappage un-pour-un d'un intervalle d'identifiants  utilisateur
       contigus  de deux espaces de noms utilisateur. Lorsqu'un espace de noms utilisateur vient d'être créé, ce
       fichier est vide. Chaque ligne contient trois nombres  délimités  par  des  espaces.  Les  deux  premiers
       nombres  indiquent les premiers identifiants utilisateur de chacun des deux espaces de noms. Le troisième
       nombre indique la longueur de l'intervalle de mappage. Plus précisément, les champs sont  interprétés  de
       la façon suivante :

       (1)  Le  début  de l'intervalle d'identifiants utilisateur dans l'espace de noms utilisateur du processus
            pid.

       (2)  Le début de l'intervalle d'identifiants utilisateur auquel mappe l'identifiant  utilisateur  indiqué
            dans  le  premier  champ. Selon que le processus qui a ouvert le fichier uid_map et le processus pid
            sont ou non dans le même espace de noms, le deuxième  champ  est  interprété  de  l'une  des  façons
            suivantes :

            (a)  Si  les deux processus sont dans différents espaces de noms utilisateur : le deuxième champ est
                 le début de l'intervalle d'identifiants  utilisateur  dans  l'espace  de  noms  utilisateur  du
                 processus qui a ouvert uid_map.

            (b)  Si les deux processus sont dans le même espace de noms utilisateur : le second champ correspond
                 au  début de la séquence d'identifiants utilisateur dans l'espace de noms utilisateur parent du
                 processus pid. Cela permet au processus qui a ouvert uid_map (généralement, le processus  ouvre
                 /proc/self/uid_map)  de  voir  le  mappage  des  identifiants utilisateur dans l'espace de noms
                 utilisateur du processus qui a créé cet espace de noms utilisateur.

       (3)  La longueur de l'intervalle des identifiants utilisateur qui est mappé entre  les  deux  espaces  de
            noms utilisateur.

       Les  appels  système  qui renvoient des identifiants utilisateur (des identifiant de groupes) — comme par
       exemple, getuid(2), getgid(2), et les champs relatifs aux droits dans la structure renvoyée par stat(2) —
       affichent la valeur de l'identifiant utilisateur (l'identifiant de groupe) mappé dans  l'espace  de  noms
       utilisateur de l'appelant.

       Lorsqu'un  processus accède à un fichier, ses identifiant utilisateur et groupe sont mappés dans l’espace
       de noms utilisateur initial pour pouvoir vérifier les droits ou pour assigner des identifiants lors de la
       création d'un fichier. Lorsqu'un processus obtient les identifiants utilisateur et  groupe  d'un  fichier
       par la commande stat(2), les identifiants sont évalués dans le sens inverse, afin de renvoyer les valeurs
       relatives aux mappages des ID utilisateur et de groupe du processus.

       L'espace  de  noms utilisateur initial n'a pas d'espace de noms parent, mais pour conserver la cohérence,
       le noyau lui attribue des fichiers de mappage d'identifiants utilisateur  et  groupe  factices  pour  cet
       espace  de  noms.  Si l'on consulte le fichier uid_map (ou gid_map de la même façon) depuis une invite de
       commande dans l'espace de noms initial, on peut voir :

           $ cat /proc/$$/uid_map
                    0          0 4294967295

       Ce mappage nous indique que l'intervalle commençant avec l'identifiant utilisateur 0 dans cet  espace  de
       noms  mappe  avec un intervalle commençant à 0 dans l'espace de noms parent (qui n'existe pas), et que la
       longueur de cet intervalle est la valeur du plus grand entier 32 bits non signé. Cela  laisse  4294967295
       (la  valeur  32 bits  signé  moins 1)  non  mappé. Cela est voulu : (uid_t) -1 est utilisé dans plusieurs
       interfaces (par exemple, setreuid(2)) comme façon d’indiquer « pas d’ID utilisateur ». Laisser (uid_t) -1
       non mappé et inutilisable garantit  qu’il  n’y  aura  aucune  confusion  lors  de  l’utilisation  de  ces
       interfaces.

   Création des mappages d'ID utilisateur et groupe : écriture dans uid_map et gid_map
       Après  la  création  d'un  nouvel espace de noms utilisateur, le fichier uid_map de l'un des processus de
       l'espace de noms peut être ouvert en écriture une seule fois pour y consigner le mappage des identifiants
       utilisateur dans le nouvel espace de noms utilisateur. Toute tentative d'écrire plus d'une fois  dans  un
       fichier  uid_map  se solde par un échec qui renvoie l'erreur EPERM. Des règles analogues s'appliquent aux
       fichiers gid_map.

       Les lignes inscrites dans uid_map (gid_map) doivent suivre les règles de validité suivantes :

       -  Les trois champs doivent être des nombres valables et le dernier champ doit être strictement positif.

       -  Les lignes doivent se terminer par un saut de ligne.

       -  Il y a une limite (arbitraire) du nombre de lignes que peut contenir le fichier.  Dans  Linux 4.14  et
          précédents,  la  limite  est  (arbitrairement)  de  5 lignes.  Depuis  Linux 4.15,  la  limite  est de
          340 lignes. En outre, le nombre d'octets inscrits dans le fichier doit  être  inférieur  à  la  taille
          d'une  page du système, et l'écriture doit être réalisée au début du fichier (c’est-à-dire lseek(2) et
          pwrite(2) ne peuvent être utilisées pour écrire dans le fichier avec un décalage non nul).

       -  L'intervalle d'identifiants utilisateur (ou de groupe) indiqué dans chaque ligne ne peut recouvrir les
          intervalles des autres lignes. Dans l'implémentation initiale (Linux 3.8), cette règle  était  assurée
          par  une implémentation plus sommaire qui comprenait une contrainte supplémentaire : les deux premiers
          champs de chaque ligne devaient apparaître en ordre croissant. Cela empêchait cependant la création de
          mappages valables. Ce problème a été réglé dans Linux 3.9 et  suivants,  et  toutes  les  combinaisons
          valables de mappages non recouvrantes sont désormais acceptées.

       -  Au moins une ligne doit être inscrite dans le fichier.

       Les  opérations  d'écritures qui ne respectent pas les règles énoncées précédemment échouent en renvoyant
       l'erreur EINVAL.

       Un processus ne peut écrire dans le fichier /proc/pid/uid_map (/proc/pid/gid_map) qu'à  la  condition  de
       respecter les contraintes suivantes :

       -  Le  processus  réalisant l'écriture doit disposer de la capacité CAP_SETUID (CAP_SETGID) dans l'espace
          de noms utilisateur du processus pid.

       -  Le processus réalisant l'écriture doit se trouver soit dans l'espace de noms utilisateur du  processus
          pid, soit dans l'espace de noms utilisateur parent du processus pid.

       -  Les  identifiants utilisateur (ou groupe) mappés doivent, en retour, avoir un mappage dans l'espace de
          noms utilisateur parent.

       -  Pour une mise à jour de /proc/pid/uid_map pour créer un mappage pour l’UID 0  dans  l’espace  de  noms
          parent, une des propositions suivantes doit être vraie :

          (a)  si  le  processus  écrivain  est dans l’espace de noms utilisateur parent, il doit disposer de la
               capacité CAP_SETUID ;

          (b)  si le processus écrivain est dans l’espace de noms enfant, alors le processus ayant créé l’espace
               de noms utilisateur doit avoir la capacité CAP_SETFCAP lors de la création de l’espace de noms.

          Cette règle a été mise en place depuis Linux 5.12. Elle supprime un  bogue  de  sécurité  précédent  à
          cause  duquel  un processus d’UID 0 n’ayant pas la capacité CAP_SETFCAP, qui est nécessaire pour créer
          un  binaire  avec  les  capacités  de  fichier  d’un  certain  espace  de  noms  (comme  décrit   dans
          capabilities(7)), pouvait néanmoins créer un tel binaire en effectuant les étapes suivantes :

          (1)  Créer  un  nouvel  espace  de noms utilisateur avec le mappage d’identifiant (c’est-à-dire, UID 0
               dans le nouvel espace de noms utilisateur correspond à l’UID 0 dans  l’espace  de  noms  parent),
               ainsi cet UID 0 dans les deux espaces de noms est équivalent au même ID de superutilisateur.

          (2)  Puisque  le  processus  enfant  a  la  capacité  CAP_SETFCAP,  il  peut créer un binaire avec les
               capacités de fichier d’un certain espace de noms qui serait alors  disponible  dans  l’espace  de
               noms parent (parce que les ID du superutilisateur sont les mêmes dans les deux espaces de noms).

       -  L'un des deux points suivants est vérifié :

          (a)  soit le processus réalisant l'écriture doit disposer de la capacité CAP_SETUID ( CAP_SETGID) dans
               l'espace de noms utilisateur parent.

               -  Aucune  autre  restriction,  le  processus  peut  établir des mappages vers les ID utilisateur
                  (groupe) dans l’espace de noms parent.

          (b)  Ou sinon toutes les restrictions suivantes s’appliquent :

               -  Les données inscrites dans uid_map (gid_map) doivent consister en une seule  ligne  qui  mappe
                  l'identifiant  utilisateur  effectif  (groupe)  du  processus  écrivant  dans l’espace de noms
                  utilisateur parent à un ID utilisateur (groupe) dans l’espace de noms utilisateur.

               -  Le processus réalisant l'écriture doit avoir le même ID utilisateur effectif que le  processus
                  ayant créé l’espace de noms utilisateur.

               -  Dans  le  cas  de  gid_map,  l’utilisation  de  l’appel système setgroups(2) doit être d’abord
                  interdit en écrivant « deny » dans le  fichier  /proc/pid/setgroups  (voir  ci-dessous)  avant
                  d’écrire dans gid_map.

       Les écritures violant ces règles échouent avec l’erreur EPERM.

   Mappages d’ID de projet : projid_map
       De  la  même  manière que pour les mappages d’ID d’utilisateur et de groupe, il est possible de créer des
       mappages d’ID de projet pour un espace de noms utilisateur (les ID de  projets  sont  utilisés  pour  des
       quotas de disque, consulter setquota(8) et quotactl(2)).

       Les  mappages d’ID de projet sont définis par des écritures dans le fichier /proc/pid/projid_map (présent
       depuis Linux 3.7).

       Les règles de validité pour écrire dans le fichier  /proc/pid/projid_map  sont  les  mêmes  que  pour  le
       fichier uid_map. Une violation de ces règles provoque l'échec de write(2) avec l’erreur EINVAL.

       Les règles de permission pour écrire dans le fichier /proc/pid/projid_map sont les suivantes :

       -  Le  processus réalisant l'écriture doit se trouver soit dans l'espace de noms utilisateur du processus
          pid, soit dans l'espace de noms utilisateur parent du processus pid.

       -  Les ID de projet mappés doivent, en retour, avoir un mappage dans l'espace de noms utilisateur parent.

       La violation de ces règles provoque l'échec de write(2) avec l’erreur EPERM.

   Interaction avec les appels système qui modifient les UID ou les GID
       Dans un espace de noms utilisateur où aucun fichier  uid_map  n’a  été  écrit,  les  appels  système  qui
       modifient  l’ID  utilisateur échoueront. De la même manière, si le fichier gid_map n’a pas été écrit, les
       appels système modifiant les ID de groupe échoueront. Après que les fichiers uid_map et gid_map aient été
       écrits, seules les valeurs mappées peuvent être utilisées  dans  les  appels  système  modifiant  les  ID
       utilisateur et groupe.

       Pour  les  ID  utilisateur,  les appels système concernés incluent setuid(2), setfsuid(2), setreuid(2) et
       setresuid(2). Pour les ID de groupe,  les  appels  système  concernés  incluent  setgid(2),  setfsgid(2),
       setregid(2), setresgid(2) et setgroups(2).

       Écrire  « deny » dans le fichier /proc/pid/setgroups avant d’écrire dans /proc/pid/gid_map désactivera de
       manière  permanente  setgroups(2)  dans  un  espace  de  noms  utilisateur  et  permettra  d’écrire  dans
       /proc/pid/gid_map sans avoir la capacité CAP_SETGID dans l’espace de noms utilisateur parent.

   Le fichier /proc/pid/setgroups
       Le  fichier  /proc/pid/setgroups  affichera  la  chaîne  « allow » si les processus dans l’espace de noms
       utilisateur qui contient le processus pid sont autorisés à  employer  l’appel  système  setgroups(2).  Il
       affichera  « deny » si setgroups(2) n’est pas autorisé dans cet espace de noms utilisateur. Remarquez que
       quelle que soit la valeur dans le fichier /proc/pid/setgroups (et quelles que  soient  les  capacités  du
       processus),  les appels à setgroups(2) ne sont en outre pas permis si /proc/pidgid_map n’a pas encore été
       défini.

       Un processus privilégié (un avec la capacité CAP_SYS_ADMIN dans l’espace de noms)  peut  écrire  une  des
       chaînes « allow » ou « deny » dans ce fichier avant d’écrire un mappage d’ID de groupe pour cet espace de
       noms utilisateur dans le fichier /proc/pid/gid_map. Écrire la chaîne « deny » empêche tout processus dans
       l’espace de noms utilisateur d’employer setgroups(2).

       L’idée  de  ces  restrictions  décrites dans le paragraphe précédent est qu’il n'est permis d’écrire dans
       /proc/pid/setgroups que sil’appel à setgroups(2) est désactivé parce que /proc/pid/gid_map  n’a  pas  été
       défini.  Cela  garantit qu’un processus ne peut transiter d’un état dans lequel setgroups(2) est autorisé
       vers un état dans lequel setgroups(2) est interdit. Un processus peut transiter seulement de setgroups(2)
       interdit vers setgroups(2) autorisé.

       La valeur par défaut dans ce fichier dans l’espace de noms utilisateur initial est « allow ».

       Une fois que /proc/pid/gid_map a été écrit (ce qui a pour effet d’activer setgroups(2) dans  l’espace  de
       noms  utilisateur),  il  n’est  plus  possible  de  désactiver  setgroups(2)  en  écrivant  « deny » dans
       /proc/pid/setgroups (l’écriture échoue avec l’erreur EPERM).

       Un espace de noms utilisateur enfant hérite du réglage /proc/pid/setgroups de son parent.

       Si le fichier setgroups a la valeur « deny », alors l’appel système setgroups(2) ne peut pas par la suite
       être réactivé (en écrivant « allow » dans  le  fichier)  dans  cet  espace  de  noms  utilisateur  (toute
       tentative  échouera  avec  l’erreur  EPERM).  Cette  restriction  se  propage  vers  les  espaces de noms
       utilisateur enfant de cet espace de noms utilisateur.

       Le fichier /proc/pid/setgroups a été ajouté dans Linux 3.19, mais a été rétroporté vers plusieurs  séries
       stables  du  noyau  car  il  corrige  un  problème  de  sécurité.  Cela  concernait les fichiers avec les
       permissions telles que « rwx---rwx ». De tels  fichiers  accordent  moins  de  permissions  au  « group »
       qu’elles  ne  donnent  à  « other ».  Cela signifie qu’abandonner les groupes utilisant setgroups(2) peut
       permettre un accès au fichier du processus que celui-ci n’avait pas  auparavant.  Avant  l’existence  des
       espaces  de  noms utilisateur cela n’était pas un problème, puisque seul un processus privilégié (un avec
       la capacité CAP_SETGID) pouvait appeler setgroups(2). Cependant, avec l’introduction des espaces de  noms
       utilisateur,  il  est  devenu possible pour un processus non privilégié de créer un nouvel espace de noms
       dans lequel l’utilisateur a tous les privilèges. Cela permet alors à des  utilisateurs  anciennement  non
       privilégiés d’abandonner les groupes et donc obtenir l’accès à des fichiers auxquels ils ne pouvaient pas
       accéder.  Le fichier /proc/pid/setgroups a été ajouté pour résoudre le problème de sécurité en refusant à
       tout chemin pour un processus non privilégié d’abandonner les groupes avec setgroups(2).

   ID utilisateur et groupe non mappés
       Il existe différentes situations dans lesquelles un identifiant utilisateur (ou de groupe) non mappé peut
       être exposé dans un espace de noms utilisateur. Par exemple, le premier processus d'un nouvel  espace  de
       noms  utilisateur  peut appeler getuid() avant que le mappage des identifiants utilisateur ait été défini
       pour l'espace de noms. Dans la plupart de ces cas, l'identifiant utilisateur non mappé est converti en un
       identifiant utilisateur (groupe) au-delà de la limite de débordement ; la valeur par défaut  au  delà  de
       cette  limite  pour  un  identifiant  utilisateur  (ou  groupe)  est 65534. Consultez les descriptions de
       /proc/sys/kernel/overflowuid et de /proc/sys/kernel/overflowgid dans proc(5).

       Les situations dans lesquelles des identifiants non mappés sont transformés de  cette  façon  comprennent
       les cas des appels système qui renvoient des identifiants utilisateur (getuid(2), getgid(2) et les appels
       similaires),  les  accréditations  passées  à  l’aide  d’un  socket  de  domaine UNIX, les accréditations
       renvoyées par stat(2), waitid(2)  et  les  autres  opérations  IPC  « ctl »  IPC_STAT  de  System V,  les
       accréditations  présentées  par  /proc/pid/status  et  les  fichiers  /proc/sysvipc/*, les accréditations
       renvoyées par le  champ  si_uid  de  siginfo_t  reçues  avec  un  signal  (consultez  sigaction(2)),  les
       accréditations  écrites  dans  le  fichier  du  processus de tenue des comptes (consultez acct(5)) et les
       accréditations renvoyées avec des notifications de files de messages POSIX (consultez mq_notify(3)).

       Il est un cas notable où des identifiants d'utilisateur et de groupe non mappés ne sont pas convertis  en
       des  valeurs  d’ID  correspondantes au-delà de la limite. Lors de la consultation d'un fichier uid_map ou
       gid_map dans lequel il n'y a pas de mappage pour le second champ, ce champ apparaît comme 4294967295  (-1
       représenté comme un entier non signé).

   Accession aux fichiers
       Dans  le  but  de  déterminer  les permissions quand un processus non privilégié accède à un fichier, les
       accréditations du processus (UID, GID) et les accréditations du fichier sont en réalité mappées  vers  ce
       qu’elles  seraient  dans  l’espace  de  noms  utilisateur  initial et alors comparées pour déterminer les
       permissions que le processus possède sur le fichier. La même chose est valable pour les autres objets qui
       emploient les accréditations plus le modèle d’accessibilité avec le masque de permission,  tels  que  les
       objets IPC de System V.

   Opérations sur les capacités relatives aux fichiers
       Certaines  capacités  permettent à un processus de contourner diverses restrictions imposées par le noyau
       lors d’opérations sur des fichiers possédés par d’autres utilisateurs  ou  groupes.  Ce  sont  CAP_CHOWN,
       CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER et CAP_FSETID.

       Dans  un  espace de noms utilisateur, ces capacités permettent à un processus de contourner les règles si
       le processus possède la capacité adéquate sur le fichier, signifiant que :

       -  le processus a la capacité effective adéquate dans son espace de noms utilisateur;

       -  les ID utilisateur et groupe du fichier ont tous les deux des mappages valables dans l’espace de  noms
          utilisateur.

       La  capacité  CAP_FOWNER est traitée de manière quelque peu exceptionnelle. Elle permet à un processus de
       contourner les règles correspondantes à condition qu’au moins l’ID  utilisateur  du  fichier  possède  un
       mappage  dans  l’espace  de  noms  utilisateur (c’est-à-dire que l’ID de groupe du fichier n’a nul besoin
       d’avoir un mappage valable).

   Programmes set-user-ID et set-group-ID
       Lorsqu'un processus appartenant à un espace de noms  exécute  un  programme  set-user-ID  (set-group-ID),
       l'identifiant  utilisateur  (groupe)  effectif  du processus dans l'espace de noms est changé à n’importe
       quelle valeur mappée pour l’identifiant utilisateur (groupe)  du  fichier.  Cependant,  si  l'identifiant
       utilisateur  ou  groupe  n'a  pas de mappage dans l'espace de noms, le bit set-user-ID (set-group-ID) est
       ignoré silencieusement : le nouveau  programme  est  exécuté,  mais  l'identifiant  utilisateur  (groupe)
       effectif  n’est  pas  modifié.  Cela  reproduit  la  sémantique d'exécution d'un programme set-user-ID ou
       set-group-ID qui se trouve dans un système de fichiers monté avec l'indicateur MS_NOSUID,  comme  indiqué
       dans mount(2).

   Divers
       Lorsque  les  identifiants  utilisateur  et  groupe  d'un processus sont transmis à l’aide d’un socket de
       domaine UNIX à un processus d'un autre espace de noms (consultez la description de  SCM_CREDENTIALS  dans
       unix(7)),  ils  sont  transformés  en  leur  valeur  correspondante suivant les mappages des identifiants
       utilisateur et groupe du processus réceptionnaire.

STANDARDS

       Les espaces de noms sont propres à Linux.

NOTES

       Au fil des ans, de nombreuses fonctionnalités  ont  été  ajoutées  au  noyau  Linux  mais  réservées  aux
       utilisateurs  disposant  de  privilèges  du  fait  de  la  confusion  qu'elles  peuvent  induire dans les
       applications set-user-ID-root. En général, il n'est pas dangereux d'autoriser  un  superutilisateur  d'un
       espace  de  noms  à  utiliser  ces  fonctionnalités  parce  qu'il  est impossible, dans un espace de noms
       utilisateur, d'obtenir plus de droits que ce que peut obtenir le superutilisateur  d’un  espace  de  noms
       utilisateur.

   Superutilisateur global
       Le  terme de « superutilisateur global » (global root) est parfois utilisé comme un raccourci pour l’ID 0
       dans l’espace de noms utilisateur initial.

   Disponibilité
       Le noyau doit avoir été configuré avec l'option CONFIG_USER_NS pour permettre l'utilisation  des  espaces
       de  noms  utilisateur. Ces espaces doivent également être pris en charge par un ensemble de sous-systèmes
       du noyau. Si un sous-système non pris en charge est activé dans  le  noyau,  il  n'est  pas  possible  de
       configurer la prise en charge des espaces de noms.

       Depuis  Linux 3.8,  la  plupart  des  principaux  sous-systèmes  prennent  en  charge les espaces de noms
       utilisateur, mais certains systèmes de fichiers n'ont pas l'infrastructure  nécessaire  pour  mapper  les
       identifiants   utilisateur  et  groupe  entre  les  espaces  de  noms  utilisateur.  Linux 3.9  a  fourni
       l'infrastructure nécessaire à la prise en charge de nombreux systèmes de fichiers restants (Plan 9  (9P),
       Andrew  File  System  (AFS),  Ceph, CIFS, CODA, NFS et OCFS2). Linux 3.12 a apporté la prise en charge du
       dernier des principaux systèmes de fichiers non encore géré, XFS.

EXEMPLES

       Le programme suivant est conçu pour permettre de s'exercer avec les espaces de  noms  utilisateur,  comme
       avec  d'autres espaces de noms. Il crée des espaces de noms tels que définis dans les options de la ligne
       de commande et exécute une commande dans ces espaces de noms. Les commentaires  et  la  fonction  usage()
       dans  le programme fournissent une explication détaillée du programme. La session shell suivante illustre
       son utilisation.

       Tout d'abord, regardons l'environnement d'exécution :

           $ uname -rs     # à partir de Linux 3.8
           Linux 3.8.0
           $ id -u         # exécuté comme utilisateur sans privilèges
           1000
           $ id -g
           1000

       Démarrons maintenant un nouveau shell dans les nouveaux espaces de noms utilisateur (-U), de montage (-m)
       et de PID (-p), avec l'identifiant utilisateur (-M) et groupe (-G) 1000 mappés à 0 dans l'espace de  noms
       utilisateur :

           $ ./userns_child_exec -p -m -U -M '0 1000 1' -G '0 1000 1' bash

       Le shell a le PID 1 puisqu'il est le premier processus de l'espace de noms :

           bash$ echo $$
           1

       Lorsque  l'on  monte un nouveau système de fichiers /proc et que l'on affiche tous les processus visibles
       dans le nouvel espace de noms PID, on constate que le shell peut voir tous les processus qui se  trouvent
       à l'extérieur de l'espace de noms PID :

           bash$ mount -t proc proc /proc
           bash$ ps ax
             PID TTY      STAT   TIME COMMAND
               1 pts/3    S      0:00 bash
              22 pts/3    R+     0:00 ps ax

       Dans  l'espace  de  noms  utilisateur,  le  shell a les identifiants utilisateur et groupe 0, ainsi qu'un
       ensemble complet de capacités autorisées et effectives :

           bash$ cat /proc/$$/status | egrep '^[UG]id'
           Uid: 0    0    0    0
           Gid: 0    0    0    0
           bash$ cat /proc/$$/status | egrep '^Cap(Prm|Inh|Eff)'
           CapInh:   0000000000000000
           CapPrm:   0000001fffffffff
           CapEff:   0000001fffffffff

   Source du programme

       /* userns_child_exec.c

          Sous licence publique générale GNU, versions 2 ou postérieures

       Créer un processus enfant qui exécute une commande de shell dans
       un nouvel espace de noms. Il permet de préciser les mappages
       d'identifiants utilisateur et groupe lors de la création d’un
       nouvel espace de noms utilisateur.
       #define _GNU_SOURCE
       #include <err.h>
       #include <sched.h>
       #include <unistd.h>
       #include <stdint.h>
       #include <stdlib.h>
       #include <sys/wait.h>
       #include <signal.h>
       #include <fcntl.h>
       #include <stdio.h>
       #include <string.h>
       #include <limits.h>
       #include <errno.h>

       struct child_args {
           char **argv;        /* Commande à exécuter par l’enfant, avec arguments */
           int    pipe_fd[2];  /* Tube utilisé pour synchroniser le parent et l’enfant */
       };

       static int verbose;

       static void
       usage(char *pname)
       {
           fprintf(stderr, "Utilisation: %s [options] cmd [arg...]\n\n", pname);
           fprintf(stderr, "Créer un processus enfant qui exécute une invite "
                   "de commandes dans un nouvel espace de noms utilisateur et\n"
                   "éventuellement au moins un nouvel espace de noms.\n\n");
           fprintf(stderr, "Les options sont :\n\n");
       #define fpe(str) fprintf(stderr, "    %s", str);
           fpe("-i          Nouvel espace de noms IPC\n");
           fpe("-m          Nouvel espace de noms de montage\n");
           fpe("-n          Nouvel espace de noms réseau \n");
           fpe("-p          Nouvel espace de noms PID\n");
           fpe("-u          Nouvel espace de noms UTS\n");
           fpe("-U          Nouvel espace de noms utilisateur\n");
           fpe("-M uid_map  Mappage UID pour l'espace de noms utilisateur\n");
           fpe("-G gid_map  Mappage GID pour l'espace de noms utilisateur\n");
           fpe("-z          Mappage des UID et GID à 0 dans l'espace de noms
                            utilisateur\n");
           fpe("            (équivalent à : -M '0 <uid> 1' -G '0 <gid> 1')\n");
           fpe("-v          Affichage détaillé\n");
           fpe("\n");
           fpe("Si -z, -M, or -G est invoqué, -U doit être précisé.\n");
           fpe("Il n'est pas possible d'utiliser -z et soit -M, soit -G.\n");
           fpe("\n");
           fpe("Les chaînes de mappages pour -M et -G se composent"
               "d'enregistrements de la forme :\n");
           fpe("\n");
           fpe("    ID-inside-ns   ID-outside-ns   len\n");
           fpe("\n");
           fpe("Une chaîne de mappage peut contenir plusieurs"
               "enregistrements séparés par des virgules;\n");
           fpe("les virgules sont remplacées par des retours à la ligne"
               "avant l'écriture des fichiers de mappage.\n");

           exit(EXIT_FAILURE);
       }

       /* Mise à jour du fichier de mappage 'map_file', avec la valeur fournie
          dans 'mapping', une chaîne qui définit un mappage d'identifiant
          utilisateur ou groupe. Un mappage d'identifiant d'utilisateur ou groupe
          se compose d'un ou plusieurs enregistrements séparés par des retours
          à la ligne de la forme suivante :

              ID_dans-Espace    ID-hors-Espace   longueur

         La nécessité de fournir une chaîne qui contienne des retours
         à la ligne ne convient pas bien à une utilisation en ligne de commande.
         C'est pour cette raison que l'utilisation des virgules pour délimiter les
         champs de la chaîne est autorisée. Celles-ci sont remplacées par des
         retours à la ligne avant l'écriture de la chaîne dans le fichier. */

       static void
       update_map(char *mapping, char *map_file)
       {
           int fd;
           size_t map_len;     /* Longueur de 'mapping' */

           /* Remplacer les virgules de la chaîne de mappage
              par des retours à la ligne */

           map_len = strlen(mapping);
           for (size_t j = 0; j < map_len; j++)
               if (mapping[j] == ',')
                   mapping[j] = '\n';

           fd = open(map_file, O_RDWR);
           if (fd == -1) {
               fprintf(stderr, "ERROR: open %s: %s\n", map_file,
                       strerror(errno));
               exit(EXIT_FAILURE);
           }

           if (write(fd, mapping, map_len) != map_len) {
               fprintf(stderr, "ERROR: write %s: %s\n", map_file,
                       strerror(errno));
               exit(EXIT_FAILURE);
           }

           close(fd);
       }

       /* Linux 3.19 a modifié la gestion de setgroups(2) et le fichier
          'gid_map' pour corriger le problème de sécurité. Celui-ci
          permet aux utilisateurs *non privilégiés* d’employer des espaces de noms
          utilisateur pour supprimer des groupes. Le résultat des modifications de 3.19
          est que pour mettre à jour le fichier 'gid_maps',
          l’utilisation de l’appel système setgroups() dans cet espace de noms
          utilisateur doit d’abord être désactivée en écrivant « deny » dans
          un des fichiers /proc/PID/setgroups pour cet espace de noms. C’est
          le but de la fonction suivante. */

       static void
       proc_setgroups_write(pid_t child_pid, char *str)
       {
           char setgroups_path[PATH_MAX];
           int fd;

           snprintf(setgroups_path, PATH_MAX, "/proc/%jd/setgroups",
                   (intmax_t) child_pid);

           fd = open(setgroups_path, O_RDWR);
           if (fd == -1) {

               /* Nous sommes peut être sur un système qui ne gère pas
                  /proc/PID/setgroups. Dans ce cas, le fichier n’existe pas
                  et le système n’impose pas les restrictions que Linux 3.19
                  a ajoutées. Bien, nous n’avons pas besoin de faire quelque
                  chose pour permettre la mise à jour de « gid_map ».

                  Cependant, si l’erreur d’open() était quelque chose autre que
                  l’erreur ENOENT attendue dans ce cas, faisons que l’utilisateur
                  le sache. */

               if (errno != ENOENT)
                   fprintf(stderr, "ERROR: open %s: %s\n", setgroups_path,
                       strerror(errno));
               return;
           }

           if (write(fd, str, strlen(str)) == -1)
               fprintf(stderr, "ERROR: write %s: %s\n", setgroups_path,
                   strerror(errno));

           close(fd);
       }

       static int              /* Lancer la fonction pour l’enfant cloné */
       childFunc(void *arg)
       {
           struct child_args *args = arg;
           char ch;

           /* Attendre que le parent ait mis à jour les mappages d'identifiants
              d'utilisateur et de groupe. Consultez le commentaire de main(). On
              attend le signal de fin de fichier dans le tube qui sera fermé par le
              processus parent lorsque les mappages seront mis à jour. */

          close(args->pipe_fd[1]);    /* Fermer notre descripteur à la fin
                                          d’écriture du tube afin de présenter EOF
                                          lorsque le parent ferme son descripteur */
           if (read(args->pipe_fd[0], &ch, 1) != 0) {
               fprintf(stderr,
                       "Échec dans l’enfant : donnée renvoyée par le tube != 0\n");
               exit(EXIT_FAILURE);
           }

           close(args->pipe_fd[0]);

           /* Lancer une commande de shell */

           printf("About to exec %s\n", args->argv[0]);
           execvp(args->argv[0], args->argv);
           err(EXIT_FAILURE, "execvp");
       }

       #define STACK_SIZE (1024 * 1024)

       static char child_stack[STACK_SIZE];    /* Espace pour la pile de l’enfant */

       int
       main(int argc, char *argv[])
       {
           int flags, opt, map_zero;
           pid_t child_pid;
           struct child_args args;
           char *uid_map, *gid_map;
           const int MAP_BUF_SIZE = 100;
           char map_buf[MAP_BUF_SIZE];
           char map_path[PATH_MAX];

           /* Analyser les options de la ligne de commande. Le caractère
              « + » initial de l'argument final de getopt() empêche la
              permutation des options de la ligne de commande de style
              GNU. Cela peut être utile dans les cas où la « commande »
              exécutée par le programme lui-même a des options de ligne de
              commande. Cela évite que getopt() ne traite ces options comme
              étant celles du programme */

           flags = 0;
           verbose = 0;
           gid_map = NULL;
           uid_map = NULL;
           map_zero = 0;
           while ((opt = getopt(argc, argv, "+imnpuUM:G:zv")) != -1) {
               switch (opt) {
               case 'i': flags |= CLONE_NEWIPC;        break;
               case 'm': flags |= CLONE_NEWNS;         break;
               case 'n': flags |= CLONE_NEWNET;        break;
               case 'p': flags |= CLONE_NEWPID;        break;
               case 'u': flags |= CLONE_NEWUTS;        break;
               case 'v': verbose = 1;                  break;
               case 'z': map_zero = 1;                 break;
               case 'M': uid_map = optarg;             break;
               case 'G': gid_map = optarg;             break;
               case 'U': flags |= CLONE_NEWUSER;       break;
               default:  usage(argv[0]);
               }
           }

           /* -M ou -G sans -U est incohérent */

           if (((uid_map != NULL || gid_map != NULL || map_zero) &&
                       !(flags & CLONE_NEWUSER)) ||
                   (map_zero && (uid_map != NULL || gid_map != NULL)))
               usage(argv[0]);

           args.argv = &argv[optind];

           /* L'utilisation d'un tube pour réaliser la synchronisation du parent et
              de l’enfant a pour but d'obliger le parent à définir les mappages
              d'identifiants utilisateur et groupe avant que l’enfant n'appelle
              execve(). Cela permet d'assurer que l’enfant conserve ses capacités
              pendant l'exécution de execve() dans le cas classique où l'on souhaite
              mapper l’identifiant utilisateur effectif de l’enfant avec 0 dans le
              nouvel espace de noms utilisateur. Sans cette synchronisation, l’enfant
              perdrait ses capacités s'il effectuait execve() avec un identifiant
              utilisateur autre que 0 (consultez la page du manuel consacrée
              à capabilities(7) pour plus de détails sur la modification des capacités
              d'un processus lors de l'exécution de execve()). */

           if (pipe(args.pipe_fd) == -1)
               err(EXIT_FAILURE, "pipe");

           /* Création de l’enfant dans le ou les nouveaux espaces de noms. */

           child_pid = clone(childFunc, child_stack + STACK_SIZE,
                             flags | SIGCHLD, &args);
           if (child_pid == -1)
               err(EXIT_FAILURE, "clone");

           /* Le parent se retrouve ici. */

           if (verbose)
               printf("%s: le PID de l’enfant créé par clone() est %jd\n",
                       argv[0], (intmax_t) child_pid);

           /* Mise à jour des mappages de l'UID et du PID pour l’enfant. */

           if (uid_map != NULL || map_zero) {
               snprintf(map_path, PATH_MAX, "/proc/%jd/uid_map",
                       (intmax_t) child_pid);
               if (map_zero) {
                   snprintf(map_buf, MAP_BUF_SIZE, "0 %jd 1",
                           (intmax_t) getuid());
                   uid_map = map_buf;
               }
               update_map(uid_map, map_path);
           }

           if (gid_map != NULL || map_zero) {
               proc_setgroups_write(child_pid, "deny");

               snprintf(map_path, PATH_MAX, "/proc/%jd/gid_map",
                       (intmax_t) child_pid);
               if (map_zero) {
                   snprintf(map_buf, MAP_BUF_SIZE, "0 %ld 1",
                           (intmax_t) getgid());
                   gid_map = map_buf;
               }
               update_map(gid_map, map_path);
           }

           /* Fermer le côté écriture du tube afin d'indiquer à l’enfant
              que les mappages d'UID et de GID ont été mis à jour */

           close(args.pipe_fd[1]);

           if (waitpid(child_pid, NULL, 0) == -1)      /* Attente de l’enfant */
               err(EXIT_FAILURE, "waitpid");

           if (verbose)
               printf("%s: fin d'exécution\n", argv[0]);

           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       newgidmap(1), newuidmap(1), clone(2), ptrace(2), setns(2),  unshare(2),  proc(5),  subgid(5),  subuid(5),
       capabilities(7), cgroup_namespaces(7), credentials(7), namespaces(7), pid_namespaces(7)

       Le fichier Documentation/admin-guide/namespaces/resource-control.rst des sources du noyau.

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>,    Cédric    Boutillier     <cedric.boutillier@gmail.com>,     Frédéric     Hantrais
       <fhantrais@gmail.com> et Jean-Paul Guillonneau <guillonneau.jeanpaul@free.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.03                    5 février 2023                               user_namespaces(7)