• [^] # Re: Forkons Fedora !

    Posté par (site web personnel) . En réponse au journal Un fork de Debian à cause de systemd ?. Évalué à 10.

    Je pense que j'ai pas besoin d'expliquer en quoi la syntaxe de bash est complexe, ni en quoi le fait de faire un parser parfait est quasiment impossible, vu que personne ou presque ne connait les centaines de subtilités.

    Donc le souci, si tu rajoutes un DSL en shell, c'est plus du shell. Et ça va bloquer les gens qui vont confondre les 2 syntaxes.

    Mais comme j'avais pas envie de faire un paté sans fin, j'ai pas tout mis, et le véritable souci d'utiliser le shell, c'est que tu peux pas avoir le même niveau de fonctionnalité que systemd en matiére de configuration.

    Et je dit pas ça parce qu'il y a pas des outils en CLI pour faire ça, car je suis sur globalement que ça peut s'écrire. Tu peux faire un chroot, un su, un changement de group, etc.

    Je dit ça parce qu'il y a des endroits ou c'est juste impossible par design du shell lui même, et j'ai pigé ça y a moins de 2 semaines.

    Exemple personnel. Pour rajouter ma pierre à l'édifice de la discussion du TC Debian il y a un an, j'ai codé le support de AppArmor dans systemd ( l'idée étant de réduire la différence entre systemd et upstart, mais y a que systemd ou j'ai réussi à produire du code upstreamable ).

    La fonctionnalité est de pouvoir dire "tel service est lancé avec tel profile". Je teste sur une opensuse, ça marche, j'envoie, c'est mergé debut janvier. Il se trouve que je croise les gens de Tails en avril, qui sont en effet intéressé par la feature, et qui après l'intégration de systemd, testent et trouvent que ça ne marche pas en octobre ( https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=760526 ).

    Il se trouve que par hasard à la recherche de bug à corriger, je passe sur le BTS de Debian, et déjà, je vois que j'ai un premier bug sur le message d'erreur de mon code que je corrige ( envoie, merge, dans la journée ). À partir de la, j'arrive à piger que j'ai un 2eme bug.

    Le bug est que pour changer de profile apparmor, tu dois écrire dans /proc/self/attr ( http://wiki.apparmor.net/index.php/Kernel_interfaces ). Tu peux changer le profile du processus courant, ou du prochain processus exécuté. Le déclencheur du bug est que le service tor du projet tails est blindé, et notamment, l'accés à /proc est restreint pour tor via systemd. Et si tu fait disparaitre /proc avant de tenter de changer de profile, ça ne marche pas, ce qui est le cas dans mon code. D'abord, systemd restreint les namespaces, ensuite, il fait la demande de changement de profil pour le prochain processus ( exec_child dans src/core/execute.c ).

    Donc la solution est d'écrire dans /proc en demandant de changer le profil du prochain process , puis de faire des montages spéciaux avec les namespaces. Changer le processus courant bloque les changements avec les namespaces, et faire les changements avec les namespaces bloque le changement de contexte apparmor.

    Systemd est en en C, et ça marche parce que systemd ne fait pas de fork sauf pour lancer le service.

    En shell, ça ne peux pas marcher dans l'état, car tout est un fork.

    Si je commence par faire le echo kivabien dans /proc pour apparmor, ça va s'appliquer au prochain processus, qui va être le processus nsenter qui va changer les namespaces, et qui va sans doute être bloqué en fonction de la politique apparmor.

    Et si je rentre dans un namespace d'abord, puis que je fait l'écriture vers /proc, je peux pas car mon namespace peut supprimer /proc.

    Conclusion, ça ne marche pas, et c'est à mon sens impossible de faire marcher ça, sauf à changer apparmor pour avoir un autre mécanisme de communication qui marche sans /proc.

    Et même la, le mécanisme devra marcher dans un environnement très restrictif ( genre avec des syscalls désactivés, etc ).

    Le fait de dire "fait le changement pour le prochain executable" est très élégant car tu peux empiler les restrictions sans que ça se marche sur les pieds, ça ne s’appliquera qu'à ton fils, le processus à lancer.

    Mais en shell, tu n'as pas de séparation logique donc tu ne peux pas avoir ça.

    Alors mon exemple est ultra particulier. J'ai relu le reste du code et globalement, y a rien qui ne me saute aux yeux pour dire "y a pas que apparmor" ( enfin y a le choix du contexte selinux, mais le souci est une variation de apparmor, qui souffre du même bug comme je viens de le voir, et qui a été aussi écrit par moi (j'ai un peu honte)).

    Le coeur du souci est en effet d'appliquer des restrictions capables de se bloquer les unes et les autres, et les appliquer dans un ordre convenable. Sauf que comme il y a une boucle, le seul moyen est de briser la boucle en séparant l'application de la restriction de sa déclaration en appliquant à un événement dans le futur. Le fait d'appliquer "on exec" est exactement ça.

    Alors une solution serait de modifier le protocole de communication pour prendre un argument en plus, le chemin de l’exécutable à confiner en plus du profile/domaine/etc.
    Mais il y a des corners cases et des choses non intuitives ( genre si je veut restreindre python et qu'un des programmes pour restreindre est écrit aussi en python, ou justement, si je veux restreindre un script en python, il faut que je dise que c'est python que je veux restreindre car c'est ce que le kernel va voir, etc ).

    Donc parce que des APIs et le kernel est pas vraiment toujours shell friendly, un systéme d'init qui se base sur le shell autant que possible ne va pas avoir le même niveau de fonctionnalités.

    Bien sur, une solution alternative serait sans doute d'avoir juste un gros binaire comme start-stop-daemon qui prends des tas d'options, voir des variables d'environement. On en reviens du coup à la critique "je ne peux pas comprendre ce qui se passe dans le script", vu que ça devient juste "je déclare des vars et je lance un binaire magique qui fait tout". Je ne doute pas qu'on râle au manque d'esprit unix de la chose :)