Pour vérifier les permissions, les implémentations
UNIX traditionnelles distinguent deux catégories de
processus : les processus privilégiés (dont
l'UID effectif est 0, appelé superutilisateur ou root) et les
processus non privilégiés (dont les UID effectifs sont
différents de zéro). Les processus privilégiés
contournent toutes les vérifications de permissions du noyau, alors
que les processus non privilégiés sont soumis à une
vérification complète basée sur l'identification du
processus (habituellement : UID effectif, GID effectif et liste des
groupes additionnels).
À partir de Linux 2.2, Linux scinde les
privilèges traditionnellement associés au superutilisateur en
unités distinctes, connues sous le nom de capabilities
(capacités) que l'on peut activer ou inhiber individuellement. Les
capacités sont des attributs individuels à chaque thread.
La liste suivante indique les capacités
implémentées sous Linux et les opérations ou
comportements que chaque capacité permet :
- CAP_AUDIT_CONTROL
(depuis Linux 2.6.11)
- Activer et désactiver l'audit du noyau, changer les règles
de filtrage d'audit, accéder à l'état de l'audit et
aux règles de filtrage.
- CAP_AUDIT_READ
(depuis Linux 3.16)
- Autoriser la lecture du journal d'audit au moyen d'un socket netlink
multidiffusion.
- CAP_AUDIT_WRITE
(depuis Linux 2.6.11)
- Écrire des enregistrements dans le journal d'audit du noyau.
- CAP_BLOCK_SUSPEND
(depuis Linux 3.5)
- Utiliser des fonctionnalités qui peuvent bloquer la mise en veille
du système (epoll(7) EPOLLWAKEUP,
/proc/sys/wake_lock).
- CAP_BPF (depuis
Linux 5.8)
- Utiliser des opérations BPF privilégiées ;
consultez bpf(2) et bpf-helpers(7).
- Cette capacité a été ajoutée dans
Linux 5.8 pour séparer la fonctionnalité BPF de la
capacité CAP_SYS_ADMIN surchargée.
- CAP_CHECKPOINT_RESTORE
(depuis Linux 5.9)
- Mettre à jour /proc/sys/kernel/ns_last_pid (consultez
pid_namespaces(7)) ;
- Utiliser la fonction set_tid de clone3(2) ;
- Lire le contenu des liens symboliques dans
/proc/pid/map_files pour les autres processus.
- Cette capacité a été ajoutée dans
Linux 5.9 pour séparer la fonctionnalité
checkpoint/restore de la capacité CAP_SYS_ADMIN
surchargée.
- CAP_CHOWN
- Effectuer toute modification des UID et GID de fichiers (consultez
chown(2)).
- CAP_DAC_OVERRIDE
- Contourner les vérifications des permissions de lecture,
écriture et exécution. (DAC est l'abréviation de
« discretionary access control »,
contrôle d'accès à volonté).
- CAP_DAC_READ_SEARCH
- Contourner les vérifications des permissions de lecture de fichiers
et celles de lecture et d'exécution des
répertoires ;
- invoquer open_by_handle_at(2) ;
- utiliser l'attribut AT_EMPTY_PATH de linkat(2) pour
créer un lien vers un fichier visé par un descripteur de
fichier.
- CAP_FOWNER
- Contourner les vérifications pour les opérations qui
demandent que l'UID de système de fichiers du processus corresponde
à l'UID du fichier (par exemple chmod(2), utime(2)),
à l'exclusion des opérations couvertes par
CAP_DAC_OVERRIDE et CAP_DAC_READ_SEARCH ;
- positionner les attributs d'inœuds (consultez
ioctl_iflags(2)) pour n'importe quel fichier ;
- positionner les listes de contrôle d'accès ACL
(« Access Control Lists ») pour n'importe quel
fichier ;
- ignorer le « sticky bit » des
répertoires pour les suppressions de fichier ;
- modifier les attributs étendus user sur un répertoire
avec le sticky bit défini, appartenant à n'importe quel
utilisateur ;
- spécifier O_NOATIME dans open(2) et fcntl(2)
pour n'importe quel fichier.
- CAP_FSETID
- Ne pas effacer les bits de mode set-user-ID et set-group-ID lors de la
modification d'un fichier ;
- positionner le bit Set-group-ID sur un fichier dont le GID ne correspond
pas au système de fichiers ni à aucun GID additionnel du
processus appelant.
- CAP_IPC_LOCK
- Verrouiller des pages mémoire (mlock(2), mlockall(2),
mmap(2), shmctl(2)) ;
- allouer des pages mémoire utilisant des pages larges
(memfd_create(2), mmap(2), shmctl(2)).
- CAP_IPC_OWNER
- Contourner les vérifications de permission pour les
opérations sur les objets IPC System V.
- CAP_KILL
- Contourner les vérifications de permission pour l'émission
de signaux (consultez kill(2)). Cette capacité inclut
l'utilisation de l'opération KDSIGACCEPT
d'ioctl(2).
- CAP_LEASE
(depuis Linux 2.4)
- Demander des baux (leases) sur n'importe quel fichier (consultez
fcntl(2)).
- CAP_LINUX_IMMUTABLE
- Positionner les attributs d'inœuds FS_APPEND_FL et
FS_IMMUTABLE_FL (consultez ioctl_iflags(2)).
- CAP_MAC_ADMIN
(depuis Linux 2.6.25)
- Permettre les modifications de la configuration ou des états MAC.
Implémentée pour le module LSM (Smack Linux Security
Module).
- CAP_MAC_OVERRIDE
(depuis Linux 2.6.25)
- Surcharger les contrôles d'accès MAC
(« Mandatory Access Control »).
Implémentée pour le module Smack LSM.
- CAP_MKNOD
(depuis Linux 2.4)
- Créer des fichiers spéciaux avec mknod(2).
- CAP_NET_ADMIN
- Effectuer diverses opérations liées au
réseau :
- configuration des interfaces ;
- administration du pare-feu, de la traduction d'adresse IP
(« masquerading ») et collection de
données sur le trafic réseau
(« accounting ») ;
- modification des tables de routages ;
- attachement à n'importe quelle adresse pour un service mandataire
transparent ;
- sélection du type de service
(« TOS ») ;
- effacement des statistiques du pilote ;
- sélection du mode
« promiscuité » ;
- activation de la diffusion multipoint
(« multicast ») ;
- utilisation de setsockopt(2) pour définir les options de
sockets suivantes : SO_DEBUG, SO_MARK,
SO_PRIORITY (pour une priorité en dehors des valeurs
de 0 à 6), SO_RCVBUFFORCE et
SO_SNDBUFFORCE.
- CAP_NET_BIND_SERVICE
- Attacher un socket à un port privilégié du domaine de
l'Internet (numéro de port inférieur à 1024).
- CAP_NET_BROADCAST
- (Inutilisé) diffusion par socket et écoute de
multidiffusion.
- CAP_NET_RAW
- Utiliser des sockets RAW et PACKET ;
- attacher à n'importe quelle adresse pour un service mandataire
transparent.
- CAP_PERFMON
(depuis Linux 5.8)
- Utiliser divers mécanismes de suivi des performances
dont :
- appeler perf_event_open(2) ;
- utiliser diverses opérations BPF qui ont des incidences sur les
performances.
- Cette capacité a été ajoutée dans
Linux 5.8 pour séparer la fonctionnalité de suivi des
performances de la capacité CAP_SYS_ADMIN surchargée.
Consultez aussi le fichier source du noyau
Documentation/admin-guide/perf-security.rst.
- CAP_SETGID
- Faire des manipulations arbitraires des GID et de la liste de GID
additionnels des processus ;
- simuler des GID lors du passage de références de sockets au
moyen de sockets de domaine UNIX ;
- écrire une projection de GID dans un espace de noms utilisateur
(consultez user_namespaces(7)).
- CAP_SETFCAP
(depuis Linux 2.6.24)
- Définir des capacités arbitraires sur un fichier
- Depuis Linux 5.12, cette capacité est aussi
nécessaire pour projeter l'UID 0 dans un nouvel espace de
noms utilisateur ; pour en savoir plus consultez
user_namespaces(7).
- CAP_SETPCAP
- Si les capacités de fichier sont prises en charge
(c'est-à-dire depuis Linux 2.6.24) : ajouter toute
capacité de l'ensemble de limitation de capacités du thread
appelant à son ensemble hérité ; supprimer les
capacités de l'ensemble de limitation de capacités (avec
prctl(2) PR_CAPBSET_DROP) ; modifier les attributs
securebits.
- Si les capacités de fichier ne sont pas prises en charge
(c'est-à-dire avec les noyaux antérieurs à
Linux 2.6.24) : accorder ou interdire toute capacité
dans l'ensemble des capacités permises de l'appelant vers ou depuis
tout autre processus (cette propriété de CAP_SETPCAP
n'est pas disponible quand le noyau est configuré pour prendre en
charge les capacités de fichiers, puisque CAP_SETPCAP a une
toute autre sémantique pour ces noyaux).
- CAP_SETUID
- Faire des manipulations arbitraires des UID de processus
(setuid(2), setreuid(2), setresuid(2),
setfsuid(2)) ;
- simuler des UID lors du passage de références de sockets au
moyen de sockets de domaine UNIX ;
- écrire une projection de l'UID dans un espace de noms utilisateur
(consultez user_namespaces(7)).
- CAP_SYS_ADMIN
- Remarque : cette capacité est
surchargée : voir les Notes pour les développeurs
du noyau ci-dessous.
- Effectuer certaines opérations d'administration système
comme : quotactl(2), mount(2), umount(2),
pivot_root(2), swapon(2), swapoff(2),
sethostname(2) et setdomainname(2) ;
- effectuer des opérations syslog(2) nécessitant des
droits (depuis Linux 2.6.37, CAP_SYSLOG doit être
utilisée pour permettre de telles opérations) ;
- effectuer une commande VM86_REQUEST_IRQ
vm86(2) ;
- accéder à la même fonctionnalité
checkpoint/restore qui est contrôlée par
CAP_CHECKPOINT_RESTORE (mais cette dernière capacité
plus faible est préférée pour accéder à
cette fonctionnalité) ;
- effectuer les mêmes opérations BPF que celles
contrôlées par CAP_BPF (mais cette dernière
capacité plus faible est préférée pour
accéder à cette fonctionnalité) ;
- utiliser les mêmes mécanismes de suivi des performances qui
sont contrôlés par CAP_PERFMON (mais cette
dernière capacité plus faible est
préférée pour accéder à cette
fonctionnalité) ;
- effectuer des opérations IPC_SET et IPC_RMID sur
n'importe quel objet IPC System V ;
- ne pas tenir compte de la limite de ressource
RLIMIT_NPROC ;
- effectuer des opérations sur les attributs étendus
trusted et security (consultez
xattr(7)) ;
- utiliser lookup_dcookie(2) ;
- utiliser ioprio_set(2) pour configurer une classe d'ordonnancement
d'E/S IOPRIO_CLASS_RT et (avant Linux 2.6.25)
IOPRIO_CLASS_IDLE ;
- simuler des PID lors du passage de références de sockets au
moyen de sockets de domaine UNIX ;
- dépasser /proc/sys/fs/file-max, la limite système du
nombre de fichiers ouverts dans les appels système qui ouvrent des
fichiers (par exemple accept(2), execve(2), open(2)
et pipe(2)) ;
- utiliser les attributs CLONE_* qui créent de nouveaux
espaces de noms avec clone(2) et unshare(2) (mais, depuis
Linux 3.8, la création d'espaces de noms utilisateur ne
nécessite aucune capacité) ;
- accéder aux informations d'événements perf
nécessitant des droits ;
- appeler setns(2) (nécessite la capacité
CAP_SYS_ADMIN dans l'espace de noms target ;
- appeler fanotify_init(2) ;
- effectuer des opérations KEYCTL_CHOWN et
KEYCTL_SETPERM de keyctl(2) nécessitant des
droits ;
- effectuer une opération madvise(2)
MADV_HWPOISON ;
- utiliser la commande TIOCSTI de ioctl(2) pour insérer
des caractères dans la file d'entrées d'un terminal autre
que le terminal de contrôle de l'appelant ;
- utiliser l'appel système obsolète
nfsservctl(2) ;
- utiliser l'appel système obsolète
bdflush(2) ;
- effectuer diverses opérations ioctl(2) sur des
périphériques bloc nécessitant des
droits ;
- effectuer diverses opérations ioctl(2) sur des
systèmes de fichiers nécessitant des droits ;
- effectuer des opérations ioctl(2) nécessitant des
droits sur le périphérique /dev/random (consultez
random(4)) ;
- installer un filtre seccomp(2) sans avoir à définir
d'abord l'attribut de thread no_new_privs ;
- modifier les règles d'autorisation ou d'interdiction pour les
groupes de contrôle de périphérique ;
- utiliser l'opération PTRACE_SECCOMP_GET_FILTER de
ptrace(2) pour vider les filtres seccomp de
l'observé ;
- utiliser l'opération PTRACE_SETOPTIONS de ptrace(2)
pour suspendre les protections seccomp de l'observé
(c'est-à-dire l'attribut
PTRACE_O_SUSPEND_SECCOMP) ;
- effectuer des opérations d'administration sur de nombreux pilotes
de périphériques ;
- modifier les valeurs de courtoisie de l'autogroupe en écrivant dans
/proc/pid/autogroup (consultez sched(7)).
- CAP_SYS_BOOT
- Utiliser reboot(2) et kexec_load(2).
- CAP_SYS_CHROOT
- Utiliser chroot(2) ;
- modifier l'espace de noms montage en utilisant setns(2).
- CAP_SYS_MODULE
- Charger ou décharger des modules noyaux (consultez
init_module(2) et delete_module(2)) ;
- avant Linux 2.6.25 : enlever des capacités de
l'ensemble de limitation de capacités au niveau du
système.
- CAP_SYS_NICE
- Baisser la valeur de courtoisie (« nice »)
(nice(2), setpriority(2)) et changer la courtoisie de
n'importe quel processus ;
- définir les politiques d'ordonnancement temps réel pour le
processus appelant et les politiques d'ordonnancement et les
priorités de n'importe quel processus
(sched_setscheduler(2), sched_setparam(2),
sched_setattr(2)) ;
- définir l'affinité CPU pour n'importe quel processus
(sched_setaffinity(2)) ;
- définir la classe et la priorité d'ordonnancement
d'entrées/sorties pour n'importe quel processus
(ioprio_set(2)) ;
- appliquer migrate_pages(2) à n'importe quel processus et
migrer un processus vers n'importe quel nœud ;
- appliquer move_pages(2) pour n'importe quel processus ;
- utiliser l'attribut MPOL_MF_MOVE_ALL avec mbind(2) et
move_pages(2).
- CAP_SYS_PACCT
- Utiliser acct(2).
- CAP_SYS_PTRACE
- Suivre n'importe quel processus avec ptrace(2) ;
- appliquer get_robust_list(2) à n'importe quel
processus ;
- transférer les données depuis ou vers la mémoire de
n'importe quel processus au moyen de process_vm_readv(2) et de
process_vm_writev(2) ;
- examiner les processus avec kcmp(2).
- CAP_SYS_RAWIO
- Effectuer des opérations d'entrées-sorties (iopl(2)
et ioperm(2)) ;
- accéder à /proc/kcore ;
- utiliser l'opération FIBMAP de ioctl(2) ;
- ouvrir les périphériques pour accéder aux registres
spécifiques au modèle (MSR, consultez msr(4)) d'un
processeur x86 ;
- mettre à jour /proc/sys/vm/mmap_min_addr ;
- créer des projections en mémoire aux adresses
inférieures à la valeur indiquée par
/proc/sys/vm/mmap_min_addr ;
- projeter les fichiers dans /proc/bus/pci ;
- ouvrir /dev/mem et /dev/kmem ;
- effectuer diverses commandes de périphérique
SCSI ;
- effectuer certaines opérations sur les périphériques
hpsa(4) et cciss(4) ;
- effectuer certaines opérations spécifiques à un
périphérique sur d'autres périphériques.
- CAP_SYS_RESOURCE
- Utiliser de l'espace réservé sur des systèmes de
fichiers ext2 ;
- effectuer des appels ioctl(2) pour contrôler la
journalisation ext3 ;
- ne pas tenir compte des limites de quota disque ;
- augmenter les limites de ressources (consultez
setrlimit(2)) ;
- ne pas tenir compte de la limite de ressource
RLIMIT_NPROC ;
- ne pas tenir compte du nombre maximal de consoles sur l'allocation de
console ;
- ne pas tenir compte du nombre maximal de dispositions de
clavier ;
- permettre des interruptions à plus de 64 Hz depuis l'horloge
temps réel ;
- augmenter la limite msg_qbytes pour la file de messages
System V au-dessus de la limite /proc/sys/kernel/msgmnb
(consultez msgop(2) et msgctl(2)) ;
- permettre le contournement de la limite de ressource RLIMIT_NOFILE
sur le nombre de descripteurs de fichiers « en
cours » lors de leur transmission à un autre
processus au moyen d'un socket de domaine UNIX (consultez
unix(7)) ;
- ne pas tenir compte de la limite /proc/sys/fs/pipe-size-max lors du
réglage de la capacité d'un tube avec la commande
fcntl(2) avec l'argument F_SETPIPE_SZ ;
- utiliser F_SETPIPE_SZ pour augmenter la capacité d'un tube
au-dessus de la limite spécifiée par
/proc/sys/fs/pipe-max-size ;
- ne pas tenir compte des limites /proc/sys/fs/mqueue/queues_max,
/proc/sys/fs/mqueue/msg_max et
/proc/sys/fs/mqueue/msgsize_max lors de la création de files
de messages POSIX (consultez mq_overview(7)) ;
- utiliser l'opération PR_SET_MM de
prctl(2) ;
- affecter à /proc/pid/oom_score_adj une valeur
inférieure à la dernière valeur affectée par
un processus avec CAP_SYS_RESOURCE.
- CAP_SYS_TIME
- Modifier l'heure système (settimeofday(2), stime(2),
adjtimex(2)) ; modifier l'horloge temps réel
(matérielle).
- CAP_SYS_TTY_CONFIG
- Utiliser vhangup(2) ; employer diverses opérations
ioctl(2) nécessitant des droits sur des terminaux
virtuels.
- CAP_SYSLOG
(depuis Linux 2.6.37)
- Effectuer des opérations syslog(2) nécessitant des
droits. Consultez syslog(2) pour savoir quelles opérations
nécessitent des droits.
- Inspecter les adresses du noyau exposées par /proc et
d'autres interfaces lorsque /proc/sys/kernel/kptr_restrict a la
valeur 1. (Voir la discussion sur kptr_restrict dans
proc(5).)
- CAP_WAKE_ALARM
(depuis Linux 3.0)
- Déclencher quelque chose qui réveillera le système
(réglage des alarmes CLOCK_REALTIME_ALARM et
CLOCK_BOOTTIME_ALARM).
Une implémentation complète des capacités
nécessite que :
- pour toutes les opérations privilégiées, le noyau
doit vérifier si le thread a la capacité requise dans son
ensemble effectif ;
- le noyau doit fournir des appels système permettant de changer et
récupérer les ensembles de capacités d'un
thread ;
- le système de fichiers doit permettre d'attacher des
capacités aux fichiers exécutables pour qu'un processus en
dispose quand le fichier est exécuté.
Avant Linux 2.6.24, seules les deux premières
exigences sont remplies ; depuis Linux 2.6.24, ces trois
exigences sont remplies.
Lors de l'ajout d'une nouvelle fonctionnalité du noyau qui
pourrait être contrôlée par une capacité,
veuillez prendre en considération les points suivants :
- Le but des capacités est de découper le pouvoir du
superutilisateur en plusieurs aptitudes de telle sorte que si un programme
qui a une ou plusieurs capacités est compromis, son pouvoir
d'endommager le système soit moindre que si le programme est
exécuté avec les privilèges du superutilisateur.
- Vous pouvez choisir de créer une nouvelle capacité pour
votre nouvelle fonctionnalité, ou d'associer la
fonctionnalité à l'une des capacités existantes. Afin
que l'ensemble des capacités garde une taille gérable, la
seconde solution est préférable, à moins qu'il y ait
des raisons convaincantes de choisir la première option (il existe
aussi une limite technique : la taille des ensembles de
capacités est actuellement limitée à
64 bits).
- Pour déterminer parmi les capacités existantes laquelle est
la mieux adaptée pour être associée à la
nouvelle fonctionnalité, examinez la liste de capacités
ci-dessus pour trouver un « silo » dans lequel
la nouvelle capacité est la mieux adaptée. Une des options
est de déterminer s'il y a d'autres fonctionnalités exigeant
des capacités qui seront toujours utilisées avec la nouvelle
fonctionnalité. Si la nouvelle fonctionnalité ne sert
à rien sans les autres fonctions, vous devriez utiliser la
même capacité que ces autres fonctions.
- Ne choisissez pas CAP_SYS_ADMIN si vous pouvez
l'éviter ! Une forte proportion de vérifications de
capacités existantes lui sont associée (voir une liste
partielle plus haut). Elle pourrait plausiblement être
appelée « la nouvelle racine », dans la
mesure où d'une part, elle confère une large palette de
pouvoirs, et d'autre part, sa vaste portée signifie que c'est la
capacité qui est requise par de nombreux programmes
privilégiés. Ne rendez pas le problème encore plus
compliqué. Les seules nouvelles fonctionnalités qui
pourraient être associées à CAP_SYS_ADMIN sont
celles qui correspondent de façon étroite aux usages
existants dans ce silo.
- Si vous avez établi qu'il était réellement
nécessaire de créer une nouvelle capacité pour votre
fonctionnalité, ne la créez pas ou ne la nommez pas comme
une capacité « à usage unique ».
Par conséquent, par exemple, l'ajout de la capacité
très spécifique CAP_SYS_PACCT était
probablement une erreur. Essayez plutôt d'identifier et de nommer
votre nouvelle capacité comme un silo plus général
dans lequel d'autres futures cas d'usage semblable pourraient
s'intégrer.
Chaque thread a les ensembles de capacités suivants
contenant zéro ou plus des capacités ci-dessus :
- Permitted
(permis)
- Il s'agit d'un surensemble limitant les capacités effectives que le
thread peut prendre. Il limite également les capacités qui
peuvent être ajoutées à l'ensemble héritable
par un thread qui n'a pas la capacité CAP_SETPCAP dans son
ensemble effectif.
- Si un processus supprime une capacité de son ensemble de
capacités permises, il ne peut plus jamais la
récupérer (sauf s'il appelle execve(2) sur un
programme set-user-ID-root ou un programme dont les capacités
associées au fichier accordent cette capacité).
- Inheritable
(héritable)
- Il s'agit d'un ensemble de capacités préservées au
travers d'un execve(2). Les capacités héritables
restent héritables lors de l'exécution d'un programme et les
capacités héritables sont ajoutées à
l'ensemble de capacités permises lors de l'exécution d'un
programme qui a les bits correspondant activés dans l'ensemble
héritable du fichier.
- Parce que les capacités héritables ne sont
généralement pas préservées au travers d'un
execve(2) lors d'une exécution en tant qu'utilisateur
ordinaire, les applications qui souhaitent exécuter des programmes
d'assistance avec des capacités plus élevées
devraient envisager d'utiliser les capacités ambiantes,
décrites ci-dessous.
- Effective
(effectif)
- Il s'agit de l'ensemble des capacités utilisées par le noyau
pour vérifier les permissions du thread.
- Bounding
(limitation) (par processus depuis Linux 2.6.25)
- L’ensemble de limitation des capacités
(« capability bounding set ») est un
mécanisme qui peut être utilisé pour limiter les
capacités qui peuvent être obtenues lors d'un
execve(2).
- Depuis Linux 2.6.25, c'est un ensemble de capacités par
thread. Dans les noyaux plus anciens, la limitation des capacités
était un attribut pour l'ensemble du système, partagé
par tous les threads du système.
- Pour plus de détails, voir Ensemble de limitation des
capacités, ci-dessous.
- Ambient (ambiant)
(depuis Linux 4.3)
- Il s'agit d'un ensemble de capacités préservées au
travers d'un execve(2) d'un programme non privilégié.
L'ensemble de capacités ambiantes obéit à la
règle invariable qu'aucune capacité ne peut être
ambiante si elle n'est pas à la fois permise et
héritable.
- L'ensemble de capacités ambiantes peut être directement
modifié avec prctl(2). Les capacités ambiantes sont
automatiquement diminuées si une capacités soit permises
soit héritables correspondantes sont diminuées.
- L'exécution d'un programme qui change l'UID ou le GID à
cause des bits set-user-ID ou set-group-ID, ou l'exécution d'un
programme qui a un ensemble de capacités de fichier supprimera
l'ensemble ambiant. Les capacités ambiantes sont ajoutées
à l'ensemble des capacités permises et assignées
à l'ensemble des capacités effectives quand execve(2)
est appelé. Si les capacités ambiantes font que les
capacités permises et ambiantes d'un processus sont accrues durant
un execve(2), cela ne déclenche pas le mode
« secure-execution » décrit dans
ld.so(8).
Un enfant créé par fork(2) hérite
d'une copie des ensembles de capacités de son parent. Pour des
détails sur la façon dont execve(2) affecte les
capacités, voir Transformation des capacités lors d'un
appel execve() plus bas.
En utilisant capset(2), un thread peut manipuler ses
propres ensembles de capacités ; voir Ajuster les ensembles
de capacités par programmation ci-dessous).
À partir de Linux 3.2, le fichier
/proc/sys/kernel/cap_last_cap contient la valeur numérique de
la capacité la plus élevée qui soit acceptée par
le noyau en cours d'exécution ; cette valeur peut être
utilisée pour déterminer le bit le plus élevé
qui puisse être défini dans un ensemble de
capacités.
Capacités de fichier
Depuis Linux 2.6.24, le noyau prend en charge l'association
d'ensembles de capacités avec un fichier exécutable à
l'aide de setcap(8). Les ensembles de capacités du fichier
sont stockés dans un attribut étendu (consultez
setxattr(2) et xattr(7)) appelé
security.capability. Écrire dans cet attribut étendu
nécessite la capacité CAP_SETFCAP. Les ensembles de
capacités d'un fichier, combinés avec les ensembles de
capacités du thread, déterminent les capacités d'un
thread après un execve(2).
Les trois ensembles de capacités de fichier
sont :
- Permitted
(anciennement forced (forcé)) :
- Ces capacités sont automatiquement permises au thread, quelles que
soient ses capacités héritables.
- Inheritable
(anciennement allowed (autorisé)) :
- Cet ensemble est combiné par un ET avec l'ensemble héritable
du thread pour savoir quelles capacités de l'ensemble des
capacités héritables sont permises dans l’ensemble
permis du thread après l'appel à execve(2).
- Effective
(effectif) :
- Il ne s'agit pas d'un ensemble, mais plutôt d'un unique bit. Si le
bit est positionné, alors, lors d'un execve(2), toutes les
nouvelles capacités permises pour le thread sont également
positionnées dans l'ensemble effectif. Si ce bit n'est pas
positionné, alors, après un execve(2), aucune des
nouvelles capacités permises ne se trouvera dans le nouvel ensemble
effectif.
- Activer le bit des capacités effectives d'un fichier implique que
toute capacité de fichier permise ou héritable qui permet
à un thread d'obtenir les capacités permises correspondantes
lors d'un execve(2) (consultez Transformation des
capacités lors d'un appel execve() ci-dessous) fera que ce
fichier aura aussi cette capacité dans son ensemble effectif.
Ainsi, lors de l'ajout de capacités à un fichier
(setcap(8), cap_set_file(3), cap_set_fd(3)), si
l’attribut effectif pour une des capacités est
activé, alors l'attribut effectif doit également être
activé pour toutes les autres capacités dont
l’attribut permis ou héritable correspondant est
activé.
Pour permettre l'extensibilité, le noyau prend en charge un
système pour coder un numéro de version dans l'attribut
étendu security.capability qui est utilisé pour
implémenter les capacités de fichier. Ces numéros de
version sont intégrés à l'implémentation et pas
directement visibles aux applications de l'espace utilisateur. À ce
jour, les versions suivantes sont prise en charge :
- VFS_CAP_REVISION_1
- C'était l'implémentation d'origine de la capacité de
fichier qui prenait en charge les masques 32 bits pour les
capacités de fichier.
- VFS_CAP_REVISION_2
(depuis Linux 2.6.25)
- Cette version permet des masques de capacité de fichier d'une
taille de 64 bits, ce qui était nécessaire, car le
nombre de capacités prises en charge dépassait 32. Le
noyau continue de façon transparente à prendre en charge
l'exécution de fichiers qui ont des masques de capacité
version 1 32 bits, mais lors de l'ajout de capacités
à des fichiers qui n'avaient pas encore de capacités ou lors
de la modification des capacités de fichiers existants, il utilise
automatiquement le système de la version 2 (ou
éventuellement la version 3, comme décrit plus
bas).
- VFS_CAP_REVISION_3
(depuis Linux 4.14)
- Les capacités de fichier version 3 sont fournies pour
prendre en charge les capacités de fichier mises dans un espace de
noms (décrites plus bas).
- Comme avec les capacités de fichier version 2, les masques
de capacité version 3 ont une longueur de 64 bits.
Mais en complément, l'UID root de l'espace de noms est codé
dans l'attribut étendu security.capability (un UID root
d'espace de noms est la valeur à laquelle l'UID 0 dans cet
espace de noms correspond dans l'espace de noms utilisateur initial).
- Les capacités de fichier version 3 sont conçues pour
coexister avec les capacités version 2 ;
c'est-à-dire que, sur un système Linux moderne, il peut y
avoir certains fichiers avec des capacités version 2 tandis
que d'autres ont des capacités version 3.
Avant Linux 4.14, le seul type d'attribut étendu de
capacité de fichier qui pouvait être attaché à
un fichier était un attribut VFS_CAP_REVISION_2. Depuis
Linux 4.14, la version de l'attribut étendu
security.capability attaché à un fichier dépend
des circonstances dans lesquelles l'attribut a été
créé.
À partir de Linux 4.14, un attribut étendu
security.capability est créé automatiquement (ou
converti) en attribut version 3 (VFS_CAP_REVISION_3) si les
deux conditions suivantes sont vraies :
- Le thread qui écrit l'attribut réside dans un espace de noms
utilisateur non initial (plus précisément, le thread
réside dans un espace de noms utilisateur autre que celui à
partir duquel le système de fichiers sous-jacent a
été monté).
- Le thread a la capacité CAP_SETFCAP sur l'inœud du
fichier, ce qui veut dire que (a) le thread a la capacité
CAP_SETFCAP dans son propre espace de noms utilisateur et (b) l'UID
et le GID de l'inœud du fichier a des correspondances dans l'espace
de noms utilisateur de celui qui écrit.
Quand un attribut étendu security.capability
VFS_CAP_REVISION_3 est créé, l'UID root de l'espace de
noms utilisateur du thread qui crée l'attribut est enregistré
dans l'attribut étendu.
Par contre, la création ou la modification d'un attribut
étendu security.capability à partir d'un thread
privilégié (CAP_SETFCAP) qui réside dans
l'espace de noms où le système de fichiers sous-jacent a
été monté (ce qui correspond normalement à
l'espace de noms utilisateur initial) a automatiquement pour
conséquence la création d'un attribut version 2
(VFS_CAP_REVISION_2).
Veuillez noter que la création d'un attribut étendu
security.capability version 3 est automatique.
C'est-à-dire que losrsqu'une application de l'espace utilisateur
écrit (setxattr(2)) un attribut security.capability au
format de la version 2, le noyau créera automatiquement un
attribut version 3 si l'attribut est créé dans les
conditions décrites plus haut. En parallèle, quand un attribut
security.capability version 3 est
récupéré (getxattr(2)) par un processus qui
réside dans un espace de noms utilisateur qui a été
créé par l'UID root (ou un descendant de cet espace de noms
utilisateur), l'attribut renvoyé est (automatiquement)
simplifié pour apparaître comme un attribut version 2
(c'est-à-dire que la valeur renvoyée est la taille de
l'attribut version 2 et n'inclut pas l'UID root). Ces transpositions
automatiques signifient qu'aucune modification n'est requise pour les outils
de l'espace utilisateur (par exemple setcap(1) getcap(1)) pour
que ces outils soient utilisés pour créer et
récupérer des attributs security.capability
version 3.
Veuillez noter qu'un fichier peut se voir associé un
attribut étendu security.capability version 2 ou
version 3, mais pas les deux à la fois : la
création ou la modification de l'attribut étendu
security.capability modifiera automatiquement la version selon les
conditions dans lesquelles l'attribut étendu est créé
ou modifié.
Durant un execve(2), le noyau calcule les nouvelles
capacités du processus en utilisant l'algorithme suivant :
P'(ambient) = (le fichier est privilégié) ? 0 : P(ambient)
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & P(bounding)) | P'(ambient)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient)
P'(inheritable) = P(inheritable) [c'est-à-dire inchangé]
P'(bounding) = P(bounding) [c'est-à-dire inchangé]
où :
- P()
- indique la valeur d'un ensemble de capacités du thread avant le
execve(2)
- P'()
- indique la valeur d'un ensemble de capacités du thread après
le execve(2)
- F()
- indique la valeur d'un ensemble de capacités du fichier
Veuillez noter les détails suivants concernant les
règles de transformation de capacités ci-dessus :
- L'ensemble de capacités ambiantes est présent seulement
depuis Linux 4.3. Lors de la détermination de la
transformation de l'ensemble ambiant durant un execve(2), un
fichier privilégié est un fichier qui a des capacités
ou le bit set-user-ID ou le bit set-group-ID positionné.
- Avant Linux 2.6.25, l'ensemble de limitation de capacités
était un attribut au niveau du système, partagé par
tous les threads. Cette valeur au niveau du système était
employée pour calculer le nouvel ensemble de capacités
permises durant un execve(2) de la même manière que
cela est montré plus haut pour P(bounding).
Note : durant les transitions de capacité
décrite plus haut, les capacités de fichier peuvent
être ignorées (traitées comme si elles étaient
vides) pour les mêmes raisons que les bits set-user-ID et
set-group-ID sont ignorés ; voir execve(2). Les
capacités de fichier sont ignorées de la même
manière si le noyau a été lancé avec l'option
no_file_caps.
Note : conformément aux règles
ci-dessus, si un processus avec des UID différents de zéro
exécutent un execve(2), alors toutes les capacités
présentes dans son ensemble de capacités permises et
effectives seront supprimées. Pour le traitement de capacités
quand un processus avec un UID de zéro exécute un
execve(2), consultez ci-dessous Capacités et
exécution de programmes par le superutilisateur.
Un binaire passif aux capacités est une application qui a
été marquée pour avoir des capacités de fichier,
mais n'a pas été convertie pour utiliser l'API
libcap(3) pour manipuler ses capacités (en d'autres mots,
c'est un programme set-user-iD-root traditionnel qui a été
modifié pour utiliser des capacités de fichier, mais dont le
code n'a pas été modifié pour comprendre les
capacités). Pour ce type d'application, le bit de capacité
effective est défini sur le fichier, de telle sorte que les
capacités de fichier permises soient activées automatiquement
dans l'ensemble de capacités effectives du processus lors de
l'exécution du fichier. Le noyau reconnaît un fichier qui a un
bit de capacité effective défini comme passif aux
capacités en vue de la vérification décrite ici.
Lors de l'exécution d'un binaire passif aux
capacités, le noyau vérifie si le processus a obtenu toutes
les capacités permises qui sont spécifiées dans
l'ensemble de capacités permises de fichier, après que les
transformations de capacité décrites plus haut ont
été exécutées (la raison habituelle pour
laquelle cela pourrait ne pas se produire est que l'ensemble de
limitation de capacités a interdit certaines des capacités
dans l'ensemble de capacités permises de fichier). Si le processus
n'obtient pas l'ensemble complet de capacités permises de fichier,
alors l'execve(2) échoue avec l'erreur EPERM. Cela
évite de possibles risques de sécurité qui pourraient
survenir quand une application passive aux capacités est
exécutée avec moins de privilèges que
nécessaire. Notez que, par définition, l'application ne
pourrait pas reconnaître elle-même ce problème, dans la
mesure où elle n'emploie pas l'API libcap(3).
Capacités et exécution de programmes par le
superutilisateur
Afin de refléter les sémantiques traditionnelles
d'UNIX, le noyau effectue un traitement particulier des capacités de
fichier quand un processus avec l'UID 0 (superutilisateur)
exécute un programme et quand un programme set-user-ID-root est
exécuté.
Après avoir réalisé toutes les modifications
de l'ID effectif du processus qui ont été
déclenchées par le bit de mode set-user-ID du binaire (par
exemple, le changement de l'UID à 0 (superutilisateur) parce
qu'un programme set-user-ID-root a été exécuté),
le noyau calcule les ensembles de capacités de fichier comme
suit :
- (1)
- Si l'UID réel ou effectif du processus est 0
(superutilisateur), alors les ensembles de capacités
héritables et permises de fichier sont ignorés ; ils
sont plutôt considérés théoriquement comme
remplis de uns (c'est-à-dire, toutes les capacités
activées). Il y a une exception à ce comportement,
décrite ci-dessous dans la section Programmes set-user-ID-root
qui ont des capacités de fichier.
- (2)
- Si l'UID effectif du processus est 0 (superutilisateur) ou le bit
des capacités effectives du fichier est en fait activé,
alors le bit des capacités effectives du fichier est
théoriquement défini à un (activé).
Ces valeurs théoriques pour les ensembles de
capacités de fichier sont alors utilisées comme
décrites ci-dessus pour calculer la transformation des
capacités du processus durant l'execve(2).
Alors, quand un processus avec des UID différents de
zéro appelle execve(2) sur un programme set-user-ID-root qui
n'a pas de capacités attachées ou quand un processus dont les
UID réel et effectif sont zéro applique execve(2) sur
un programme, le calcul des nouvelles capacités permises du processus
est simplifié à :
P'(permitted) = P(inheritable) | P(bounding)
P'(effectives) = P'(permitted)
En conséquence, le processus obtient toutes les
capacités dans ses ensembles de capacités permises et
effectives, à l'exception de celles supprimées par l'ensemble
de limitation de capacités (dans le calcul de P'(permitted), le terme
P'(ambient) peut être simplifié parce qu'il est par
définition un sous-ensemble propre de P(inheritable)).
Les traitements particuliers de l'UID 0 (superutilisateur)
décrits dans cette sous-section peuvent être
désactivés en utilisant le mécanisme de
« securebits » décrit plus bas.
Il y a une exception au comportement décrit dans
Capacités et exécution de programmes par le
superutilisateur ci-dessus. Si (a) le binaire qui est en cours
d'exécution a des capacités attachées, (b) l'UID
réelle du processus n'est pas 0 (supertutilisateur) et
(c) l'UID effectif du processus est 0 (superutilisateur),
alors les bits de capacité de fichier sont honorés
(c'est-à-dire qu'ils ne sont pas théoriquement
considérés comme remplis de uns). La circonstance habituelle
dans laquelle cette situation peut se produire est lors de
l'exécution d'un programme set-user-ID-root qui a aussi les
capacités de fichier. Quand un programme de ce type est
exécuté, le processus obtient simplement les capacités
accordées par le programme (c'est-à-dire pas toutes les
capacités comme cela pourrait se produire lors de l'exécution
d'un programme set-user-ID-root qui ne possède aucune capacité
de fichier associée).
Notez qu'il est possible d'assigner un ensemble de
capacités vide à un fichier de programme et donc qu'il est
possible de créer un programme set-user-ID-root qui modifie
en 0 le set-user-ID effectif et sauvegardé du processus qui
exécute le programme, mais ne confère aucune capacité
à ce processus.
L’ensemble de limitation des capacités
(« capability bounding set ») est un
mécanisme de sécurité qui peut être
utilisé pour limiter les capacités qui peuvent être
obtenues lors d'un execve(2). L’ensemble de limitation de
capacités est utilisé de cette façon :
- Lors d'un execve(2), l’ensemble de limitation de
capacités est combinée par un ET binaire avec l'ensemble des
capacités autorisées du fichier, et le résultat de
cette opération est placé dans l'ensemble des
capacités autorisées du thread. L’ensemble de
limitation de capacités permet donc de limiter les capacités
permises qui peuvent être accordées par un fichier
exécutable.
- (Depuis Linux 2.6.25) L’ensemble de limitation de
capacités agit comme un surensemble limitant les capacités
qu'un thread peut ajouter à son ensemble de capacités
héritables en utilisant capset(2). Cela signifie que si une
capacité ne se trouve pas dans l'ensemble de limitation des
capacités, alors un thread ne peut ajouter cette capacité
dans son ensemble de capacités héritables, même si
elle se trouvait dans son ensemble de capacités permises, et ne
peut donc pas conserver cette capacité dans son ensemble de
capacités permises lorsqu'il exécute avec execve(2)
un fichier qui a cette capacité dans son ensemble de
capacités héritables.
Notez que l’ensemble de limitation de capacités
masque les capacités permises du fichier, mais pas les
capacités héritées. Si un thread conserve une
capacité dans son ensemble de capacités héritées
et que cette capacité ne se trouve pas dans l'ensemble de limitation
des capacités, alors il peut toujours obtenir cette capacité
dans son ensemble de capacités permises en exécutant un
fichier qui a la capacité dans son ensemble de capacités
héritées.
Suivant la version du noyau, l’ensemble de limitation de
capacités est un attribut au niveau du système ou un attribut
par processus.
Ensemble de limitation de capacités après
Linux 2.6.25
Depuis Linux 2.6.25, l’ensemble de limitation de
capacités est un attribut par thread. (L'ensemble de limitation
de capacités au niveau du système décrite ci-dessous
n'existe plus.)
L’ensemble de limitation est hérité du parent
du thread au travers d'un fork(2) et est préservé au
travers d'un execve(2).
Un thread peut enlever des capacités de son ensemble de
limitation de capacités en utilisant l'opération
PR_CAPBSET_DROP de prctl(2), à condition qu'il
possède la capacité CAP_SETPCAP. Une fois qu'une
capacité a été supprimée de l'ensemble de
limitation, elle ne peut y être remise. Un thread peut
déterminer si une capacité est dans son ensemble de limitation
de capacités en utilisant l'opération PR_CAPBSET_READ
de prctl(2).
La suppression de capacités dans l'ensemble de limitation
des capacités n'est prise en charge que si les capacités de
fichier sont compilées dans le noyau. Avant Linux 2.6.33, les
capacités de fichier étaient une fonctionnalité
optionnelle configurable ua moyen de l'option
CONFIG_SECURITY_FILE_CAPABILITIES. Depuis Linux 2.6.33,
l'option de configuration a été supprimée et les
capacités de fichier font maintenant toujours partie du noyau. Quand
les capacités de fichier sont compilées dans le noyau, le
processus init (l'ancêtre de tous les processus)
démarre avec un ensemble de limitation complet. Si les
capacités de fichier ne sont pas compilées dans le noyau,
init démarre alors avec un ensemble de limitation complet,
à l'exception de CAP_SETPCAP, parce que cette capacité
a une autre signification quand il n'y a pas de capacités de
fichier.
Supprimer une capacité de l’ensemble de limitation
de capacités ne la supprime pas de l'ensemble héritable d'un
thread. Cependant, il empêche de rajouter la capacité dans
l'ensemble héritable du thread par la suite.
Ensemble de limitation de capacités avant
Linux 2.6.25
Avant Linux 2.6.25, l’ensemble de limitation de
capacités est un attribut au niveau du système qui affecte
tous les threads. L’ensemble de limitation de capacités est
accessible par le fichier /proc/sys/kernel/cap-bound (le masque de
bits est exprimé comme un nombre décimal signé dans
/proc/sys/kernel/cap-bound, ce qui entretient les confusions).
Seul le processus init peut configurer des capacités
dans l'ensemble de limitation de capacités ; en dehors de
cela, le superutilisateur (plus précisément : un
processus avec la capacité CAP_SYS_MODULE) peut uniquement
supprimer des capacités de cet ensemble.
Sur un système standard, l’ensemble de limitation
élimine toujours la capacité CAP_SETPCAP. Pour
supprimer cette restriction (attention, c'est dangereux !), modifiez
la définition de CAP_INIT_EFF_SET dans
include/linux/capability.h et recompilez le noyau.
L’ensemble de limitation de capacités pour tout le
système a été ajoutée à
Linux 2.2.11.
Afin de préserver la sémantique traditionnelle pour
les transitions entre des UID 0 et des UID différents de
zéro, le noyau modifie les ensembles de capacités d'un thread
de la façon suivante lors de modifications des UID réel,
effectif, sauvegardé et du système de fichiers (avec
setuid(2), setresuid(2) et compagnie) :
- Si un ou plus des UID réels, effectifs ou sauvés
étaient égal à 0, et qu'à la suite de
la modification d'UID, tous ces ID ont une valeur différente de
zéro, et toutes les capacités sont supprimées des
ensembles de capacités permises, effectives et ambiantes.
- Si l'UID effectif était 0 et devient différent de
zéro, toutes les capacités sont supprimées de
l'ensemble effectif.
- Si l'UID effectif est modifié d'une valeur différente de
zéro à 0, l'ensemble des capacités permises
est copié dans l'ensemble des capacités effectives.
- Si l’UID du système de fichiers est modifié
de 0 à une valeur différente de zéro
(consultez setfsuid(2)), les capacités suivantes sont
supprimées de l'ensemble effectif : CAP_CHOWN,
CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER,
CAP_FSETID, CAP_LINUX_IMMUTABLE (depuis
Linux 2.6.30), CAP_MAC_OVERRIDE et CAP_MKNOD (depuis
Linux 2.6.30). Si l’UID du système de fichiers
devient 0, chacune de ces capacités est activée dans
l'ensemble des capacités effectives si elle faisait partie de
l'ensemble des capacités permises.
Si un thread qui a une valeur 0 pour un ou plus de ses UID
ne veut pas que son ensemble de capacités permises soit vidé
lorsqu'il redéfinit tous ses UID à des valeurs non nulles, il
peut le faire avec l'attribut « securebits » de
SECBIT_KEEP_CAPS décrit ci-dessous.
Un thread peut obtenir ou modifier ses ensembles de
capacités permises, effectives et héritées en utilisant
les appels système capget(2) et capset(2). Cependant,
il faut leur préférer l'utilisation de cap_get_proc(3)
et cap_set_proc(3), toutes deux fournies par le paquet libcap.
Les règles suivantes gouvernent les modifications des ensembles de
capacités d'un thread :
- Si l'appelant n'a pas la capacité CAP_SETPCAP, le nouvel
ensemble des capacités héritables doit être un
sous-ensemble de l'union des ensembles de capacités
héritables et des capacités permises.
- (Depuis Linux 2.6.25) Le nouvel ensemble héritable doit
être un sous-ensemble de l'ensemble héritable existant et de
l'ensemble de limitation de capacités.
- Le nouvel ensemble des capacités permises doit être un
sous-ensemble de l'ensemble des capacités permises existant
(c'est-à-dire qu'il n'est pas possible d'obtenir des
capacités permises que le thread n'a pas actuellement).
- Le nouvel ensemble effectif doit être un sous-ensemble du nouvel
ensemble des capacités permises.
À partir de Linux 2.6.26, si les capacités de
fichier sont activées dans le noyau, Linux implémente un
ensemble d'attributs securebits par thread qui peuvent être
utilisés pour désactiver la gestion particulière des
capacités pour l'UID 0 (root). Ces attributs sont les
suivants :
- SECBIT_KEEP_CAPS
- Activer cet attribut permet à un thread qui a un UID (ou plus)
égal à 0 de conserver ses capacités dans son
ensemble des capacités permises quand il change tous ses UID et que
plus aucun n'est zéro. Si cet attribut est désactivé,
alors ces changements d'UID feront perdre au thread toutes ses
capacités permises. Cet attribut est toujours
désactivé lors d'un execve(2).
- Notez que même quand l'attribut SECBIT_KEEP_CAPS est actif,
les capacités effectives d'un thread sont supprimées quand
il change son UID effectif pour une valeur différente de
zéro. Néanmoins, si le thread a activé cet attribut
et que son UID effectif est déjà différent de
zéro et si le thread change ensuite tous les autres UID pour des
valeurs différentes de zéro, alors, les capacités
effectives ne seront pas supprimées.
- L'activation de l'attribut SECBIT_KEEP_CAPS est ignorée si
l'attribut SECBIT_NO_SETUID_FIXUP est actif (ce dernier attribut
fournit un surensemble des effets de l'attribut
précédent).
- Cet attribut fournit la même fonctionnalité que l'ancienne
opération PR_SET_KEEPCAPS de prctl(2).
- SECBIT_NO_SETUID_FIXUP
- Activer cet attribut stoppe l'ajustement des ensembles de capacités
permises, effectives et ambiantes du processus par le noyau lorsque les
UID effectifs et du système de fichiers du thread passent d'une
valeur zéro à une valeur différente de zéro.
Consultez Effet des modifications d'UID sur les capacités
plus haut.
- SECBIT_NOROOT
- Si cet attribut est activé, alors le noyau n'accorde pas les
capacités lorsqu'un programme set-user-ID-root est
exécuté ou lorsqu'un processus dont l'UID effectif ou
réel est zéro appelle execve(2) (consultez
Capacités et exécution de programmes par le
superutilisateur ci-dessus).
- SECBIT_NO_CAP_AMBIENT_RAISE
- Activer cet attribut désactive l'élévation des
capacités ambiantes au moyen de l'opération
PR_CAP_AMBIENT_RAISE de prctl(2).
Chacun des attributs de « base »
ci-dessus a un attribut compagnon
« verrouillé ». L'activation d'un
attribut « verrouillé » est
irréversible et permet d'éviter toute modification
ultérieure de l'attribut de « base »
correspondant. Les attributs
« verrouillé » sont :
SECBIT_KEEP_CAPS_LOCKED, SECBIT_NO_SETUID_FIXUP_LOCKED,
SECBIT_NOROOT_LOCKED et
SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED.
Les attributs securebits peuvent être
modifiés et récupérés en utilisant les
opérations PR_SET_SECUREBITS et PR_GET_SECUREBITS de
prctl(2). La capacité CAP_SETPCAP est nécessaire
pour modifier ces attributs. Notez que les constantes SECBIT_* ne
sont disponibles qu'après l'inclusion du fichier d'en-tête
<linux/securebits.h>.
Les attributs securebits sont hérités par les
processus enfants. Lors d'un execve(2), tous les attributs sont
conservés, à l'exception de SECBIT_KEEP_CAPS qui est
toujours désactivé.
Une application peut utiliser l'appel suivant pour se verrouiller
elle-même, ainsi que tous ses descendants, dans un environnement
où la seule façon d'obtenir des capacités est
d'exécuter un programme avec les capacités de fichiers
associées :
prctl(PR_SET_SECUREBITS,
/* SECBIT_KEEP_CAPS désactivé */
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
/* Activation/verrouillage de SECBIT_NO_CAP_AMBIENT_RAISE
non requis */
Un programme set-user-ID dont l'UID correspond à l'UID qui
a créé par un espace de noms utilisateur donnera des
capacités dans les ensembles de capacités permises et
effectives du processus lorsqu'il était utilisé par un
processus dans l'espace de noms ou tout espace de noms utilisateur qui en
est issu.
Les règles de transformation des capacités du
processus pendant un execve(2) sont exactement comme décrites
dans Transformation des capacités lors d'un appel execve() et
Capacités et exécution de programmes par le
superutilisateur ci-dessus;à la différence que, dans la
seconde sous-section, « root » est l'UID du
créateur de l'espace de noms utilisateur.
Capacités de fichier mises dans un espace de noms
Les capacités de fichier traditionnelles
(c'est-à-dire version 2) n'associent qu'un ensemble de masques
de capacité à un fichier binaire exécutable. Quand un
processus exécute un binaire avec des capacités de ce type, il
obtient les capacités associées (dans son espace de noms
utilisateur) comme pour les règles décrites ci-dessus dans
Transformation des capacités lors d'un appel execve().
Étant donné que les capacités de fichier
version 2 confèrent des capacités pour
l'exécution de processus quel que soit l'espace de noms utilisateur
dans lequel il réside, seuls les processus privilégiés
ont le droit d'associer des capacités avec un fichier. Ici,
« privilégié » veut dire un
processus qui a la capacité CAP_SETFCAP dans l'espace de noms
utilisateur où le système de fichiers a été
monté (normalement, l'espace de noms initial de l'utilisateur). Cette
limitation rend les capacités de fichier inutiles dans certains cas
d'usage. Par exemple, dans les conteneurs d'un espace de noms utilisateur,
il peut être souhaitable de pouvoir créer un binaire qui
confère des capacités uniquement au processus
exécuté dans ce conteneur, mais pas aux processus
exécutés en dehors du conteneur.
Linux 4.14 a ajouté des capacités de fichier
appelées « mises dans un espace de noms »
pour gérer ce genre de cas d'usage. Les capacités de fichier
mises dans un espace de noms sont enregistrées en tant qu'attribut
étendu security.capability version 3
(c'est-à-dire VFS_CAP_REVISION_3). Un attribut de ce type est
créé automatiquement dans les circonstances décrites
ci-dessus dans Versionnage d'attributs étendus de capacité
de fichier. Quand un attribut étendu security.capability
version 3 est créé, le noyau n'enregistre pas que les
masques de capacité dans l'attribut étendu, mais aussi l'UID
root de l'espace de noms.
Comme c'est le cas avec un binaire qui possède des
capacités de fichier VFS_CAP_REVISION_2, un binaire avec des
capacités de fichier VFS_CAP_REVISION_3 confère des
capacités à un processus durant un execve().
Néanmoins, ces capacités ne sont conférées que
si le processus est exécuté par un processus qui réside
dans un espace de noms utilisateur dont l'UID 0 correspond à
l'UID root qui est sauvegardé dans l'attribut étendu, ou quand
il est exécuté par un processus qui réside dans un
descendant de ce type d'espace de noms.
Pour en savoir plus sur les interactions entre les
capacités et les espaces de noms utilisateur, consultez
user_namespaces(7).