Effectivement on ne s'est pas bien compris. Ce que je veux dire c'est que dans la tradition des systèmes à capacités, les données vont avec leur droit d'accès. Il n'y a plus de donnée "plate" sur laquelle tu fais des actions, tirées d'un ensemble global d'actions possible, en y étant autorisé ou pas par une politique de sécurité, chaque donnée vient avec l'ensemble des opérations qu'elle permet et c'est ce que tu utilises pour agir dessus. Par exemple les "file descriptors" utilisés en mode Capsicum contiennent des masques qui indiquent les droits que la possession du fd donne sur le fichier (ou plus généralement la ressource) correspondant. Donne ce fd à quelqu'un, et tu lui transfères du même coup ces droits. Et tu les as parce qu'à ton démarrage le système te les as fournis.
(Ça c'est dans un mode "tout capacité; capsicum est un système hybride unix/capacités où un processus lancée depuis le shell classique va avoir tous les droits de l'utilisateur, et donc la possibilité de "forger" ces file-descriptor avec les droits un peu qu'elle veut. Ensuite elle demande explicitement à passer en "mode capabilités" et il devient impossible de forger de nouveaux fd, on peut seulement en utiliser des existants ou en obtenir en communiquant avec un autre process)
si je pige bien, ce qui fait la spécificité de capsicum ( qui va aussi séparer les objets manipulé ), c'est le fait que la source primaire de la politique appliqué sur les objets soit le programme lui même ( via son code ), et pas une base de référence externe
Oui, c'est une différence plus concrète et moins philosophique. Ça fait qu'à mon avis les deux sont complémentaires : au développeur de réduire au maximum les droits demandés par son application en utilisant Capsicum ou autre, et l'admin de la machine peut par dessus rajouter des politiques SELinux/AppArmor qui correspondent à des contraintes supplémentaires locales (au risque de rendre inopérantes certaines fonctionnalités de l'appli). Un aspect important de l'approche "la sécurité est dans le code" est qu'en pratique pour ne pas utiliser trop de droits il faut un bon design, et le design il est décidé par le programmeur, donc il vaut mieux qu'il soit impliqué dans le début dans les questions de sécurité plutôt que mettre ça en jeu "après coup" avec un outil qui fonctionne "à l'extérieur".
séparer ton process en composant ( ie ce que le papier appelle "logical applications" ) reviens plus ou moins à refaire le travail de l'os ( qui sépare tout sous forme de process )
Il y a une légère incompréhension ici: les autres de l'article proposent de changer les applications en les découpant en plein de petits processus pour faciliter le partage des privilèges (par exemple au lieu de faire tourner dans le processus maître le parsing des données utilisateur, on se méfie de cette tâche propices aux buffer overflow et on le fait tourner dans un sous-process forké depuis le maître, à qui on passe juste les file-descriptor des données concernées et aucun autre droit). Ils désignent par "logical application" le groupe de processus qui coopèrent pour faire ce que veut l'utilisateur, correspondant au process monolithique que tu avais avant.
Un exemple de découpage intéressant que j'utilise souvent : aujourd'hui quand tu veux ouvrir un fichier dans ton éditeur de texte, le code appelle la fonction "OpenFile" de l'API que tu utilises (Gtk ou Qt par exemple), qui va te proposer de naviguer dans ton filesystem. Ça veut dire que pour proposer cette fonctionnalité le programme doit avoir le droit de lecture sur tout le filesystem. Si à la place tu appelles un processus privilégié auxiliaire qui prend tes métadonnées en entrée (le type de fichier que tu veux, les droits que tu demandes dessus, tout ça), interagis avec l'utilisateur, et te rends le file_descriptor qui va bien ensuite, le programme lui-même n'a plus besoin de droit de lecture/exploration sur le filesystem, et c'est une grosse catégorie d'exploitations en moins à considérer en cas de faille d'injection de code. Mais pour pouvoir réduire ces privilèges il est crucial d'avoir pensé au découpage de l'application en plusieurs processus selon les bordures des droits nécessaires au fonctionnement des différentes parties.
Évidemment ça conduit à une augmentation des coûts de communication, mais personnellement j'abandonnerais avec plaisir un petit peu de perfs pour beaucoup plus de sécurité. C'est un peu la même chose que le débat {micro,macro}kernel, mais dans un domaine où les découpages restent plus gros et les performances souvent moins contraintes par la communication.
[^] # Re: Capsicum
Posté par gasche . En réponse au journal Un article sur le sandboxing de Chrome sous Linux. Évalué à 7.
Effectivement on ne s'est pas bien compris. Ce que je veux dire c'est que dans la tradition des systèmes à capacités, les données vont avec leur droit d'accès. Il n'y a plus de donnée "plate" sur laquelle tu fais des actions, tirées d'un ensemble global d'actions possible, en y étant autorisé ou pas par une politique de sécurité, chaque donnée vient avec l'ensemble des opérations qu'elle permet et c'est ce que tu utilises pour agir dessus. Par exemple les "file descriptors" utilisés en mode Capsicum contiennent des masques qui indiquent les droits que la possession du fd donne sur le fichier (ou plus généralement la ressource) correspondant. Donne ce fd à quelqu'un, et tu lui transfères du même coup ces droits. Et tu les as parce qu'à ton démarrage le système te les as fournis.
(Ça c'est dans un mode "tout capacité; capsicum est un système hybride unix/capacités où un processus lancée depuis le shell classique va avoir tous les droits de l'utilisateur, et donc la possibilité de "forger" ces file-descriptor avec les droits un peu qu'elle veut. Ensuite elle demande explicitement à passer en "mode capabilités" et il devient impossible de forger de nouveaux fd, on peut seulement en utiliser des existants ou en obtenir en communiquant avec un autre process)
Oui, c'est une différence plus concrète et moins philosophique. Ça fait qu'à mon avis les deux sont complémentaires : au développeur de réduire au maximum les droits demandés par son application en utilisant Capsicum ou autre, et l'admin de la machine peut par dessus rajouter des politiques SELinux/AppArmor qui correspondent à des contraintes supplémentaires locales (au risque de rendre inopérantes certaines fonctionnalités de l'appli). Un aspect important de l'approche "la sécurité est dans le code" est qu'en pratique pour ne pas utiliser trop de droits il faut un bon design, et le design il est décidé par le programmeur, donc il vaut mieux qu'il soit impliqué dans le début dans les questions de sécurité plutôt que mettre ça en jeu "après coup" avec un outil qui fonctionne "à l'extérieur".
Il y a une légère incompréhension ici: les autres de l'article proposent de changer les applications en les découpant en plein de petits processus pour faciliter le partage des privilèges (par exemple au lieu de faire tourner dans le processus maître le parsing des données utilisateur, on se méfie de cette tâche propices aux buffer overflow et on le fait tourner dans un sous-process forké depuis le maître, à qui on passe juste les file-descriptor des données concernées et aucun autre droit). Ils désignent par "logical application" le groupe de processus qui coopèrent pour faire ce que veut l'utilisateur, correspondant au process monolithique que tu avais avant.
Un exemple de découpage intéressant que j'utilise souvent : aujourd'hui quand tu veux ouvrir un fichier dans ton éditeur de texte, le code appelle la fonction "OpenFile" de l'API que tu utilises (Gtk ou Qt par exemple), qui va te proposer de naviguer dans ton filesystem. Ça veut dire que pour proposer cette fonctionnalité le programme doit avoir le droit de lecture sur tout le filesystem. Si à la place tu appelles un processus privilégié auxiliaire qui prend tes métadonnées en entrée (le type de fichier que tu veux, les droits que tu demandes dessus, tout ça), interagis avec l'utilisateur, et te rends le file_descriptor qui va bien ensuite, le programme lui-même n'a plus besoin de droit de lecture/exploration sur le filesystem, et c'est une grosse catégorie d'exploitations en moins à considérer en cas de faille d'injection de code. Mais pour pouvoir réduire ces privilèges il est crucial d'avoir pensé au découpage de l'application en plusieurs processus selon les bordures des droits nécessaires au fonctionnement des différentes parties.
Évidemment ça conduit à une augmentation des coûts de communication, mais personnellement j'abandonnerais avec plaisir un petit peu de perfs pour beaucoup plus de sécurité. C'est un peu la même chose que le débat {micro,macro}kernel, mais dans un domaine où les découpages restent plus gros et les performances souvent moins contraintes par la communication.