Provided by: manpages-sv_4.23.1-1_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).

       En uppgift som ändrar ett av sina effektiva ID:n kommer  ha  sin  dumpbarhet  återställd  till  värdet  i
       /proc/sys/fs/suid_dumpable.  Detta  kan  påverka  ägandet  av proc-filer för barnprocesser och kan alltså
       orsaka att föräldern kommer att sakna rättigheter att skriva till avbildningsfiler för barnprocesser  som
       kör i en ny användarnamnrymd. I dessa fall kan man genom att göra processen dumpbar med PR_SET_DUMPABLE i
       ett  anrop  av  prctl(2)  före  en  barnprocess skapas i en ny användarnamnrymd åtgärda detta problem. Se
       prctl82) och proc(5) för detaljer om hur ägarskap påverkas.

   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

       This mapping tells us that the range starting at user ID 0 in this namespace maps to a range starting  at
       0  in  the  (nonexistent)  parent  namespace,  and the length of the range is the largest 32-bit unsigned
       integer. This leaves 4294967295 (the 32-bit signed -1 value) unmapped. This is deliberate: (uid_t) -1  is
       used  in  several  interfaces  (e.g.,  setreuid(2))  as a way to specify "no user ID". Leaving (uid_t) -1
       unmapped and unusable guarantees that there will be no confusion when using these interfaces.

   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

       Linux.

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

          Licensed under GNU General Public License v2 or later

          Skapa en barnprocess som kör ett skalkommando i nya namnrymder;
          låt UID- och GID-avbildningar 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å \[aq]avbildning\[aq] */

           /* 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)      /* Wait for child */
               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  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.

Linux man-pages 6.8                                2 maj 2024                                 user_namespaces(7)