Man page - user_namespaces(7)
Packages contains this manual
- shm_overview(7)
- nss(5)
- proc_mtrr(5)
- intro(7)
- tcp(7)
- iso_8859-9(7)
- armscii-8(7)
- proc_kpagecount(5)
- initrd(4)
- mouse(4)
- proc_stat(5)
- x25(7)
- proc_interrupts(5)
- fifo(7)
- repertoiremap(5)
- icmp(7)
- futex(7)
- feature_test_macros(7)
- lp(4)
- bpf-helpers(7)
- epoll(7)
- proc_sys_dev(5)
- namespaces(7)
- proc_sysrq-trigger(5)
- proc_bus(5)
- cp1251(7)
- proc_pid_maps(5)
- proc_sys_vm(5)
- proc_pid_projid_map(5)
- st(4)
- proc_pid(5)
- issue(5)
- pid_namespaces(7)
- unicode(7)
- inode(7)
- hosts.equiv(5)
- iso-8859-13(7)
- proc_fb(5)
- proc_modules(5)
- proc_pid_autogroup(5)
- keyrings(7)
- sysvipc(7)
- proc_kmsg(5)
- cgroups(7)
- latin6(7)
- proc_pid_uid_map(5)
- unix(7)
- proc_pid_io(5)
- pts(4)
- packet(7)
- ld-linux.so(8)
- tzselect(8)
- iconv(1)
- proc_pid_syscall(5)
- proc_pid_net(5)
- proc_pid_pagemap(5)
- tty(4)
- proc_profile(5)
- standards(7)
- proc_pid_mounts(5)
- filesystems(5)
- iso-8859-15(7)
- locale(5)
- iso_8859_3(7)
- xattr(7)
- iso-8859-2(7)
- proc_uptime(5)
- persistent-keyring(7)
- credentials(7)
- proc_pid_timers(5)
- utmpx(5)
- vcsa(4)
- proc_pid_exe(5)
- proc_net(5)
- proc_timer_stats(5)
- ip(7)
- proc_pid_fd(5)
- ptmx(4)
- user_namespaces(7)
- resolv.conf(5)
- url(7)
- iso_8859_5(7)
- iso_8859-8(7)
- urn(7)
- process-keyring(7)
- proc_pid_auxv(5)
- proc_ksyms(5)
- proc_ide(5)
- veth(4)
- ldd(1)
- proc_swaps(5)
- landlock(7)
- proc_vmstat(5)
- system_data_types(7)
- cp1252(7)
- lirc(4)
- proc_kpageflags(5)
- random(7)
- precedence(7)
- cpuset(7)
- proc_pid_ns(5)
- acct(5)
- latin4(7)
- proc_pid_cgroup(5)
- proc_cpuinfo(5)
- iso_8859-2(7)
- proc_keys(5)
- charsets(7)
- pldd(1)
- proc_pid_stat(5)
- rtnetlink(7)
- netlink(7)
- ram(4)
- mem(4)
- iso-8859-6(7)
- proc_key-users(5)
- iso_8859_15(7)
- fanotify(7)
- proc_sys_net(5)
- sysfs(5)
- math_error(7)
- latin1(7)
- proc_pid_root(5)
- nptl(7)
- proc_cgroups(5)
- proc_iomem(5)
- proc_pid_statm(5)
- sem_overview(7)
- hier(7)
- full(4)
- proc_pid_status(5)
- proc_pid_cwd(5)
- proc_pid_cpuset(5)
- proc_scsi(5)
- uri(7)
- proc_diskstats(5)
- iso_8859_6(7)
- latin2(7)
- latin5(7)
- man-pages(7)
- ld.so(8)
- uts_namespaces(7)
- proc_pid_mountstats(5)
- intro(3)
- proc_pid_seccomp(5)
- proc_pid_wchan(5)
- attributes(7)
- symlink(7)
- mount_namespaces(7)
- charmap(5)
- tis-620(7)
- iso-8859-10(7)
- getent(1)
- proc_buddyinfo(5)
- ttytype(5)
- rtc(4)
- proc_malloc(5)
- suffixes(7)
- sln(8)
- signal(7)
- proc_sys_abi(5)
- signal-safety(7)
- time_namespaces(7)
- proc_pid_comm(5)
- raw(7)
- gai.conf(5)
- proc_crypto(5)
- locale(1)
- iso-8859-3(7)
- motd(5)
- proc_meminfo(5)
- iso-8859-8(7)
- protocols(5)
- proc_pid_map_files(5)
- pthreads(7)
- null(4)
- proc(5)
- zdump(8)
- socket(7)
- proc_sys_kernel(5)
- ddp(7)
- memusagestat(1)
- hd(4)
- iso-8859-14(7)
- shells(5)
- pipe(7)
- glob(7)
- proc_self(5)
- network_namespaces(7)
- utmp(5)
- proc_kcore(5)
- nsswitch.conf(5)
- sd(4)
- iso-8859-5(7)
- iso_8859_16(7)
- man(7)
- iso_8859-6(7)
- dir_colors(5)
- mq_overview(7)
- vsock(7)
- ascii(7)
- thread-keyring(7)
- fs(5)
- proc_pid_attr(5)
- proc_sys_debug(5)
- proc_sys(5)
- proc_pid_cmdline(5)
- pty(7)
- services(5)
- cgroup_namespaces(7)
- securetty(5)
- netdevice(7)
- iso_8859_13(7)
- host.conf(5)
- proc_pid_setgroups(5)
- proc_slabinfo(5)
- sock_diag(7)
- iso_8859-14(7)
- iso-8859-11(7)
- iso_8859_11(7)
- operator(7)
- regex(7)
- wavelan(4)
- proc_sys_fs(5)
- nologin(5)
- proc_pci(5)
- koi8-r(7)
- erofs(5)
- intro(2)
- utf8(7)
- proc_kallsyms(5)
- proc_sysvipc(5)
- queue(7)
- proc_sys_sunrpc(5)
- intro(5)
- latin8(7)
- mtrace(1)
- ipc_namespaces(7)
- dsp56k(4)
- iso_8859_4(7)
- proc_pid_smaps(5)
- proc_cmdline(5)
- rpc(5)
- proc_tty(5)
- proc_version(5)
- smartpqi(4)
- proc_pid_timerslack_ns(5)
- aio(7)
- session-keyring(7)
- resolver(5)
- slabinfo(5)
- wtmp(5)
- iso_8859_9(7)
- proc_locks(5)
- mailaddr(7)
- proc_pid_oom_score(5)
- kmem(4)
- iconvconfig(8)
- iso_8859-7(7)
- glibc(7)
- hostname(7)
- proc_thread-self(5)
- ipv6(7)
- iso_8859_7(7)
- proc_kpagecgroup(5)
- core(5)
- time(7)
- units(7)
- proc_dma(5)
- loop(4)
- address_families(7)
- zero(4)
- intro(4)
- procfs(5)
- iso_8859-4(7)
- vdso(7)
- tmpfs(5)
- iso-8859-16(7)
- iso_8859_10(7)
- user-session-keyring(7)
- libc(7)
- proc_fs(5)
- koi8-u(7)
- latin3(7)
- proc_tid_children(5)
- proc_pid_limits(5)
- proc_pid_coredump_filter(5)
- iso_8859-15(7)
- arp(7)
- urandom(4)
- iso_8859-10(7)
- hpsa(4)
- proc_pid_environ(5)
- boot(7)
- ftm(7)
- ld-linux(8)
- proc_driver(5)
- loop-control(4)
- iso_8859-16(7)
- proc_filesystems(5)
- tzfile(5)
- sprof(1)
- proc_pid_task(5)
- proc_pid_oom_score_adj(5)
- proc_mounts(5)
- iso-8859-4(7)
- iso_8859-1(7)
- utf-8(7)
- iso_8859-13(7)
- intro(6)
- proc_timer_list(5)
- rtld-audit(7)
- iso_8859-3(7)
- group(5)
- sched(7)
- proc_pid_clear_refs(5)
- hosts(5)
- iso_8859-11(7)
- numa(7)
- iso_8859_2(7)
- locale(7)
- iso-8859-1(7)
- fuse(4)
- proc_tid(5)
- proc_execdomains(5)
- proc_pid_mountinfo(5)
- intro(8)
- iso_8859_8(7)
- proc_loadavg(5)
- proc_pid_oom_adj(5)
- re_format(7)
- iso_8859_14(7)
- zic(8)
- bootparam(7)
- inotify(7)
- posixoptions(7)
- proc_partitions(5)
- iso-8859-9(7)
- proc_pid_mem(5)
- networks(5)
- proc_sys_user(5)
- udp(7)
- proc_zoneinfo(5)
- latin10(7)
- proc_pid_fdinfo(5)
- proc_pid_stack(5)
- memusage(1)
- spufs(7)
- pkeys(7)
- path_resolution(7)
- proc_ioports(5)
- intro(1)
- ldconfig(8)
- msr(4)
- svipc(7)
- port(4)
- proc_pid_personality(5)
- cciss(4)
- latin9(7)
- capabilities(7)
- localedef(1)
- vcs(4)
- iso_8859-5(7)
- elf(5)
- proc_sys_proc(5)
- console_codes(4)
- random(4)
- iso-8859-7(7)
- termcap(5)
- cpuid(4)
- environ(7)
- string_copying(7)
- proc_pid_gid_map(5)
- queue(3)
- termio(7)
- user-keyring(7)
- complex(7)
- latin7(7)
- proc_config.gz(5)
- udplite(7)
- kernel_lockdown(7)
- proc_devices(5)
- proc_apm(5)
- iso_8859_1(7)
- proc_pid_numa_maps(5)
apt-get install manpages
Available languages:
en fr sv ja deManual
user_namespaces
NOMDESCRIPTION
Espaces de noms imbriqués, appartenance aux espaces de noms
Capacités
Effet des capacitĂ©s Ă lâintĂ©rieur dâun espace de noms utilisateur
Liens entre les espaces de noms utilisateur et les autres espaces de noms
Correspondance des identifiants dâutilisateur et de groupe : uid_map etgid_map
CrĂ©ation des mappages dâID utilisateur et groupe : Ă©criture dans uid_map etgid_map
Mappages dâID de projet : projid_map
Interaction avec les appels systĂšme qui modifient les UID ou les GID
The /proc/pid/setgroups file
ID utilisateur et groupe non mappés
Accession aux fichiers
Opérations sur les capacités relatives aux fichiers
Programmes set-user-ID et set-group-ID
Divers
STANDARDS
NOTES
Superutilisateur global
Disponibilité
EXEMPLES
Source du programme
VOIR AUSSI
TRADUCTION
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.
The NS_GET_PARENT ioctl (2) operation can be used to discover the parental relationship between user namespaces; see ioctl_nsfs (2).
A task that changes one of its effective IDs will have its dumpability reset to the value in /proc/sys/fs/suid_dumpable . This may affect the ownership of proc files of child processes and may thus cause the parent to lack the permissions to write to mapping files of child processes running in a new user namespace. In such cases making the parent process dumpable, using PR_SET_DUMPABLE in a call to prctl (2), before creating a child process in a new user namespace may rectify this problem. See prctl (2) and proc (5) for details on how ownership is affected.
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). |
||
|
- |
When a user namespace is created, the kernel records the effective user ID of the creating process as being the "owner" of the namespace. A process that resides in the parent of the user namespace and whose effective user ID matches the owner of the namespace has all capabilities in the namespace. By virtue of the previous rule, this means that the process has all capabilities in all further removed descendant user namespaces as well. The NS_GET_OWNER_UID ioctl (2) operation can be used to discover the user ID of the owner of the namespace; see ioctl_nsfs (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) |
Holding CAP_SYS_ADMIN within the user namespace that owns a processâs cgroup namespace allows (since Linux 4.6) that process to the mount the cgroup version 2 filesystem and cgroup version 1 named hierarchies (i.e., cgroup filesystems mounted with the "none,name=" option).
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.
The NS_GET_USERNS ioctl (2) operation can be used to discover the user namespace that owns a nonuser namespace; see ioctl_nsfs (2).
Correspondance des identifiants dâutilisateur et de groupe : uid_map etgid_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
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.
CrĂ©ation des mappages dâID utilisateur et groupe : Ă©criture dans uid_map etgid_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.
The /proc/pid/setgroups file
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/ pid gid_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
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
Licensed under GNU General Public License v2 or later
Create a child process that executes a shell command in new
namespace(s); allow UID and GID mappings to be specified
when
creating a user namespace.
*/
#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; /* Command to be executed by child, with args
*/
int pipe_fd[2]; /* Pipe used to synchronize parent and child
*/
};
static int verbose;
static void
usage(char *pname)
{
fprintf(stderr, "Usage: %s [options] cmd
[arg...]\n\n", pname);
fprintf(stderr, "Create a child process that executes a
shell "
"command in a new user namespace,\n"
"and possibly also other new namespace(s).\n\n");
fprintf(stderr, "Options can be:\n\n");
#define fpe(str) fprintf(stderr, " %s", str);
fpe("-i New IPC namespace\n");
fpe("-m New mount namespace\n");
fpe("-n New network namespace\n");
fpe("-p New PID namespace\n");
fpe("-u New UTS namespace\n");
fpe("-U New user namespace\n");
fpe("-M uid_map Specify UID map for user
namespace\n");
fpe("-G gid_map Specify GID map for user
namespace\n");
fpe("-z Map user's UID and GID to 0 in user
namespace\n");
fpe(" (equivalent to: -M '0 <uid> 1' -G '0
<gid> 1')\n");
fpe("-v Display verbose messages\n");
fpe("\n");
fpe("If -z, -M, or -G is specified, -U is
required.\n");
fpe("It is not permitted to specify both -z and either
-M or -G.\n");
fpe("\n");
fpe("Map strings for -M and -G consist of records of
the form:\n");
fpe("\n");
fpe(" ID-inside-ns ID-outside-ns len\n");
fpe("\n");
fpe("A map string can contain multiple records,
separated"
" by commas;\n");
fpe("the commas are replaced by newlines before
writing"
" to map files.\n");
exit(EXIT_FAILURE);
}
/* Update the mapping file 'map_file', with the value
provided in
'mapping', a string that defines a UID or GID mapping. A UID
or
GID mapping consists of one or more newline-delimited
records
of the form:
ID_inside-ns ID-outside-ns length
Requiring the user to supply a string that contains newlines
is
of course inconvenient for command-line use. Thus, we permit
the
use of commas to delimit records in this string, and replace
them
with newlines before writing the string to the file. */
static void
update_map(char *mapping, char *map_file)
{
int fd;
size_t map_len; /* Length of 'mapping' */
/* Replace commas in mapping string with newlines. */
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 made a change in the handling of setgroups(2)
and
the 'gid_map' file to address a security issue. The issue
allowed *unprivileged* users to employ user namespaces in
order to drop groups. The upshot of the 3.19 changes is that
in order to update the 'gid_maps' file, use of the
setgroups()
system call in this user namespace must first be disabled by
writing "deny" to one of the /proc/PID/setgroups
files for
this namespace. That is the purpose of the following
function. */
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) {
/* We may be on a system that doesn't support
/proc/PID/setgroups. In that case, the file won't exist,
and the system won't impose the restrictions that Linux 3.19
added. That's fine: we don't need to do anything in order
to permit 'gid_map' to be updated.
However, if the error from open() was something other than
the ENOENT error that is expected for that case, let the
user know. */
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 /* Start function for cloned child */
childFunc(void *arg)
{
struct child_args *args = arg;
char ch;
/* Wait until the parent has updated the UID and GID
mappings.
See the comment in main(). We wait for end of file on a
pipe that will be closed by the parent process once it has
updated the mappings. */
close(args->pipe_fd[1]); /* Close our descriptor for the
write
end of the pipe so that we see EOF
when parent closes its descriptor. */
if (read(args->pipe_fd[0], &ch, 1) != 0) {
fprintf(stderr,
"Failure in child: read from pipe returned !=
0\n");
exit(EXIT_FAILURE);
}
close(args->pipe_fd[0]);
/* Execute a shell command. */
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]; /* Space for child's
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];
/* Parse command-line options. The initial '+' character in
the final getopt() argument prevents GNU-style permutation
of command-line options. That's useful, since sometimes
the 'command' to be executed by this program itself
has command-line options. We don't want getopt() to treat
those as options to this 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 or -G without -U is nonsensical */
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];
/* We use a pipe to synchronize the parent and child, in
order to
ensure that the parent sets the UID and GID maps before the
child
calls execve(). This ensures that the child maintains its
capabilities during the execve() in the common case where we
want to map the child's effective user ID to 0 in the new
user
namespace. Without this synchronization, the child would
lose
its capabilities if it performed an execve() with nonzero
user IDs (see the capabilities(7) man page for details of
the
transformation of a process's capabilities during execve()).
*/
if (pipe(args.pipe_fd) == -1)
err(EXIT_FAILURE, "pipe");
/* Create the child in new namespace(s). */
child_pid = clone(childFunc, child_stack + STACK_SIZE,
flags | SIGCHLD, &args);
if (child_pid == -1)
err(EXIT_FAILURE, "clone");
/* Parent falls through to here. */
if (verbose)
printf("%s: PID of child created by clone() is
%jd\n",
argv[0], (intmax_t) child_pid);
/* Update the UID and GID maps in the child. */
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);
}
/* Close the write end of the pipe, to signal to the child
that we
have updated the UID and GID maps. */
close(args.pipe_fd[1]);
if (waitpid(child_pid, NULL, 0) == -1) /* Wait for child */
err(EXIT_FAILURE, "waitpid");
if (verbose)
printf("%s: terminating\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 .