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

NAMN

       user_namespaces — översikt över Linux användarnamnrymder

BESKRIVNING

       För en översikt över namnrymder, se namespaces(7).

       Användarnamnrymder  isolerar  säkerhetsrelaterade  identifierare  och attribut, mer exakt,
       användar-ID:n och grupp-ID:n (se credentials(7)), rotkatalogen,  nycklar  (se  keyring(7))
       och  förmågor  (se  capabilities(7)).  En  process användar- och grupp-ID:n kan vara olika
       inuti och utanför  en  användarnamnrymd.  I  synnerhet  kan  en  process  ha  ett  normalt
       oprivilegierat  användar-ID  utanför  en  användarnamnrymd  medan  den  på  samma gång har
       användar-ID:t 0 inuti namnrymden; med andra ord, processen  har  fullständiga  rättigheter
       vid  åtgärder  inuti  användarnamnrymden,  men  är  oprivilegierad  vid  åtgärder  utanför
       namnrymden.

   Nästade namnrymder, medlemskap i namnrymder
       Användarnamnrymder kan nästas; det vill säga, varje användarnamnrymd — utom  den  initiala
       (”rot-”)namnrymden  —  har  en  föräldraanvändarnamnrymd,  och  kan  ha  noll  eller flera
       barnanvändarnamnrymder. Föräldraanvändarnamnrymden är användarnamnrymden för processen som
       skapar  användarnamnrymden  via  ett  anrop  av  unshare(2)  eller  clone(2)  med  flaggan
       CLONE_NEWUSER.

       Kärnan lägger (från Linux 3.11) en gräns på  32  nästade  nivåer  med  användarnamnrymder.
       Anrop  av  unshare(2)  eller  clone(2) som annars skulle orsaka att denna gräns överskrids
       misslyckas med felet EUSERS.

       Varje process är medlem i exakt en användarnamnrymd. En process  som  skapas  via  fork(2)
       eller  clone(2)  utan  flaggan  CLONE_NEWUSER  är medlem av samma användarnamnrymd som sin
       förälder. En enkeltrådad process kan gå in i en annan användarnamnrymd med setns(2) om den
       har  CAP_SYS_ADMIN i den namnrymden; när den gör det får den en fullständig uppsättning av
       förmågor i den namnrymden.

       Ett anrop av clone(2) eller unshare(2) med flaggan CLONE_NEWUSER gör den nya barnprocessen
       (för  clone(2))  eller anroparen (för unshare(2)) medlem av den nya användarnamnrymden som
       skapas av anropet.

       Åtgärden NS_GET_PARENT till ioctl(2) kan  användas  för  att  upptäcka  föräldrarelationen
       mellan användarnamnrymder; se ioctl_ns(2).

   Förmågor
       Barnprocesserna   som  skapas  med  clone(2)  med  flaggan  CLONE_NEWUSER  börjar  med  en
       fullständig uppsättning av förmågor i den nya användarnamnrymden. Likadant får en  process
       som   skapar   en  ny  användarnamnrymd  med  unshare(2)  eller  går  in  i  en  befintlig
       användarnamnrymd med setns(2) en fullständig uppsättning rättigheter i den  namnrymden.  Å
       andra  sidan  har  den  processen  inga  förmågor  i  förälderns (i fallet clone(2)) eller
       tidigare (i fallet unshare(2)  och  setns(2))  användarnamnrymd,  även  om  root-anvädaren
       skapade  eller  gick  in  i  den  nya  namnrymden  (d.v.s., en process med användar-ID 0 i
       rotnamnrymden).

       Observera att ett anrop av execve(2) kommer göra att processens förmågor räknas om på  det
       vanliga  sättet  (se  capabilities(7)).  Alltså,  om inte processen har användar-ID 0 inom
       namnrymden, eller den körbara filen har en ärvbar förmågemask  som  inte  är  tom,  kommer
       processen  förlora  alla  förmågor. Se diskussionen om användar- och grupp-ID-avbildningar
       nedan.

       Ett anrop av clone(2) eller unshare(2)  med  flaggan  CLONE_NEWUSER  eller  ett  anrop  av
       setns(2)   som   flyttar  anroparen  in  i  en  annan  användarnamnrymd  sätter  flaggorna
       ”securebits” (se capabilities(7)) till sitt standardvärde (alla flaggor avslagna) i barnet
       (för  clone(2))  eller  anroparen  (för unshare(2) eller setns(2)). Observera att eftersom
       anroparen inte längre  har  förmågor  i  sin  originalanvändarnamnrymd  efter  anropet  av
       setns(2) är det inte möjligt för en process att återställa sina flaggor ”securebits” medan
       den behåller sitt medlemskap i användarnamnrymden genom att använda ett par  av  anrop  av
       setns(2)  för  att  flytta  till  en  annan  användarnamnrymd och sedan återvända till sin
       originalanvändarnamnrymd.

       Reglerna för att avgöra  huruvida  en  process  har  en  förmåga  eller  inte  i  en  viss
       användarnamnrymd är som följer:

       •  En  process har en förmåga inuti en användarnamnrymd om den är medlem av den namnrymden
          och den har förmågan i sin effektiva förmågemängd. En process kan  få  förmågor  i  sin
          effektiva   förmågemängd   på   olika   sätt.   Till   exempel   kan   den   köra   ett
          sätt-användar-ID-program eller en körbar fil associerad med filförmågor.  Dessutom  kan
          en  process  få förmågor via effekten av clone(2), unshare(2) eller setns(2), som redan
          beskrivits.

       •  Om en process har en förmåga  i en användarnamnrymd, då har den  den  förmågan  i  alla
          barn- (och mer avlägsna avkomme-)namnrymder också.

       •  När  en användarnamnrymd skapas sparar kärnan det effektiva användar-ID:t för processen
          som skapar den som varandes ”ägaren” till namnrymden. En process som  bor  i  föräldern
          till  användarnamnrymden  och  vars  effektiva  användar-ID  stämmer  med  ägaren  till
          namnrymden har alla förmågor i namnrymden. Tack vare  föregående  regel  har  processen
          alla   förmågor   i   alla   mer  avlägsna  avkommeanvändarnamnrymder  också.  Åtgärden
          NS_GET_OWNER_UID  till  ioctl(2)  kan  användas  för  att  upptäcka   användar-ID   för
          namnrymdens ägare; se ioctl_ns(2).

   Effekten av förmågor inom en användarnamnrymd
       Att  ha  en förmåga inuti en användarnamnrymd tillåter en process att utföra åtgärder (som
       kräver privilegier) endast på resurser som styrs av den namnrymden. Med andra ord, att  ha
       en förmåga i en användarnamnrymd tillåter en process att utföra privilegierade åtgärder på
       resurser som  styrs  av  (icke  användar-)namnrymder  som  ägs  av  (är  associerade  med)
       användarnamnrymden (se nästa underavdelning).

       Däremot  finns  det  många  privilegierade  åtgärder  som  påverkar  resurser  som inte är
       associerade  med  någon  namnrymdstyp,  till  exempel,  att  ändra  systemtiden   (d.v.s.,
       kalendertiden)   (som  styrs  av  CAP_SYS_TIME),  att  ladda  kärnmoduler  (som  styrs  av
       CAP_SYS_MODULE) och att skapa en enhet (som styrs av CAP_MKNOD).  Endast  en  process  med
       privilegier i den initiala användarnamnrymden kan utföra sådana åtgärder.

       Att hålla CAP_SYS_ADMIN inom användarnamnrymden som äger en process monteringsnamnrymd gör
       att den processen kan skapa bindmonteringar och montera följande typer av filsystem:

           •  /proc (från Linux 3.8)
           •  /sys (från Linux 3.8)
           •  devpts (från Linux 3.9)
           •  tmpfs(5)  (från Linux 3.9)
           •  ramfs (från Linux 3.9)
           •  mqueue (från Linux 3.9)
           •  bpf (från Linux 4.4)
           •  overlayfs (från Linux 5.11)

       Att hålla CAP_SYS_ADMIN inom användarnamnrymden som äger en  process  cgroup-namnrymd  gör
       (från  Linux 4.6) att den processen kan montera filsystemet cgroup version 2 och namngivna
       hierarkier av filsystemet cgroup verson 1 (d.v.s., cgroup-filsystem monterade med  flaggan
       "none,name=").

       Att hålla CAP_SYS_ADMIN inom användarnamnrymden som äger en process PID-namnrymd gör (från
       Linux 3.8) att den processen kan montera filsystemet /proc.

       Observera dock att montering av blockbaserade filsystem endast kan göras av en process som
       håller CAP_SYS_ADMIN i den initiala användarnamnrymden.

   Interaktion mellan användarnamnrymder och andra typer av namnrymder
       Med  början  från Linux 3.8 kan oprivilegierade processer skapa användarnamnrymder, och de
       andra typerna av namnrymder kan  skapas  med  bara  förmågan  CAP_SYS_ADMIN  i  anroparens
       användarnamnrymd.

       När  en  annan  namnrymd  än  en  användarnamnrymd  skapas  ägs  den av användarnamnrymden
       processen som skapade  den  var  en  medlem  i  vid  tidpunkten  då  namnrymden  skapades.
       Privilegierade  åtgärder  på  resurser  som  styrs  av en icke-användarnamnrymd kräver att
       processen   har   de   nödvändiga   förmågorna   i   användarnamnrymden   som   äger   den
       icke-användarnamnrymden.

       Om  CLONE_NEWUSER  anges  tillsammans  med andra flaggor CLONE_NEW* i ett enskilt anrop av
       clone(2) eller unshare(2) garanteras det att användarnamnrymden skapas  först  vilket  ger
       barnet  (clone(2)) eller anroparen (unshare(2)) privilegier över de andra namnrymderna som
       skapas av anropet. Det är alltså möjligt för en oprivilegierad  anropare  att  ange  denna
       kombination av flaggor.

       När  en  ny  namnrymd  (annan än en användarnamnrymd) skapas via clone(2) eller unshare(2)
       registrerar kärnan användarnamnrymden för processen som skapar den som ägare till den  nya
       namnrymden.  (Denna  koppling kan inte ändras.) När en process i den nya namnrymden senare
       utför privilegierade åtgärder som verkar  på  globala  resurser  isolerade  av  namnrymden
       utförs  rättighetskontrollerna  enligt processens förmågor i användarnamnrymden som kärnan
       associerade med den nya namnrymden. Till exempel, antag  att  en  process  försöker  ändra
       värdnamnet  (sethostname(2)),  en  resurs som styrs av UTS-namnrymden. I detta fall kommer
       kärnan avgöra vilken användarnamnrymd som äger processens  UTS-namnrymd,  och  kontrollera
       huruvida processen har den nödvändiga förmågan (CAP_SYS_ADMIN) i den användarnamnrymden.

       ioctl(2)-åtgärden  NS_GET_USERNS kan användas för att hitta användarnamnrymden som äger en
       icke-användarnamnrymd; se ioctl_ns(2).

   Användar- och grupp-ID-avbildningar: uid_map och gid_map
       När  en  användarnamnrymd  skapas  börjar  den  utan  någon  avbildning  av  användar-ID:n
       (grupp-ID:n)    till    förälderns   användarnamnrymd.   Filerna   /proc/pid/uid_map   och
       /proc/pid/gid_map (tillgängliga från Linux 3.5) visar  avbildningarna  för  användar-  och
       grupp-ID:n  inuti användarnamnrymden för processen pid. Dessa filer kan läsas för att visa
       avbildningarna i en  användarnamnrymd  och  skrivas  till  (en  gång)  för  att  definiera
       avbildningarna.

       Beskrivningen  i  följande  stycken  förklarar  detaljerna  för  uid_map; gid_map är exakt
       likadan, med varje förekomst av ”användar-ID” ersatt med ”grupp-ID”.

       Filen uid_map visar avbildningen av användar-ID:n från  användarnamnrymden  för  processen
       som  öppnade  uid_map  (men  se  en  avvikelse  från denna punkt nedan). Med andra ord kan
       potentiellt processer som finns i olika användarnamnrymder se olika värden  när  de  läser
       från  en viss uid_map-fil, beroende på användar-ID-avbildningarna för användarnamnrymderna
       för de läsande processerna.

       Varje rad i filen uid_map anger en 1-till-1-avbildning av ett intervall av  sammanhängande
       användar-ID:n  mellan  två  användarnamnrymder.  (När  en användarnamnrymd först skapas är
       denna fil tom.) Specifikationen på varje rad har formen tre tal avgränsade av  mellanslag.
       De   första   två   talen   anger   det   första   användar-ID:t   i  vardera  av  de  två
       användarnamnrymderna. Det tredje talet anger längden på  det  avbildade  intervallet.  Mer
       exakt tolkas fälten som följer:

       (1)  Början av intervallet av användar-ID:n i processen pids användarnamnrymd.

       (2)  Början på intervallet av användar-ID:n till vilka användar-ID:n som anges av fält ett
            avbildas. Hur fält två tolkas beror på huruvida processen  som  öppnade  uid_map  och
            processen pid finns i samma användarnamnrymd, som följer:

            (a)  Om  de  två  processerna finns i olika användarnamnrymder: fält två är början på
                 ett intervall av användar-ID:n i användarnamnrymden för  processen  som  öppnade
                 uid_map.

            (b)  Om  de  två  processerna  finns  i samma användarnamnrymd: fält två är början på
                 intervallet av användar-ID:n i process pids föräldraanvändarnamnrymd. Detta  gör
                 att   den   som   öppnar   uid_map   (det   vanliga  fallet  här  är  att  öppna
                 /proc/self/uid_map) kan se avbildningen av användar-ID:n in i användarnamnrymden
                 för processen som skapade denna användarnamnrymd.

       (3)  Längden    på   intervallet   av   användar-ID:n   som   avbildas   mellan   de   två
            användarnamnrymderna.

       Systemanrop som returnerar användar-ID:n (grupp-ID:n) — till exempel getuid(2), getgid(2),
       och  kreditivfälten  i  posten  som  returneras  av  stat(2)  —  returnerar  användar-ID:t
       (grupp-ID:t) avbildat in i anroparens användarnamnrymd.

       När en process begär tillgång till en fil avbildas dess användar- och grupp-ID:n in i  den
       initiala användarnamnrymden i syfte att kontrollera rättigheterna och tilldela ID:n när en
       fil skapas. När en process hämtar filens användar- och  grupp-ID:n  via  stat(2)  avbildas
       ID:erna  i  den  andra  riktningen, för att skapa värden relativt processens användar- och
       grupp-ID-avbildningar.

       Den initiala användarnamnrymden har ingen föräldranamnrymd, men  för  konsistensens  skull
       tillhandahåller   kärnan   tomfiler   för  användar-  och  grupp-ID-avbildningar  för  den
       namnrymden. Tittar man på filen uid_map (gid_map är likadan) från ett skal i den  initiala
       namnrymden ser man:

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

       Denna  avbildning säger oss att intervallet som startar med användar-ID 0 i denna namnrymd
       översätts till ett intervall som startar med 0 i den (obefintliga) föräldranamnrymden, och
       att  längden  på  intervallet  är  det största 32-bitars teckenlösa heltalet. Detta lämnar
       4294967295 (32-bitsvärdet -1) oavbildat. Detta är avsiktligt: (uid_t) -1 används  i  flera
       gränssnitt  (t.ex., setreuid(2)) som ett sätt att ange ”inget användar-ID”. Genom att låta
       (uid_t) -1 vara oavbildat och oanvändbart garanteras att  det  inte  kommer  uppstå  någon
       förvirring vid användning av dessa gränssnitt.

   Att definiera användar- och grupp-ID-avbildningar: att skriva till uid_map och gid_map
       Efter  att  en  ny  användarnamnrymd  skapats  kan  filen  uid_map för en av processerna i
       namnrymden skrivas till en gång för att definiera avbildningen av användar-ID:n i den  nya
       användarnamnrymden.  Ett  försök  att  skriva  mer  än  en  gång  till en uid_map-fil i en
       användarnamnrymd misslyckas med felet EPERM. Motsvarande regler gäller för gid_map-filer.

       Raderna som skrivs till uid_map (gid_map) måste lyda följande giltighetsregler:

       •  De tre fälten måste vara giltiga tal, och det sista fältet måste vara större än 0.

       •  Rader avslutas av nyradstecken.

       •  Det finns en gräns på antalet rader i filen. I Linux 4.14  och  tidigare  sattes  denna
          gräns  (godtyckligt) till 5 rader. Från Linux 4.15 är gränsen 340 rader. Dessutom måste
          antalet byte som skrivs till filen vara mindre än systemets sidstorlek, och skrivningen
          måste  göras från början av filen (d.v.s., lseek(2) och pwrite(2) kan inte användas för
          att skriva till nollskilda avstånd in i filen).

       •  Intervallet av användar-ID:n (grupp-ID:n) som anges på varje rad får inte överlappa med
          intervallerna  på  några  andra  rader. I den ursprungliga implementationen (Linux 3.8)
          uppfylldes detta krav av en enkel implementation som lade till det  ytterligare  kravet
          att  värdena  i både fält 1 och fält 2 av följande rader måste vara i stigande numerisk
          ordning, vilket förhindrade några eljest giltiga avbildningar från  att  skapas.  Linux
          3.9  och  senare  fixar  denna  begränsning, och tillåter alla giltiga uppsättningar av
          avbildningar som inte överlappar.

       •  Åtminstone en rad måste skrivas till filen.

       Skrivningar som bryter mot ovanstående regler misslyckas med felet EINVAL.

       För att en process skall kunna skriva till filen /procpid/uid_map (/procpid/gid_map) måste
       alla följande rättighetskrav vara uppfyllda:

       •  Den  skrivande  processen  måste  ha  förmågan CAP_SETUID (CAP_SETGID) i processen pids
          användarnamnrymd.

       •  Den skrivande processen måste antingen finnas i namnrymden för process pid eller finnas
          i föräldraanvändarnamnrymden till process pid.

       •  De  avbildade  användar-ID:na  (grupp-ID:na)  måste  i  sin  tur  ha  en  avbildning  i
          föräldraanvändarnamnrymden.

       •  Om man uppdaterar /proc/pid/uid_map för att skapa en avbildning som avbildar till UID 0
          i föräldranamnrymden måste en av de följande vara sann:

          (a)  om  den  skrivande  processen  finns i föräldraanvändarnamnrymden, då måste den ha
               förmågan CAP_SETFCAP i den användarnamnrymden; eller

          (b)  om den skrivande processen finns i barnanvändarnamnrymden, då måste processen  som
               skapade användarnamnrymden ha haft förmågan CAP_SETFCAP när namnrymden skapades.

          Denna  regel  har  funnits  från  Linux 5.12. Den eliminerar en tidigare säkerhetsbrist
          varigenom en UID 0-process som saknar förmågan CAP_SETFCAP vilken behövs för att  skapa
          en  binär  med  namnrymdsfilförmågor (så som det beskrivs i capabilities(7)) ändå kunde
          skapa en sådan binär genom följande steg:

          (1)  Skapa en ny användarnamnrymd med identitetsavbildningen (d.v.s., AID 0 i  den  nya
               användarnamnrymden  avbildas  på  AID  0  i föräldranamnrymden), så att AID 0 båda
               namnrymderna är ekvivalent med samma root-användar-ID.

          (2)  Eftersom barnprocessen har förmågan CAP_SETFCAP  kunde  den  skapa  en  binär  med
               namnrymdsfilförmågor  som  sedan  skulle  vara verkningsfulla i föräldranamnrymden
               (eftersom root-användar-ID:t är desamma i de två namnrymderna).

       •  En av följande två fall gäller:

          (a)  Antingen  har  den  skrivande  processen  förmågan   CAP_SETUID   (CAP_SETGID)   i
               föräldraanvändarnamnrymden.

               •  Inga  ytterligare  begränsningar  gäller:  processen kan göra avbildningar till
                  godtyckliga användar-ID:n (grupp-ID:n) i föräldraanvändarnamnrymden.

          (b)  Eller i annat fall gäller alla följande beskrivningar:

               •  Data som skrivs till uid_map (gid_map) måste bestå av en enda rad som  avbildar
                  den     skrivande     processens    effektiva    användar-ID    (grupp-ID)    i
                  föräldraanvändarnamnrymden    till     ett     användar-ID     (grupp-ID)     i
                  användarnamnrymden.

               •  Den  skrivande processen måste ha samma effektiva användar-ID som processen som
                  skapade användarnamnrymden.

               •  När det gäller gid_map måste först  användning  av  systemanropet  setgroups(2)
                  nekas  genom  att  skriva "deny" till filen /proc/pid/setgroups (se nedan) före
                  någon skrivning till gid_map.

       Skrivningar som strider mot ovanstående regler misslyckas med felet EPERM.

   Projekt-ID-avbildningar: projid_map
       Liksom   för   användar-   och   grupp-ID-avbildningar   är   det   möjligt   att    skapa
       projekt-ID-avbildningar  för  användarnamnrymder. (Projekt-ID:n används för diskkvoter; se
       setquota(8) och quotactl(2).)

       Projekt-ID-avbildningar definieras genom att skriva till filen  /proc/pid/projid_map  (som
       finns från Linux 3.7).

       Giltighetsreglerna  för  att  skriva till filen /proc/pid/projid_map är som för att skriva
       till filen uid_map; brott mot dessa regler får write(2) att misslyckas med felet EINVAL.

       Rättighetsreglerna för att skriva till filen /proc/pid/projid_map är som följer:

       •  Den skrivande processen måste antingen finnas i namnrymden för process pid eller finnas
          i föräldraanvändarnamnrymden till process pid.

       •  De    avbildade    projekt-ID:na    måste    i    sin    tur   ha   en   avbildning   i
          föräldraanvändarnamnrymden.

       Brott mot dessa regler får write(2) att misslyckas med felet EPERM.

   Interaktion med systemanrop som ändrar process-AID:n eller -GID:n
       I en användarnamnrymd där filen uid_map inte har skrivits kommer  systemanrop  som  ändrar
       användar-ID:n  att misslyckas. På liknande sätt, om filen gid_map inte har skrivits kommer
       systemanrop som ändrar grupp-ID:n att misslyckas. Efter att filerna  uid_map  och  gid_map
       har  skrivits  kan endast de avbildade värdena användas i systemanrop som ändrar användar-
       och grupp-ID:n.

       För  användar-ID:n  inkluderar  de   relevanta   systemanropen   setuid(2),   setfsuid(2),
       setreuid(2)  och  setresuid(2).  För  grupp-ID:n  inkluderar  de  relevanta  systemanropen
       setgid(2), setfsgid(2), setregid(2), setresgid(2) och setgroups(2).

       Att skriva "deny" till filen /proc/pid/setgroups före man skriver  till  /proc/pid/gid_map
       kommer permanent avaktivera setgroups(2) i en användarnamnrymd och tillåta att man skriver
       till /proc/pid/gid_map utan att ha förmågan CAP_SETGID i föräldraanvändarnamnrymden.

   Filen /proc/pid/setgroups
       Filen /proc/pid/setgroups visar strängen "allow" om  processer  i  användarnamnrymden  som
       innehåller process pid får lov att använda systemanropet setgroups(2); den visar "deny" om
       setgroups(2) inte tillåts i den användarnamnrymden. Observera att oavsett värdet  i  filen
       /proc/pid/setgroups (och oavsett processens förmågor) är inte heller setgroups(2) tillåtet
       om inte /proc/pid/gid_map har satts ännu.

       En privilegierad process (en med förmågan CAP_SYS_ADMIN i namnrymden) kan skriva endera av
       strängarna "allow" eller "deny" till denna fil före den skriver en grupp-ID-avbildning för
       denna användarnamnrymd till filen /proc/pid/gid_map. Att skriva strängen "deny" förhindrar
       alla processer i användarnamnrymden från att använda setgroups(2).

       Essensen  av  begränsningarna  som beskrivs i föregående stycke är att det är tillåtet att
       skriva till /proc/pid/setgroups endast så länge som anrop av setgroups(2) är otillåtet för
       att  /proc/pid/gid_map  inte har satts. Detta säkerställer att en process inte kan gå över
       från ett tillstånd där setgroups(2) är tillåtet till ett tillstånd där setgroups(2) nekas;
       en  process kan gå över endast från att setgroups(2) är otillåtet till att setgroups(2) är
       tillåtet.

       Standardvärdet i denna fil i den initiala användarnamnrymden är "allow".

       När /proc/pid/gid_map har skrivits till (vilket har effekten av att aktivera  setgroups(2)
       i  användarnamnrymden),  är  det inte längre möjligt att göra setgroups(2) otillåtet genom
       att skriva "deny" till /proc/pid/setgroups (skrivningen misslyckas med felet EPERM).

       En barnnamnrymd ärver inställningen av /proc/pid/setgroups från sin förälder.

       Om filen setgroups har värdet  "deny",  då  kan  inte  senare  systemanropet  setgroups(2)
       återaktiveras  (genom att skriva "allow" till filen) i den användarnamnrymden. (Försök att
       göra  så  misslyckas  med  felet  EPERM.)  Denna  begränsning  propagerar  ner  till  alla
       barnanvändarnamnrymder till denna användarnamnrymd.

       Filen /proc/pid/setgroups lades till i Linux 3.19, men bakåtporterades till många tidigare
       stabila kärnserier, eftersom den åtgärdar ett säkerhetsproblem. Problemet rörde filer  med
       rättigheter såsom ”rwx---rwx”. Sådana filer ger färre rättigheter till ”gruppen” än de gör
       till ”övriga”. Detta betyder att genom att släppa grupper med setgroups(2) kan en  process
       tillåtas  filåtkomst  som  den  inte  tidigare hade. Före det fanns användarnamnrymder var
       detta inte ett bekymmer,  eftersom  endast  en  privilegierad  process  (en  med  förmågan
       CAP_SETGID) kunde anropa setgroups(2). Dock, med introduktionen av användarnamnrymder blev
       det möjligt för en oprivilegierad process att skapa en ny namnrymd i vilken användaren har
       alla  privilegier.  Detta  tillät  sedan  tidigare  oprivilegierade  användare  att släppa
       grupprivilegier  och  därmed  få   filåtkomst   som   de   inte   tidigare   hade.   Filen
       /proc/pid/setgroups lades till för att åtgärda detta säkerhetsproblem, genom att neka alla
       vägar för en oprivilegierad process att släppa grupper med setgroups(2).

   Oavbildade användar- och grupp-ID:n
       Det finns olika platser  där  ett  oavbildat  användar-ID  (grupp-ID)  kan  exponeras  för
       användarrymden.  Till  exempel  kan  den  första processen i en ny användarnamnrymd anropa
       getuid(2) innan en användar-ID-avbildning har definierats  för  namnrymden.  I  de  flesta
       sådana  fall  konverteras  ett oavbildat användar-ID till spillanvändar-ID:t (grupp-ID:t);
       standardvärdet  på  spillanvändar-ID:t  (grupp-ID:t)   65534).   Se   beskrivningarna   av
       /proc/sys/kernel/overflowuid och /proc/sys/kernel/overflowgid i proc(5).

       Fallen  där  oavbildade  ID:n avbildas på detta sätt inkluderar systemanrop som returnerar
       användar-ID:n  (getuid(2),  getgid(2)  och  liknande),  kreditiv  som  skickas  över   ett
       UNIX-domänsuttag,  kreditiv  som  returneras  av  stat(2),  waitid(2)  och  System  V  IPC
       ”ctl”-åtgärder  IPC_STAT,  kreditiv  som  exponeras  av  /proc/pid/status  och  filerna  i
       /proc/sysvipc/*,  kreditiv  som  returneras via fältet si_uid i den siginfo_t som tas emot
       med en signal (se sigaction(2)),  kreditiv  som  skrivs  till  processbokföringsfilen  (se
       acct(5))  och  kreditiv  som  returneras  via  POSIX  notifieringar  i  meddelandeköer (se
       mq_notify(3)).

       Det finns ett nämnvärt fall där oavbildade användar- och grupp-ID:n inte konverteras  till
       motsvarande  spill-ID-värde.  När  man betraktar en fil uid_map eller gid_map i vilken det
       inte finns någon avbildning för det andra fältet visas det fältet som 4294967295  (-1  som
       ett teckenlöst heltal).

   Åtkomst av filer
       För  att  avgöra  rättigheterna  när  en oprivilegierad process söker tillgång till en fil
       avbildas processkreditiven (AID, GID) och de aktiva filkreditiven  tillbaka  till  vad  de
       skulle   vara  i  den  initiala  användarnamnrymden  och  jämförs  sedan  för  att  avgöra
       rättigheterna som processen har till filen. Detsamma är också sant för  andra  objekt  som
       använder åtkomstmodellen med kreditiv plus rättighetsmasker, såsom System V IPC-objekt.

   Åtgärder med filrelaterade förmågor
       Vissa   förmågor   tillåter   en  process  att  kringgå  olika  begränsningar  som  kärnan
       upprätthåller när den utför åtgärder på filer som ägs av andra  användare  eller  grupper.
       Dessa  förmågor  är:  CAP_CHOWN,  CAP_DAC_OVERRIDE,  CAP_DAC_READ_SEARCH,  CAP_FOWNER  och
       CAP_FSETID.

       Inom en användarnamnrymd tillåter dessa  förmågor  en  process  att  kringgå  reglerna  om
       processen har den relevanta förmågan över filen, vilket betyder:

       •  processen har den relevanta effektiva förmågan i sin användarnamnrymd; och

       •  filens användar-ID och grupp-ID båda har giltiga avbildningar i användarnamnrymden.

       Förmågan  CAP_FOWNER  behandlas  något  speciellt:  den  tillåter  en  process att kringgå
       motsvarande regler så  länge  som  åtminstone  filens  användar-ID  har  en  avbildning  i
       användarnamnrymden (d.v.s., filens grupp-ID behöver inte ha en giltig avbildning).

   Sätt-användar-ID- och sätt-grupp-ID-program
       När  en  process  inuti  en  användarnamnrymd  kör  ett  program  som  är sätt-användar-ID
       (sätt-grupp-ID) ändras processens effektiva användar- (grupp-)ID inuti namnrymden till det
       värde  som är avbildat för filens användar- (grupp-)ID. Dock, om antingen filens användar-
       eller  grupp-ID  inte  har  någon  avbildning  inuti  namnrymden  ignoreras   tyst   biten
       sätt-användar-ID  (sätt-grupp-ID):  det  nya  programmet  körs,  men  processens effektiva
       användar- (grupp-)ID lämnas orört. (Detta avspeglar semantiken hos att  köra  ett  program
       med  sätt-användar-ID  eller  sätt-grupp-ID  som  bor  på ett filsystem som monterades med
       flaggan MS_NOSUID, såsom beskrivs i mount(2).)

   Diverse
       När en process användar- och grupp-ID:n skickas över ett UNIX-domänsuttag till en  process
       i  en  annan användarnamnrymd (se beskrivningen av SCM_CREDENTIALS i unix(7)) översätts de
       till de motsvarande värdena  i  enlighet  med  den  mottagande  processens  användar-  och
       grupp-ID-avbildningar.

STANDARDER

       Namnrymder är en Linux-specifik funktion.

NOTERINGAR

       Under  åren  har  det funnits många funktioner som har lagts till till Linuxkärnan som har
       gjorts tillgängliga endast till privilegierade användare på grund av deras  potential  att
       förvirra   sätt-användar-ID-root-program.   I   allmänhet  blir  det  säkert  att  tillåta
       root-användaren i en  användarnamnrymd  att  använda  dessa  funktioner  eftersom  det  är
       omöjligt,  så  länge man finns i en användarnamnrymd, att få fler privilegier än de som en
       användarnamnrymds root-användare har.

   Global root
       Termen ”global root” används ibland som en kortform  för  användar-ID  0  i  den  initiala
       användarnamnrymden.

   Tillgänglighet
       Användning  av  användarnamnrymder  kräver  en  kärna som är konfigurerad med alternativet
       CONFIG_USER_NS. Användarnamnrymder kräver stöd i ett antal undersystem i hela kärnan.  När
       ett  undersystem som inte stödjs konfigureras i kärnan är det inte möjligt att konfigurera
       stöd för användarnamnrymder.

       Fram till Linux 3.8 stödde de mest relevanta subsystemen användarnamnrymder, men ett antal
       filsystem  hade  inte  den  nödvändiga  infrastrukturen  för  att  avbilda  användar-  och
       grupp-ID:n   mellan   användarnamnrymder.   Linux   3.9   lade   till    det    nödvändiga
       infrastrukturstödet  till  många  av  de  återstående  ej stödda filsystemen (Plan 9 (9P),
       Andrew File System (AFS), Ceph, CIFS, CODA, NFS och OCFS2). Linux 3.12 lade till stöd till
       det sista av de ej stödda större filsystemen, XFS.

EXEMPEL

       Nedanstående program är skapat för att möjliggöra experimenterande med användarnamnrymder,
       liksom även andra typer av namnrymder. Det skapar namnrymder enligt  specifikationen  från
       kommandoradsflaggor  och  kör sedan ett kommando inuti dessa namnrymder. Kommentarerna och
       funktionen usage() inuti programmet  ger  den  fullständiga  förklaringen  av  programmet.
       Följande skalsession demonstrerar dess användning.

       Först betraktar vi körtidsmiljön:

           $ uname -rs     # Förutsätter Linux 3.8 eller senare
           Linux 3.8.0
           $ id -u         # Kör som en oprivilegierad användare
           1000
           $ id -g
           1000

       Starta  nu  ett  skal i en ny användar- (-U), monterings- (-m) och PID- (-p) namnrymd, med
       användar-ID (-M) och grupp-ID (-G) 1000 avbildade på 0 inuti användarnamnrymden:

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

       Skalet har PID 1, för att det är den första processen i den nya PID-namnrymden.

           bash$ echo $$
           1

       Att montera ett nytt /proc-filsystem och lista alla processerna som är synliga i  den  nya
       PID-namnrymden visar att skalet inte kan se några processer utanför  PID-namnrymden:

           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

       Inuti   användarnamnrymden  har  skalet  användar-  och  grupp-ID  0,  och  den  kompletta
       uppsättningen av tillåtna och effektiva förmågor:

           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

   Programkällkod

       /* userns_child_exec.c

          Licensierad under GNU General Public License v2 eller senare

          Skapa en barnprocess som kör ett skalkommande i nya namnrymder;
          tillåt UID- och GID-avbildningar att anges när en användarnamnrymd
          skapas.
       */
       #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;        /* Kommando att köras av barnet, med argument */
           int    pipe_fd[2];  /* Rör använt för att synkronisera förälder och barn */
       };

       static int verbose;

       static void
       usage(char *pname)
       {
           fprintf(stderr, "Användning: %s [flaggor] kmd [arg…]\n\n", pname);
           fprintf(stderr, "Skapa en barnprocess som kör ett skalkommando i "
                   "en ny användarnamnrymd,\n"
                   "och eventuellt även andra nya namnrymder.\n\n");
           fprintf(stderr, "Flaggor kan vara:\n\n");
       #define fpe(str) fprintf(stderr, "    %s", str);
           fpe("-i          Ny IPC-namnrymd\n");
           fpe("-m          Ny monteringsnamnrymd\n");
           fpe("-n          Ny nätverksnamnrymd\n");
           fpe("-p          Ny PID-namnrymd\n");
           fpe("-u          Ny UTS-namnrymd\n");
           fpe("-U          Ny användarnamnrymd\n");
           fpe("-M uid_map  Ange AID-avbildning för användarnamnrymden\n");
           fpe("-G gid_map  Ange GID-avbildning för användarnamnrymden\n");
           fpe("-z          Avbilda användar-AID och -GID till 0 i användarnamnrymden\n");
           fpe("            (ekvivalent med: -M '0 <aid> 1' -G '0 <gid> 1')\n");
           fpe("-v          Visa utförliga meddelanden\n");
           fpe("\n");
           fpe("Om -z, -M eller -G anges är -U nödvändigt.\n");
           fpe("Det är inte tillåtet att ange både -z och någon av -M eller -G.\n");
           fpe("\n");
           fpe("Avbildningssträngar för -M och -G består av poster på formen:\n");
           fpe("\n");
           fpe("    ID-inuti-nr   ID-utanför-nr   längd\n");
           fpe("\n");
           fpe("En avbildningssträng kan innehålla flera poster, separerade"
               " av komman;\n");
           fpe("kommatecknen ersätts med nyrader före skrivning"
               " till avbildningsfiler.\n");

           exit(EXIT_FAILURE);
       }

       /* Uppdatera avbildningsfilen "map_fil", med värdena som ges i
          "avbildning", en sträng som definierar en AID- eller GID-avbildning.
          En AID- eller GID-avbildning består av en eller flera nyradsavgränsade poster
          på formen:

              ID_inuti-nr    ID-utanför-nr   längd

          Att begära att användaren skall ge en sträng som innehåller nyrader är
          naturligtvis opraktiskt för kommandoradsanvändning. Därför tillåter vi
          användningen av komman för att avgränsa poster i denna sträng, och
          ersätter dem med nyrader före vi skriver strängen till filen. */

       static void
       update_map(char *mapping, char *map_file)
       {
           int fd;
           size_t map_len;     /* Längden på "avbildning" */

           /* Ersätt kommatecken i avbildningssträngar med nyrader. */

           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, "FEL: open %s: %s\n", map_file,
                       strerror(errno));
               exit(EXIT_FAILURE);
           }

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

           close(fd);
       }

       /* Linux 3.19 gjorde en ändring av hanteringen av setgroups(2) och filen
          "gid_map" för att åtgärda ett säkerhetsproblem. Problemet tillät
          *oprivilegierade* användare att nyttja användarnamnrymder för att släppa
          grupper. Följden av ändringarna i 3.19 är att för att uppdatera filen
          "gid_maps" måste först användning av systemanropet setgroups()
          i denna användarnamnrymd avaktiveras genom att skriva "deny" till en
          av filerna /proc/PID/setgroups för denna namnrymd. Det är syftet med
          följande funktion. */

       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) {

               /* Vi kan vara på ett system som inte stödjer /proc/PID/setgroups.
                  I det fallet kommer filen inte att finnas, och systemet kommer
                  inte att påtvinga begränsningarna som Linux 3.19 lade till. Det
                  är bra så: vi behöver inte göra något för att tillåta att
                  "gid_map" uppdateras.

                  Dock, om felet från open() var något annat än felet ENOENT
                  som förväntas i det fallet, tala om det för användaren. */

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

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

           close(fd);
       }

       static int              /* Startfunktion för klonat barn */
       childFunc(void *arg)
       {
           struct child_args *args = arg;
           char ch;

           /* Vänta tills föräldern har uppdaterat AID- och GID-avbildningarna.
              Se kommentaren i main(). Vi väntar på filslut från ett rör som
              kommer stängas av föräldraprocessen när den har uppdaterat
              avbildningarna. */

           close(args->pipe_fd[1]);    /* Stäng vår beskrivare för skrivänden
                                          av röret så att vi ser EOF när föräldern
                                          stänger sin beskrivare. */
           if (read(args->pipe_fd[0], &ch, 1) != 0) {
               fprintf(stderr,
                       "Fel i barnet: läsning från röret returnerade ≠ 0\n");
               exit(EXIT_FAILURE);
           }

           close(args->pipe_fd[0]);

           /* Kör ett skalkommando. */

           printf("I begrepp att göra 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];    /* Utrymme för barnets stack */

       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];

           /* Tolka kommandoradsflaggor. Det inledande tecknet "+" i det
              sista argumentet till getopt() förhindrar permutationer av
              kommandoradsflaggor enligt GNU-stil. Det är användbart, eftersom
              ibland "kommandot" som skall köras av detta program självt
              har kommandoradsflaggor. Vi vill inte att getopt() skall hantera
              dessa som flaggor till detta program. */

           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 eller -G utan -U är meningslöst */

           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];

           /* Vi använder ett rör för att synkronisera förälder och barn, för
              att säkerställa att föräldern ställer in UID- och GID-avbildningarna
              före barnet anropar execve(). Detta ser till att barnet behåller
              sina förmågor under execve() i det vanliga fallet då vi vill avbilda
              barnets effektiva användar-ID på 0 i den nya användarnamnrymden.
              Utan denna synkronisering skulle barnet tappa sina förmågor om det
              utförde en execve() med användar-ID:n skilda från noll (se
              manualsidan capabilities(7) för detaljer om transformationen av en
              process förmågor under execve()). */

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

           /* Skapa barnet i nya namnrymder. */

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

           /* Föräldern faller igenom hit. */

           if (verbose)
               printf("%s: PID för barnet som skapades av clone() är %jd\n",
                       argv[0], (intmax_t) child_pid);

           /* Uppdatera UID- och GID-avbildningarna i barnet. */

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

           /* Stäng skrivänden av röret för att signalera till barnet att vi
              har uppdaterat UID- och GID-avbildningarna. */

           close(args.pipe_fd[1]);

           if (waitpid(child_pid, NULL, 0) == -1)      /* Vänta på barnet */
               err(EXIT_FAILURE, "waitpid");

           if (verbose)
               printf("%s: avslutar\n", argv[0]);

           exit(EXIT_SUCCESS);
       }

SE ÄVEN

       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)

       Kärnans källfil Documentation/admin-guide/namespaces/resource-control.rst.

ÖVERSÄTTNING

       Den  svenska   översättningen   av   denna   manualsida   skapades   av   Göran   Uddeborg
       <goeran@uddeborg.se>

       Denna  översättning  är  fri  dokumentation;  läs  GNU  General  Public  License Version 3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ eller senare för upphovsrättsvillkor.  Vi  tar
       INGET ANSVAR.

       Om  du  hittar  fel  i  översättningen  av  denna  manualsida,  skicka  ett mail till ⟨Tp-
       sv@listor.tp-sv.se⟩.