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 l'UID effectif est
non-nul). Les processus privilégiés contournent 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).
À partir du noyau 2.2, Linux propose un
mécanisme (encore incomplet) de capacités, qui scinde
les privilèges traditionnellement associés au superutilisateur
en unités distinctes 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_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_CHOWN
- Effectuer toute modification des UID et GID de fichiers (consultez
chown(2)).
- CAP_DAC_OVERRIDE
- Contourne les 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
- Contourne les permissions de lecture de fichiers et celles de lecture et
exécution des répertoires ;
- Invoque open_by_handle_at(2).
- CAP_FOWNER
- Contourne les vérifications pour les opérations qui
demandent que le FS-UID 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 de fichier étendus (consultez
chattr(1)) 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 bit sticky des répertoires pour les suppressions de
fichier ;
- spécifier O_NOATIME dans open(2) et fcntl(2)
pour n'importe quel fichier.
- CAP_FSETID
- Ne pas effacer les bits de permission Set-UID et Set-GID quand un fichier
est modifié ; positionner le bit Set-GID sur un fichier dont
le GID ne correspond à aucun GID du processus appelant.
- CAP_IPC_LOCK
- Verrouiller des pages mémoire (mlock(2), mlockall(2),
mmap(2), shmctl(2)).
- CAP_IPC_OWNER
- Contourne les vérifications pour les opérations sur les IPC
System V.
- CAP_KILL
- Contourne les vérifications pour l'émission de signaux
(consultez kill(2)). Cela inclut l'utilisation de l'ioctl(2)
KDSIGACCEPT.
- CAP_LEASE
(depuis Linux 2.4)
- Demander des baux 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 chattr(1)).
- CAP_MAC_ADMIN
(depuis Linux 2.6.25)
- Surcharger les contrôles d'accès MAC
(« Mandatory Access Control »).
Implémentée pour le module de sécurité
(LSM : « Linux Security Module »)
Smack.
- CAP_MAC_OVERRIDE
(depuis Linux 2.6.25)
- Permettre les modifications de la configuration ou des états MAC.
Implémentée pour le LSM Smack.
- 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 ») ;
- utiliser 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 une socket sur un port privilégié (numéro de
port inférieur à 1024).
- CAP_NET_BROADCAST
- (Inutilisé) Broadcaster et écouter en multicast avec des
sockets.
- CAP_NET_RAW
- utiliser des sockets RAW et PACKET ;
- attacher à n'importe quelle adresse pour un service mandataire
transparent.
- CAP_SETGID
- Effectuer toute manipulation des GID du processus et de la liste de
groupes supplémentaires, utiliser de faux GID sur les socket
UNIX.
- CAP_SETFCAP
(depuis Linux 2.6.24)
- Définir des capacités de fichier
- CAP_SETPCAP
- Si les capacités de fichier sont prises en charge :
autoriser ou interdire toute capacité dans l'ensemble des
capacités permises à 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é de fichiers, puisque CAP_SETPCAP a une toute autre
sémantique pour ces noyaux)
Si les capacités de fichier sont prises en
charge : 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 l'attribut
securebits.
- CAP_SETUID
- Effectuer toute manipulation des UID de processus (setuid(2),
setreuid(2), setresuid(2), setfsuid(2)) ;
transmettre un faux UID sur une socket dans le domaine UNIX.
- CAP_SYS_ADMIN
- Effectuer certaines opérations d'administration comme :
quotactl(2), mount(2), umount(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) ;
- effectuer des opérations IPC_SET et IPC_RMID sur
n'importe quel objet IPC System V ;
- effectuer des opérations sur les attributs étendus
trusted et security (consultez attr(5)) ;
- utiliser lookup_dcookie(2) ;
- utiliser ioprio_set(2) pour configurer une classe d'ordonnancement
IOPRIO_CLASS_RT (avant Linux 2.6.25) et
IOPRIO_CLASS_IDLE ;
- forger des identifiants d'utilisateur lors du passage de
références de sockets ;
- 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 (c'est-à-dire accept(2), execve(2),
open(2) et pipe(2)) ;
- utiliser les attributs CLONE_* qui créent de nouveaux
espaces de nom avec clone(2) et unshare(2) ;
- appeler perf_event_open(2) ;
- accéder aux informations d'événements perf
nécessitant des droits ;
- appeler setns(2) ;
- appeler fanotify_init(2) ;
- effectuer des opérations keyctl(2) KEYCTL_CHOWN et
KEYCTL_SETPERM ;
- effectuer une opération madvise(2)
MADV_HWPOISON ;
- utiliser la commande TIOCSTI de ioctl(2) pour insérer
des caractère dans la file d'entrée 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 d'administration sur de nombreux pilotes
de périphériques.
- CAP_SYS_BOOT
- Utiliser reboot(2) et kexec_load(2).
- CAP_SYS_CHROOT
- Utiliser chroot(2).
- CAP_SYS_MODULE
- Charger ou décharger des modules noyaux (consultez
init_module(2) et delete_module(2)) ; dans les noyaux
antérieurs à 2.6.25 : enlever des capacités de
l'ensemble système de limitation de capacités.
- CAP_SYS_NICE
- Augmenter la valeur de courtoisie (« nice »)
(nice(2), setpriority(2)) et changer la courtoisie de
n'importe quel processus ;
- utiliser des ordonnancements temps-réel pour le processus appelant,
et la modification de l'ordonnancement de n'importe quel processus
(sched_setscheduler(2), sched_setparam(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 ;
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 à d'autres
types de 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 définies par les 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)) ;
- ne pas tenir compte 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 de la limite /proc/sys/fs/mqueue/queues_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 :
- 1.
- Pour toutes les opérations privilégiées, le noyau
doit vérifier si le thread a la capacité requise dans son
ensemble effectif ;
- 2.
- Le noyau doit fournir des appels système permettant de changer et
récupérer les ensembles de capacités d'un
thread.
- 3.
- 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é.
Sous Linux 2.6.14, seules les deux premières clauses
sont remplies.Avant le noyau 2.6.24, seules les deux premières
exigences sont remplies ; depuis le noyau 2.6.24, ces trois
exigences sont remplies.
Chaque thread a trois ensembles contenant zéro ou plus des
capacités ci-dessus :
- Permises :
- 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-UID root ou un programme dont les capacités
associées au fichier permettent cette capacité).
- Héritable :
- Il s'agit d'un ensemble de capacités préservées au
travers d'un execve(2). Il fournit à un processus un
mécanisme pour assigner des capacités à l'ensemble
des capacités permises du nouveau programme lors d'un
execve(2).
- Effectif :
- Il s'agit de l'ensemble des capacités utilisées par le noyau
pour vérifier les permissions du thread.
Un fils créé par fork(2) hérite d'une
copie des ensembles de capacité de son père. Le traitement des
capacités lors d'un execve(2) est décrit plus bas.
En utilisant capset(2), un thread peut manipuler ses
propres ensembles de capacités (voir 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 le noyau 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)) 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 :
- Permises
(anciennement forcées) :
- Ces capacités sont automatiquement permises au thread, quelles que
soient ses capacités héritables.
- Héritables
(anciennement autorisées) :
- 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 permises sont permises pour le thread après
l'appel à execve(2).
- 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é permises correspondantes lors d'un execve(2)
(consultez les règles de transformation décrites
ci-dessous) fournira également cette capacité dans
l'ensemble de capacités effectives du thread. Ainsi, lors de
l'ajout de capacités à un fichier (setcap(8),
cap_set_file(3), cap_set_fd(3)), si le bit effectif pour
une des capacités est activé, alors le bit effectif doit
également être activé pour toutes les
capacités dont le bit permis ou héritable correspondant
est activé.
Durant un execve(2), le noyau calcule les nouvelles
capacités du processus en utilisant l'algorithme suivant :
P'(permises) = (P(héritables) & F(héritables) |
(F(permises) & cap_bset)
P'(effectives) = F(effectives) ? P'(permises) : 0
P'(héritables) = P(héritables) [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 après le
execve(2)
- F
- indique la valeur d'un ensemble de capacités du fichier
- cap_bset
- est la valeur de la limitation de capacités (décrit
ci-dessous).
Capacités et exécution de programmes par root
Pour fournir un root tout puissant en utilisant les
ensembles de capacités, lors d'un execve(2) :
- 1.
- Si on exécute un programme Set-UID root, ou si l'UID réel
est nul, alors les ensembles des capacités héritables et
permises du fichier sont remplis de uns (toutes les capacités
activées).
- 2.
- Si un programme Set-UID root est exécuté, alors le bit des
capacités effectives du fichier est défini à 1
(activé).
L'effet des règles ci-dessus combinées avec les
transformations de capacités ci-dessus, est que lorsqu'un processus
lance (avec execve(2)) un programme Set-UID root, ou lorsqu'un
processus d'UID effectif nul exécute un programme, il obtient toutes
les capacités dans ses ensembles de capacités permises et
effectives, sauf celles qui sont interdites par la limitation de
capacités. Ceci fournit une sémantique identique à
celle fournie par les systèmes UNIX traditionnels.
La 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). La limitation de capacités est utilisée de
cette façon :
- Lors d'un execve(2), la limitation de capacités (un ensemble
de capacités) est combinée avec 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. La limitation de
capacités permet donc de limiter les capacités permises qui
peuvent être accordées à un fichier
exécutable.
- (Depuis Linux 2.6.25) La 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). Ceci 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 la 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, la limitation de capacités est
un attribut au niveau du système ou un attribut par processus.
Limitation de capacités avant
Linux 2.6.25
Dans les noyaux antérieurs à 2.6.25, la limitation
de capacités est un attribut au niveau du système qui affecte
tous les threads. La 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 ; sinon, le
superutilisateur (plus précisément : les programmes
avec la capacité CAP_SYS_MODULE) peut uniquement supprimer des
capacités de cet ensemble.
Sur un système standard, la 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.
La limitation de capacités système a
été ajoutée à Linux à partir du
noyau 2.2.11.
Limitation de capacités après
Linux 2.6.25
Depuis Linux 2.6.25, la limitation de
capacités est un attribut par thread (il n'y a plus
désormais de limitation de capacités au niveau du
système).
La limitation est héritée 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 être 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
fichiers sont compilés dans le noyau. Dans les noyaux
antérieurs à Linux 2.6.33, les capacités de
fichiers étaient une fonctionnalité optionnelle configurable
via l'option CONFIG_SECURITY_FILE_CAPABILITIES. Depuis Linux 2.6.33,
l'option de configuration a été supprimée et les
capacités de fichiers font maintenant toujours partie du noyau. Quand
les capacités de fichiers sont compilées dans le noyau, le
processus init (l'ancêtre de tous les processus)
démarre avec ensemble de limitation complet. Si les capacités
de fichiers 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 fichiers.
Supprimer une capacité de la limitation de capacités
ne la supprime pas de l'ensemble hérité d'un thread. Cependant
il empêche de rajouter la capacité dans l'ensemble
hérité du thread par la suite.
Afin de préserver la sémantique traditionnelle pour
les transitions entre des UID nul et non nul, le noyau modifie les ensembles
de capacités d'un thread de la façon suivante lors de
modifications des UID réel, effectif, sauvé et du
système de fichiers (avec setuid(2), setresuid(2) et
compagnie) :
- 1.
- Si l'UID réel, effectif ou sauvé était égal
à 0, et qu'à la suite de la modification ils sont tous non
nuls, toutes les capacités sont supprimés des ensembles de
capacités permises et effectives.
- 2.
- Si l'UID effectif était nul et devient non nul, toutes les
capacités sont supprimées de l'ensemble effectif.
- 3.
- Si l'UID effectif est modifié d'une valeur non nulle à 0,
l'ensemble des capacités permises est copié dans l'ensemble
des capacités effectives.
- 4.
- Si le fsuid est modifié de 0 à une valeur non nulle
(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 le fsuid devient nul, 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 dont l'un des UID vaut 0 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'opération PR_SET_KEEPCAPS de l'appel système
prctl(2).
Un thread peut obtenir ou modifier ses ensembles de
capacités 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 :
- 1.
- 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.
- 2.
- (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.
- 3.
- 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).
- 4.
- Le nouvel ensemble effectif doit être un sous-ensemble du nouvel
ensemble des capacités permises.
À partir du noyau 2.6.26, si les capacités de
fichiers sont activées, 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 quand il change
ses UID et que plus aucun n'est nul. Si cet attribut est
désactivé, alors ces changements d'UID feront perdre au
thread toutes ses capacités. Cet attribut est toujours
désactivé lors d'un execve(2). 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
par le noyau lorsque les UID effectifs et d'accès aux fichiers du
thread passent d'une valeur nulle à une valeur non nulle.
(Consultez la sous-section Effet des modifications d'UID sur les
capacités.)
- SECBIT_NOROOT
- Si cet attribut est activé, alors le noyau n'autorise pas les
capacités lorsqu'un programme Set-UID root est
exécuté ou lorsqu'un processus dont l'identifiant effectif
ou réel est nul appelle execve(2). (Consultez la
sous-section Capacités et exécution de programmes par
root.)
Chacun des attributs de base ci-dessus a un attribut compagnon de
verrouillage. L'activation d'un attribut de verrouillage est
irréversible et permet d'éviter toute modification
ultérieure de l'attribut de base. Les attributs de verrouillage
sont : SECBIT_KEEP_CAPS_LOCKED,
SECBIT_NO_SETUID_FIXUP_LOCKED et SECBIT_NOROOT_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.
Les attributs securebits sont hérités par les
processus fils. 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 descendant, 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
correspondantes :
prctl(PR_SET_SECUREBITS,
SECBIT_KEEP_CAPS_LOCKED |
SECBIT_NO_SETUID_FIXUP |
SECBIT_NO_SETUID_FIXUP_LOCKED |
SECBIT_NOROOT |
SECBIT_NOROOT_LOCKED);
Depuis le noyau 2.5.27, les capacités sont
optionnelles dans le noyau et peuvent être activées ou
désactivées avec l'option de configuration
CONFIG_SECURITY_CAPABILITIES du noyau.
Le fichier /proc/PID/task/TID/status peut être
utilisé pour voir les ensembles de capacités d'un thread. Le
fichier /proc/PID/status indique les ensembles de capacités du
thread principal d'un thread. Avant Linux 3.8, les capacités
inexistantes étaient vues comme activées (1) dans ces
ensembles. Depuis Linux 3.8, toutes les capacités inexistantes
(au-délà de CAP_LAST_CAP) sont vues comme
désactivées (0).
Le paquet libcap fournit un ensemble de routines pour
écrire et lire les capacités d'un processus, de manière
plus simple et moins susceptible de changer que l'interface fournie par
capset(2) et capget(2). Ce paquet fournit également les
programmes setcap(8) et getcap(8). Il peut être
trouvé à l'adresse :
http://www.kernel.org/pub/linux/libs/security/linux-privs.
Avant le noyau 2.6.24, et depuis le noyau 2.6.24 si
les capacités de fichier ne sont pas activées, un thread avec
la capacité CAP_SETPCAP peut manipuler les capacités
des autres threads. Cependant, ce n'est possible qu'en théorie
puisqu'aucun thread n'a la capacité CAP_SETPCAP dans un des
cas suivants :
- Dans l'implémentation antérieure au noyau 2.6.25,
l'ensemble de limitation de capacités du système,
/proc/sys/kernel/cap-bound, masque toujours cette capacité
et ceci ne peut pas être changé sans modifier les sources du
noyau et le recompiler.
- Si les capacités de fichiers sont désactivées dans
l'implémentation actuelle, alors init démarre sans
cette capacité dans l'ensemble de limitation de capacité de
son processus, et cet ensemble de limitation de capacité est
hérité par tous les processus créés sur le
système.