Contrôle d’accès

Comme mentionné précédemment, perf permet d’obtenir des informations extrêmement détaillés sur l’activité système, ce qui représente un risque de sécurité sur une machine avec plusieurs utilisateurs. Pour éviter tout accident, la plupart des distributions Linux limitent donc l’utilisation d’au moins une partie des fonctionnalités de perf au superutilisateur root par défaut.

Voici une liste (probablement non exhaustive) de verrous de sécurité qui sont installés par défaut sur les distributions Linux courantes, et de procédures pour les désactiver si nécessaire.

perf_event_paranoid

L’utilisation de base de perf est contrôlée par le réglage perf_event_paranoid du noyau. Ce réglage peut être modifié temporairement en utilisant la commande sysctl kernel.perf_event_paranoid=x, ou de façon permanente en écrivant kernel.perf_event_paranoid=x dans un fichier du répertoire /etc/sysctl.d.

Les valeurs possibles de ce réglage sont :

  • 3 : Les utilisateurs non privilégiés ne peuvent pas utiliser perf du tout (réglage par défaut sous Debian, Ubuntu et Android).
  • 2 : Les utilisateurs non privilégiés ne peuvent suivre que des processus individuels, et seulement durant l’exécution en mode utilisateur (pas de suivi de l’activité noyau déclenchée par le processus).
  • 1 : L’utilisation de perf est toujours restreinte au suivi de processus individuels, mais le suivi de l’activité noyau directement associée au processus (appels système synchrones) est possible.
  • 0 : Certaines formes de suivi de l’activité du système entier deviennent possible (ex : suivi des compteurs de performance CPU), mais le suivi à grain fin de l’activité système via les mécanismes de tracing du noyau demeure inaccessible aux utilisateurs non privilégiés.
  • -1 : Aucune restriction n’est appliquée au niveau de l’outil perf (même si des contrôles d’accès peuvent encore s’appliquer en aval de l’outil, on va le voir plus loin).

Les noyaux récents devraient fournir un contrôle d’accès à grain plus fin basé sur les capabilities, permettant par exemple de ne donner accès à perf qu’à un certain groupe d’utilisateurs. Mais mon dernier test sous Linux 5.14 n’était pas concluant, il fallait encore avoir perf_event_paranoid=-1 pour un accès complet à perf.

kptr_restrict

Pour interpréter un profil l’activité CPU du noyau, il est nécessaire de savoir à quelle partie du noyau on a affaire. perf mesure la position du pointeur d’instruction du noyau, mais pour traduire cette information bas niveau en information symbolique de haut niveau (nom de fonction), il a besoin de connaître la position en mémoire des différents symboles du noyau.

Cette information est malheureusement également très utile pour mener une attaque contre le noyau Linux, et elle n’est donc accessible qu’à root par défaut. Pour la rendre accessible à tous les utilisateurs, il faut mettre à 0 le réglage kptr_restrict du noyau.

Là encore, on peut le faire de façon temporaire avec la commande sysctl kernel.kptr_restrict=0, ou de façon permanente en écrivant kernel.kptr_restrict=0 dans un fichier du répertoire /etc/sysctl.d.

Et là encore, il devrait y avoir moyen de gérer ce contrôle d’accès avec la capability CAP_SYSLOG, mais cela ne semble pas fonctionner sous Linux 5.14.

Tracing

Le suivi à grain fin de l’activité noyau (tracing) est une fonctionalité du noyau Linux qui est particulièrement puissante pour l’analyse de performances, mais aussi particulièrement dangereuse sur un système multi-utilisateurs :

  • Elle donne trivialement accès à l’ensemble des données passées en paramètres ou reçues en résultat d’appels système par les applications, ce qui peut inclure toutes sortes d’informations secrètes : mots de passe, clés SSH…
  • Il est relativement facile de charger fortement le système en l’utilisant, soit en créant une récursion infinie (suivi d’un évènement qui survient lorsqu’on suit un événement), soit en suivant de façon exhaustive un évènement extrêmement fréquent (ex : basculement entre deux tâches).

Cette fonctionnalité dispose donc de ses propres mécanismes de sécurité en sus de la protection perf_event_paranoid susmentionnée. Si vous souhaitez la rendre accessible à un groupe d’utilisateurs, disons le groupe perf, vous devez…

  • Remonter les pseudo-systèmes de fichier /sys/kernel/debug/tracing et /sys/kernel/tracing avec des permissions 770 (u+rwx g+rwx).
  • Remonter le pseudo-système de fichier /sys/kernel/debug avec les permissions 750 (u+rwx g+rx) pour permettre la navigation jusqu’à /sys/kernel/debug/tracing.
  • Transférer la propriété de /sys/kernel/debug et /sys/kernel/tracing au groupe perf.
  • Ajuster les permissions des fichiers de /sys/kernel/debug/tracing pour faire en sorte que tout ce qui est inscriptible par l’utilisateur l’est par le groupe.

Voici un service systemd permettant d’effectuer ces modifications à chaque démarrage :

[Unit]
Description=Let perf group use ftrace, kprobes and uprobes
RequiresMountsFor=/sys/kernel/tracing
RequiresMountsFor=/sys/kernel/debug/tracing
Before=multi-user.target

[Install]
WantedBy=multi-user.target

[Service]
Type=oneshot
RemainAfterExit=yes
Restart=no
ExecStart=bash -c 'mount -o remount,mode=770 /sys/kernel/tracing && mount -o remount,mode=750 /sys/kernel/debug && mount -o remount,mode=770 /sys/kernel/debug/tracing && chown -R root:perf /sys/kernel/tracing /sys/kernel/debug/tracing && find /sys/kernel/debug/tracing/ -perm -u=w -exec chmod g+w \'{}\' \\+'
ExecStop=bash -c 'mount -o remount,mode=700 /sys/kernel/tracing && mount -o remount,mode=700 /sys/kernel/debug/tracing && mount -o remount,mode=700 /sys/kernel/debug && chown -R root:root /sys/kernel/tracing /sys/kernel/debug'

Si vous utilisez perf probe, sachez que cette commande peut remettre certains des fichiers virtuels sous le contrôle de root:root et que vous serez amené à refaire des chown pour rétablir les permissions voulues, comme dans les exemples “administrateur” de la section perf probe de ce TP.