« Suite à l'incident de la porte dérobée sshd/xz (CVE-2024-3094), une discussion importante sur les vulnérabilités liées à systemd a émergé.
Cette bibliothèque, essentielle pour intégrer les services avec systemd, présente des risques de sécurité dus à ses dépendances. Pour minimiser ces risques, il est proposé de réduire les dépendances de libsystemd à libc uniquement.
Lennart Poettering a souligné des changements récents pour atténuer ces inquiétudes.
Il est également question d'exposer les informations de chargement dynamique de manière transparente. Cette proposition encourage la collaboration des acteurs de l'écosystème Linux pour renforcer la sécurité du système. »
Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Si j'ai bien compris ce commentaire sur Github, systemd ne réduit pas ses dépendances, mais les charge dynamiquement avec dlopen au moment où elles sont nécessaires.
Donc, en pratique, les dépendances sont toujours là.
Cette bibliothèque, essentielle pour intégrer les services avec systemd
Comme soulevé par Renault dans ce commentaire, libsystemd n'est pas un pré-requis pour intégrer les services avec systemd. Dans le lien donné par Renault, Lennart Potting résume en une phrase ce qui est nécessaire:
It literally is just sending a text string "READY=1" in an AF_UNIX datagram to a socket whose path is provided to you in the $NOTIFY_SOCKET env var. Anyone with a moderate understanding of UNIX APIs should be able to hack that up in a a few lines of code. It's a protocol I can summarize and explain in one frickin' sentence.
Ce qui s'est traduit concrètement par ce patch pour OpenSSH par exemple (joins ci-dessous).
Le patch est long, car OpenSSH a décidé de faire une option de build pour ne pas l'intégrer à la construction. Si on enlève ce détail, la fonction C static void ssh_systemd_notify(const char *fmt, ...) n'est effectivement pas si horrible.
Le patch est long, car OpenSSH a décidé de faire une option de build
En voyant le patch en question, je trouve cette affirmation assez fausse. Le patch est long, car coder proprement une fonction d'envoi de signal prend plus que "quelques lignes de code".
Et c'est bien la raison pour laquelle le ticket GitHub demande, à l'origine, de découper la bibliothèque "libsystemd" pour fournir des éléments plus unitaires, n'ayant réellement aucune dépendance superflue. Demande qui a été refusée d'un revers de la main, disant en gros "le dlopen résoud le problème, et on n'ira pas plus loin"… Personnellement, ça me semble très léger, et dans le cas de xz je suis persuadé qu'une variante aurait pu quand même s'activer malgré ce dlopen.
Au final, on se retrouve donc avec une belle duplication de code. Je n'ai pas compris ce refus peu (pas ?) argumenté du découpage de libsystemd.
Franchement, le code de la fonction n'est pas long, c'est juste que le langage C force à être très explicite. En Java ou python, la même fonction serait beaucoup plus concise avec la même qualité de gestion d'erreur (prêt pour un TapTempo "systemd_notify" ?).
Comme ce code est court et standard, il peut très bien être dupliqué dans tous les projets: ça sera une perte de temps de faire une librairie qui ne contient que cette fonction.
En plus, les développeurs et mainteneurs critiquent justement l'écosystème JavaScript qui a tendance à créer un module pour 10 lignes de code…
Demander de refaire complètement l'architecture de la libsystemd juste pour ces quelques lignes de code me semble quand même très tiré par les cheveux.
Ça reste du code dupliqué et non trivial (on n'est pas sur 3-4 lignes, là).
Demander de refaire complètement l'architecture de la libsystemd
Euh, on parle de séparer un .so en deux, ou même de juste construire (et rendre dispo) un .a statique intermédiaire. Ça demande de sélectionner quel code va dans la lib de base, c'est tout.
Les dev systemd font des choses bien plus impactantes à chaque version; le dlopen par exemple n'est pas forcément plus simple à faire.
Une macro dans un .h permettrait aussi de résoudre le problème. Ce n'est pas non plus ce qu'a choisi systemd, qui préfère donner une implémentation de référence dans la doc. Ceci dit c'est peut-être quelque chose à proposer dans une MR.
Ça reste du code dupliqué et non trivial (on n'est pas sur 3-4 lignes, là).
Je ne vois pas ce qu'il y a d'horrible de dupliquer 50 lignes de code C dans tous les projets en C (pour les autres langages, le code sera plus concis).
Euh, on parle de séparer un .so en deux, ou même de juste construire (et rendre dispo) un .a statique intermédiaire. Ça demande de sélectionner quel code va dans la lib de base, c'est tout.
Le projet systemd dit clairement qu'ils ne vont pas s'amuser à faire une librairie ou un header exprès pour ça.
En acceptant ce fait, si la duplication est vraiment si terrifiante et abominable, il y aura peut être un groupe de développeur ou mainteneur qui va créer cette fameuse librairie ou ce header.
Si j'ai bien compris ce commentaire sur Github, systemd ne réduit pas ses dépendances, mais les charge dynamiquement avec dlopen au moment où elles sont nécessaires.
Mais dans le cas de sshd, ou il n'y a pas besoin d'autre chose que d'écrire sur un socket pour l'intégration avec systemd (chose qui pourrait être fait via une macro dans un .h), ça va réduire la surface d'attaque.
Si ensuite tu as une fonction qui demande à écrire ou à lire du xz, que ça vienne via systemd ou autrement, tu as besoin de la lib. Tu peux te poser la question de savoir si l'écriture/lecture de xz est requise, mais ç'est indépendant de systemd.
Le patch est long, car OpenSSH a décidé de faire une option de build pour ne pas l'intégrer à la construction. Si on enlève ce détail, la fonction C static void ssh_systemd_notify(const char *fmt, …) n'est effectivement pas si horrible.
C'est pas horrible, mais j'avoue avoir tendance a tiquer quand je vois des fonctions qui se reposent sur va_args.
Alors, j'ai bien vu l'usage ici, c'est pour refiler le boulot de concaténation/formatage à la libc, mais je suis assez intrigué par la nécessité réelle de ceci, pas tout a fait "just send NOTIFY=1 to an AF_UNIX socket" (ou un truc du genre):
Posté par freem .
Évalué à 5.
Dernière modification le 07 avril 2024 à 07:14.
On peut quand même, je pense, regretter que systemd utilise un socket AF_UNIX pour ça, et pas juste un pipe.
Un simple pipe aurait éviter de s'emmerder avec sockaddr_un & co, ça aurait pu éviter ce bloc:
memset(&addr,0,sizeof(addr));addr.sun_family=AF_UNIX;if(strlcpy(addr.sun_path,path,sizeof(addr.sun_path))>=sizeof(addr.sun_path)){error_f("socket path \"%s\" too long",path);gotoout;}/* Support for abstract socket */if(addr.sun_path[0]=='@')addr.sun_path[0]=0;if((fd=socket(PF_UNIX,SOCK_DGRAM,0))==-1){error_f("socket \"%s\": %s",path,strerror(errno));gotoout;}if(connect(fd,&addr,sizeof(addr))!=0){error_f("socket \"%s\" connect: %s",path,strerror(errno));gotoout;}
qui représente une portion non-négligeable du patch d'OpenSSH. J'imagine que le socket est réutilisé pour autre chose par libsystemd0, mais tout de même.
Il y a peut-être (probablement!) d'autres aspects auxquels je ne pense pas, ceci dit. Ca fait longtemps que j'ai pas pratiqué.
Posté par freem .
Évalué à 7.
Dernière modification le 07 avril 2024 à 07:19.
Vous ne passez pas! Bon, dommage alors.
Ah, je crois que c'est parce qu'un pipe ne permets pas de savoir qui écrit dedans, alors qu'un socket af_unix permets de récupérer pas mal d'info sur le processus qui émets un message, notamment son PID, si ma mémoire me trompe pas. Et les pipes n'ont pas ça.
On peut aussi faire transiter des descripteurs de fichiers via un socket, ce qui semble utilisé par certaines autres fonctionnalités du protocole sd-notify, qui, au final, ne me semble pas si "simple" que prétendu par LP (vu que plus que le strict minimum).
Je pense qu'un pipe, ça implique aussi d'avoir quelque chose pour écrire le fichier, donc ne serait utilisable qu'à partir d'un certain moment du boot, et c'était peut être une contrainte à éviter ?
Posté par freem .
Évalué à 3.
Dernière modification le 07 avril 2024 à 15:47.
Pareil pour un socket si ma mémoire est bonne. Les pipes ne sont pas forcément nommés, mais un pipe non nommé serait plus intrusif.
D'un autre côté, je ne vois pas comment exécuter un programme sur un FS sans supporter de FS au préalable, et les gens de systemd ont justement poussé, de mémoire, pour bouger tout /bin et /sbin vers /usr, qui requiert, justement, que /usr soit monté sur /. Si tu peux exécuter un daemon géré par systemd, c'est que systemd a monté les partoches avant. Y compris /dev, qui inclue /dev/shm, qui est un ramdisk.
[edit]
D'ailleurs, le nom attendu dans la variable d'environnement est un fichier, donc oui, clairement, ce point ne change rien comparé à un af_unix tel que fait actuellement. CE point, j'insiste.
D'un autre côté, je ne vois pas comment exécuter un programme sur un FS sans supporter de FS au préalable,
Tu peux exécuter un programme sur un FS en lecture seule, alors que je suis pas sur que tu puisses créer un pipe/socket nommé sans un endroit ou écrire (donc avant le montage de /tmp ou /run).
Ceci dit, c'est sans doute improbable que ça soit ça.
Pareil pour un socket si ma mémoire est bonne. Les pipes ne sont pas forcément nommés, mais un pipe non nommé serait plus intrusif.
Dans mon souvenir (mais rien ne semble aller dans mon sens sur stackoverflow ou la doc), plusieurs clients qui écrivent sur un pipe peuvent interférer les uns avec les autres (vu qu'il n'y a qu'un seul FD pour lire pour tous. Donc ça voudrait dire ouvrir 1 pipe par process pour être sur de ne pas avoir de race condition, et ça me semble sous optimal pour la scalabilité.
Alors qu'avec une socket en mode datagram, tu n'as pas le souci vu que le kernel s'occupe de séparer les messages par client et tu as le pid en plus (et donc, tu peux chercher le pid dans le cgroup pour savoir quel service est ready).
Après réflexion, c'est sûrement la raison, plus que mon histoire de montage en RO sans /tmp/ ou /run/.
Mais ceci dit, tu peux aussi passer par une socket abstraite (sous Linux) qui n'est pas sur le disque, et donc la passer via une variable d’environnement, donc même si c'est pas la raison, ç'est peut être un bonus.
Après réflexion, c'est sûrement la raison, plus que mon histoire de montage en RO sans /tmp/ ou /run/.
Oui, ça et la capacité a faire transiter des descripteurs de fichiers. Pas besoin des cgroups pour savoir qui envoie un message par contre, ça fait partie des «ancillary data» que l'on peut récupérer.
Mais ceci dit, tu peux aussi passer par une socket abstraite (sous Linux) qui n'est pas sur le disque
Je ne suis pas sûr de ce que tu appelles une socket abstraite, je n'ai pas souvenir avoir vu cette notion avant? Et pour rappel, même si je me doute que tu le sais, avoir un système de fichiers ne nécessite pas d'avoir un périphérique de stockage local, typiquement NFS et les ramdisk sont très utiles pour ça (et l'une des raisons pour lesquelles je mets mes fichiers de runit dans un ramdisk, c'est justement pour permettre de booter avec root en ro. Pas utile dans la plupart des cas, mais mes scripts sont déjà prêts, alors tant qu'a faire, autant réutiliser :D).
Je suis quand même peu convaincu par l'idée que créer un pipe par daemon serait lourd. Le nombre de daemon a créer est connu dès le départ, après tout.
Je pense vraiment que c'est lié au transfert de FDs, vu que je ne vois pas d'autres moyens d'implémenter ce truc:
FDSTORE=1
Store file descriptors in the service manager. File
descriptors sent this way will be held for the service by the
service manager and will later be handed back using the usual
file descriptor passing logic at the next start or restart of
the service, see sd_listen_fds(3).
Je ne suis pas sûr de ce que tu appelles une socket abstraite, je n'ai pas souvenir avoir vu cette notion avant?
C'est ma traduction des termes utilisés dans man unix(7), mais je suppose que c'est moins clair si je précise pas "une socket unix abstraite", par opposition aux sockets qui peuvent être réseau, etc. De ce que je comprends, un socket unix abstrait, c'est juste un socket avec un nom, mais qui n'est pas sur le FS.
Le seul exemple que j'ai trouvé, c'est dans calibre (je crois). Avec lsof, ç'est comme une socket unix, mais le nom commence par @.
C'est par opposition aux "pathname" socket, qui sauf erreur de ma part, sont visibles sur le FS. C'est une fonction spécifique à Linux, donc c'est peut être peu utilisé.
Et pour rappel, même si je me doute que tu le sais, avoir un système de fichiers ne nécessite pas d'avoir un périphérique de stockage local, typiquement NFS et les ramdisk sont très utiles pour ça
Bien sur, mais ça arrive aussi après le montage du réseau, et tu peux imaginer que le montage passe par un ou plusieurs demons (genre, un VPN, dhcp, etc, tout les trucs pour se faire des noeuds au cerveau), demons qui ont besoin de de faire un notify, donc d'avoir un socket/pipe/etc.
Je suis quand même peu convaincu par l'idée que créer un pipe par daemon serait lourd
Pour des opérations normales, ça passerais. Par contre, si tu veux lancer des milliers de services (genre, des VPS comme le faisait Pantheon, un des sponsors de systemd à l'époque), ça peut rajouter de la charge inutilement (ne serait que pour faire une boucle sur tout les FD avec select par exemple, même si je suppose que le kernel a peut être des optims à ce niveau).
Pour des opérations normales, ça passerais. Par contre, si tu veux lancer des milliers de services (genre, des VPS comme le faisait Pantheon, un des sponsors de systemd à l'époque), ça peut rajouter de la charge inutilement (ne serait que pour faire une boucle sur tout les FD avec select par exemple, même si je suppose que le kernel a peut être des optims à ce niveau).
Certes.
Petit détail ceci dit: select(2) est obsolète, il vaut mieux utiliser poll(2) pour du portable, et pour du non portable, faut voir avec l'OS.
Notamment:
WARNING: select() can monitor only file descriptors numbers that are less than FD_SETSIZE (1024)—an unreasonably low limit for many modern applications—and this limitation will not change. All modern applications should instead use poll(2) or epoll(7), which do not suffer this limitation.
Accessoirement, le truc vraiment bien avec poll(2) c'est qu'il n'y a pas besoin de recréer le tableau a chaque itération, c'est bien pratique. Et puis, pas besoin de macros pour s'en servir, l'interface juste "coule de source".
C'était le moment culturel :)
Dans le cas de systemd, compte tenu de leurs positions, j'ose espérer qu'ils utilisent epoll(2) et non select/poll, justement, parce qu'en terme de perfs c'est mieux, qu'ils disent.
En vrai, je ne suis pas sûr qu'une boucle sur quelques milliers de pollfd soit lente, d'autant plus que si c'set bien fait, il sera rarement utile d'itérer sur la totalité, sauf en cas de gros traffic ou si ceux qui ont un événement sont à la fin. Ok, ça fait un très, très gros "sauf".
Je pense qu'en effet sur un cas de serveur avec plusieurs milliers de daemons/services, systemd sera l'un des meilleurs en terme de performance, ne serait-ce que parce que pas besoin d'allouer 4Kio de RAM pour chaque process comme le ferait par exemple runit (dans le cas d'un linkage statique, hein, ou avec muslC. Parce que link dynamique avec glibc6, c'est direct 750Kio de bouffés par process, non je ne sais pas pourquoi).
Je sais pas moi, on pourrait imaginer des processus indépendant en charge d'une et une seule tache, avec le minimum d'interactions avec les autres, uniquement quand c'est nécessaire. Ça serait révolutionnaire non ?
Disons qu'au moins, quand libsystemd ne chargera ses dépendances que si elle en a besoin, les systèmes sans systemd serons moins vulnérables aux failles introduites dans la chaîne d'approvisionnement de systemd.
Je ne sais pas si l'attaque qui nous occupe aie pu introduire une faille sur ces systèmes, mais une prochaine aurait très bien être "systemd-agnostic", et du coup il se peut que ça aide.
A noter, je n'ai pas été lire le code de libsystemd0, je ne sais donc vraiment pas.
# Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Eric . Évalué à 6.
« Suite à l'incident de la porte dérobée sshd/xz (CVE-2024-3094), une discussion importante sur les vulnérabilités liées à systemd a émergé.
Cette bibliothèque, essentielle pour intégrer les services avec systemd, présente des risques de sécurité dus à ses dépendances. Pour minimiser ces risques, il est proposé de réduire les dépendances de libsystemd à libc uniquement.
Lennart Poettering a souligné des changements récents pour atténuer ces inquiétudes.
Il est également question d'exposer les informations de chargement dynamique de manière transparente. Cette proposition encourage la collaboration des acteurs de l'écosystème Linux pour renforcer la sécurité du système. »
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Adrien Dorsaz (site web personnel, Mastodon) . Évalué à 9.
Si j'ai bien compris ce commentaire sur Github, systemd ne réduit pas ses dépendances, mais les charge dynamiquement avec
dlopen
au moment où elles sont nécessaires.Donc, en pratique, les dépendances sont toujours là.
Comme soulevé par Renault dans ce commentaire,
libsystemd
n'est pas un pré-requis pour intégrer les services avec systemd. Dans le lien donné par Renault, Lennart Potting résume en une phrase ce qui est nécessaire:Ce qui s'est traduit concrètement par ce patch pour OpenSSH par exemple (joins ci-dessous).
Le patch est long, car OpenSSH a décidé de faire une option de build pour ne pas l'intégrer à la construction. Si on enlève ce détail, la fonction C
static void ssh_systemd_notify(const char *fmt, ...)
n'est effectivement pas si horrible.[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Adrien Dorsaz (site web personnel, Mastodon) . Évalué à 3.
Oups, désolé pour le nommde famille de Lennart, c'est Poettering, pas Potting.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Christophe . Évalué à 4.
En voyant le patch en question, je trouve cette affirmation assez fausse. Le patch est long, car coder proprement une fonction d'envoi de signal prend plus que "quelques lignes de code".
Et c'est bien la raison pour laquelle le ticket GitHub demande, à l'origine, de découper la bibliothèque "libsystemd" pour fournir des éléments plus unitaires, n'ayant réellement aucune dépendance superflue. Demande qui a été refusée d'un revers de la main, disant en gros "le dlopen résoud le problème, et on n'ira pas plus loin"… Personnellement, ça me semble très léger, et dans le cas de xz je suis persuadé qu'une variante aurait pu quand même s'activer malgré ce dlopen.
Au final, on se retrouve donc avec une belle duplication de code. Je n'ai pas compris ce refus peu (pas ?) argumenté du découpage de libsystemd.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Adrien Dorsaz (site web personnel, Mastodon) . Évalué à 4.
Franchement, le code de la fonction n'est pas long, c'est juste que le langage C force à être très explicite. En Java ou python, la même fonction serait beaucoup plus concise avec la même qualité de gestion d'erreur (prêt pour un TapTempo "systemd_notify" ?).
Comme ce code est court et standard, il peut très bien être dupliqué dans tous les projets: ça sera une perte de temps de faire une librairie qui ne contient que cette fonction.
En plus, les développeurs et mainteneurs critiquent justement l'écosystème JavaScript qui a tendance à créer un module pour 10 lignes de code…
Demander de refaire complètement l'architecture de la libsystemd juste pour ces quelques lignes de code me semble quand même très tiré par les cheveux.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 5.
Une solution serait de faire une macro C qui est dans un .h.
Comme ça, pas de lien avec la lib de systemd au runtime, pas de souci de logistique sur 50 libs, pas de changement énorme coté systemd.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par jmiven . Évalué à 4.
À défaut d'être forcément une bonne idée, un paquet "leftsystempad" aurait de la gueule :)
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Christophe . Évalué à 4.
Ça reste du code dupliqué et non trivial (on n'est pas sur 3-4 lignes, là).
Euh, on parle de séparer un .so en deux, ou même de juste construire (et rendre dispo) un .a statique intermédiaire. Ça demande de sélectionner quel code va dans la lib de base, c'est tout.
Les dev systemd font des choses bien plus impactantes à chaque version; le dlopen par exemple n'est pas forcément plus simple à faire.
Pour rappel, un commentaire sur GitHub avance une liste des logiciels où cela permettrait de réduire les dépendances. 150 duplications de code, tout va bien…
Une macro dans un .h permettrait aussi de résoudre le problème. Ce n'est pas non plus ce qu'a choisi systemd, qui préfère donner une implémentation de référence dans la doc. Ceci dit c'est peut-être quelque chose à proposer dans une MR.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Adrien Dorsaz (site web personnel, Mastodon) . Évalué à 3.
Je ne vois pas ce qu'il y a d'horrible de dupliquer 50 lignes de code C dans tous les projets en C (pour les autres langages, le code sera plus concis).
Le projet systemd dit clairement qu'ils ne vont pas s'amuser à faire une librairie ou un header exprès pour ça.
En acceptant ce fait, si la duplication est vraiment si terrifiante et abominable, il y aura peut être un groupe de développeur ou mainteneur qui va créer cette fameuse librairie ou ce header.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 6.
Mais sur les 150, combien n'utilisent que sd_notify et pas le reste (comme les api pour journald etc) ?
Par exemple, je suis sur que syslog-ng utilise des fonctions lié à journald, ne serait que pour lire le dit journal.
De même, rust-libsystemd ou python-systemd doivent exposer libsystemd pour les programmes qui les utilisent, donc devrait être retiré de la liste.
Même si je pense pas que ça va changer grand chose (car même 50 duplication, c'est pas cool), je pense qu'il faut quand même relativiser cette liste.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 5.
Mais dans le cas de sshd, ou il n'y a pas besoin d'autre chose que d'écrire sur un socket pour l'intégration avec systemd (chose qui pourrait être fait via une macro dans un .h), ça va réduire la surface d'attaque.
Si ensuite tu as une fonction qui demande à écrire ou à lire du xz, que ça vienne via systemd ou autrement, tu as besoin de la lib. Tu peux te poser la question de savoir si l'écriture/lecture de xz est requise, mais ç'est indépendant de systemd.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 4.
C'est pas horrible, mais j'avoue avoir tendance a tiquer quand je vois des fonctions qui se reposent sur va_args.
Alors, j'ai bien vu l'usage ici, c'est pour refiler le boulot de concaténation/formatage à la libc, mais je suis assez intrigué par la nécessité réelle de ceci, pas tout a fait "just send NOTIFY=1 to an AF_UNIX socket" (ou un truc du genre):
Il s'agit peut-être d'une extension d'OpenSSH ceci dit.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 5. Dernière modification le 07 avril 2024 à 07:14.
On peut quand même, je pense, regretter que systemd utilise un socket AF_UNIX pour ça, et pas juste un pipe.
Un simple pipe aurait éviter de s'emmerder avec sockaddr_un & co, ça aurait pu éviter ce bloc:
qui représente une portion non-négligeable du patch d'OpenSSH. J'imagine que le socket est réutilisé pour autre chose par libsystemd0, mais tout de même.
Il y a peut-être (probablement!) d'autres aspects auxquels je ne pense pas, ceci dit. Ca fait longtemps que j'ai pas pratiqué.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 7. Dernière modification le 07 avril 2024 à 07:19.
Vous ne passez pas! Bon, dommage alors.
Ah, je crois que c'est parce qu'un pipe ne permets pas de savoir qui écrit dedans, alors qu'un socket af_unix permets de récupérer pas mal d'info sur le processus qui émets un message, notamment son PID, si ma mémoire me trompe pas. Et les pipes n'ont pas ça.
On peut aussi faire transiter des descripteurs de fichiers via un socket, ce qui semble utilisé par certaines autres fonctionnalités du protocole sd-notify, qui, au final, ne me semble pas si "simple" que prétendu par LP (vu que plus que le strict minimum).
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 5.
Je pense qu'un pipe, ça implique aussi d'avoir quelque chose pour écrire le fichier, donc ne serait utilisable qu'à partir d'un certain moment du boot, et c'était peut être une contrainte à éviter ?
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 3. Dernière modification le 07 avril 2024 à 15:47.
Pareil pour un socket si ma mémoire est bonne. Les pipes ne sont pas forcément nommés, mais un pipe non nommé serait plus intrusif.
D'un autre côté, je ne vois pas comment exécuter un programme sur un FS sans supporter de FS au préalable, et les gens de systemd ont justement poussé, de mémoire, pour bouger tout /bin et /sbin vers /usr, qui requiert, justement, que /usr soit monté sur /. Si tu peux exécuter un daemon géré par systemd, c'est que systemd a monté les partoches avant. Y compris /dev, qui inclue /dev/shm, qui est un ramdisk.
[edit]
D'ailleurs, le nom attendu dans la variable d'environnement est un fichier, donc oui, clairement, ce point ne change rien comparé à un af_unix tel que fait actuellement. CE point, j'insiste.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 4.
Tu peux exécuter un programme sur un FS en lecture seule, alors que je suis pas sur que tu puisses créer un pipe/socket nommé sans un endroit ou écrire (donc avant le montage de /tmp ou /run).
Ceci dit, c'est sans doute improbable que ça soit ça.
Dans mon souvenir (mais rien ne semble aller dans mon sens sur stackoverflow ou la doc), plusieurs clients qui écrivent sur un pipe peuvent interférer les uns avec les autres (vu qu'il n'y a qu'un seul FD pour lire pour tous. Donc ça voudrait dire ouvrir 1 pipe par process pour être sur de ne pas avoir de race condition, et ça me semble sous optimal pour la scalabilité.
Alors qu'avec une socket en mode datagram, tu n'as pas le souci vu que le kernel s'occupe de séparer les messages par client et tu as le pid en plus (et donc, tu peux chercher le pid dans le cgroup pour savoir quel service est ready).
Après réflexion, c'est sûrement la raison, plus que mon histoire de montage en RO sans /tmp/ ou /run/.
Mais ceci dit, tu peux aussi passer par une socket abstraite (sous Linux) qui n'est pas sur le disque, et donc la passer via une variable d’environnement, donc même si c'est pas la raison, ç'est peut être un bonus.
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 2.
Oui, ça et la capacité a faire transiter des descripteurs de fichiers. Pas besoin des cgroups pour savoir qui envoie un message par contre, ça fait partie des «ancillary data» que l'on peut récupérer.
Je ne suis pas sûr de ce que tu appelles une socket abstraite, je n'ai pas souvenir avoir vu cette notion avant? Et pour rappel, même si je me doute que tu le sais, avoir un système de fichiers ne nécessite pas d'avoir un périphérique de stockage local, typiquement NFS et les ramdisk sont très utiles pour ça (et l'une des raisons pour lesquelles je mets mes fichiers de runit dans un ramdisk, c'est justement pour permettre de booter avec root en ro. Pas utile dans la plupart des cas, mais mes scripts sont déjà prêts, alors tant qu'a faire, autant réutiliser :D).
Je suis quand même peu convaincu par l'idée que créer un pipe par daemon serait lourd. Le nombre de daemon a créer est connu dès le départ, après tout.
Je pense vraiment que c'est lié au transfert de FDs, vu que je ne vois pas d'autres moyens d'implémenter ce truc:
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par Misc (site web personnel) . Évalué à 3.
C'est ma traduction des termes utilisés dans man unix(7), mais je suppose que c'est moins clair si je précise pas "une socket unix abstraite", par opposition aux sockets qui peuvent être réseau, etc. De ce que je comprends, un socket unix abstrait, c'est juste un socket avec un nom, mais qui n'est pas sur le FS.
Le seul exemple que j'ai trouvé, c'est dans calibre (je crois). Avec lsof, ç'est comme une socket unix, mais le nom commence par @.
C'est par opposition aux "pathname" socket, qui sauf erreur de ma part, sont visibles sur le FS. C'est une fonction spécifique à Linux, donc c'est peut être peu utilisé.
Bien sur, mais ça arrive aussi après le montage du réseau, et tu peux imaginer que le montage passe par un ou plusieurs demons (genre, un VPN, dhcp, etc, tout les trucs pour se faire des noeuds au cerveau), demons qui ont besoin de de faire un notify, donc d'avoir un socket/pipe/etc.
Pour des opérations normales, ça passerais. Par contre, si tu veux lancer des milliers de services (genre, des VPS comme le faisait Pantheon, un des sponsors de systemd à l'époque), ça peut rajouter de la charge inutilement (ne serait que pour faire une boucle sur tout les FD avec select par exemple, même si je suppose que le kernel a peut être des optims à ce niveau).
[^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.
Posté par freem . Évalué à 2.
Certes.
Petit détail ceci dit:
select(2)
est obsolète, il vaut mieux utiliserpoll(2)
pour du portable, et pour du non portable, faut voir avec l'OS.Notamment:
Accessoirement, le truc vraiment bien avec
poll(2)
c'est qu'il n'y a pas besoin de recréer le tableau a chaque itération, c'est bien pratique. Et puis, pas besoin de macros pour s'en servir, l'interface juste "coule de source".C'était le moment culturel :)
Dans le cas de systemd, compte tenu de leurs positions, j'ose espérer qu'ils utilisent
epoll(2)
et non select/poll, justement, parce qu'en terme de perfs c'est mieux, qu'ils disent.En vrai, je ne suis pas sûr qu'une boucle sur quelques milliers de pollfd soit lente, d'autant plus que si c'set bien fait, il sera rarement utile d'itérer sur la totalité, sauf en cas de gros traffic ou si ceux qui ont un événement sont à la fin. Ok, ça fait un très, très gros "sauf".
Je pense qu'en effet sur un cas de serveur avec plusieurs milliers de daemons/services, systemd sera l'un des meilleurs en terme de performance, ne serait-ce que parce que pas besoin d'allouer 4Kio de RAM pour chaque process comme le ferait par exemple runit (dans le cas d'un linkage statique, hein, ou avec muslC. Parce que link dynamique avec glibc6, c'est direct 750Kio de bouffés par process, non je ne sais pas pourquoi).
# Et si on réduisait la dépendance à systemd ?
Posté par AncalagonTotof . Évalué à 1.
Je sais pas moi, on pourrait imaginer des processus indépendant en charge d'une et une seule tache, avec le minimum d'interactions avec les autres, uniquement quand c'est nécessaire. Ça serait révolutionnaire non ?
[^] # Re: Et si on réduisait la dépendance à systemd ?
Posté par freem . Évalué à 3.
Disons qu'au moins, quand libsystemd ne chargera ses dépendances que si elle en a besoin, les systèmes sans systemd serons moins vulnérables aux failles introduites dans la chaîne d'approvisionnement de systemd.
Je ne sais pas si l'attaque qui nous occupe aie pu introduire une faille sur ces systèmes, mais une prochaine aurait très bien être "systemd-agnostic", et du coup il se peut que ça aide.
A noter, je n'ai pas été lire le code de libsystemd0, je ne sais donc vraiment pas.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.