Qu'est-ce qui continue à drainer l'entropie?

21

Si je le fais, watch cat /proc/sys/kernel/random/entropy_availje vois que l'entropie de mes systèmes augmente lentement au fil du temps, jusqu'à ce qu'elle atteigne la plage 180-190, point auquel elle descend à environ 120-130. Les baisses d'entropie semblent se produire toutes les vingt secondes environ. J'observe cela même quand lsofdit qu'aucun processus n'a /dev/randomou /dev/urandomouvert. Qu'est-ce qui vide l'entropie? Le noyau a-t-il également besoin d'entropie, ou peut-il retraiter le plus grand pool en un pool plus petit et de meilleure qualité?

Il s'agit d'une machine à nu, sans connexion SSL / SSH / WPA.

wingedsubmariner
la source
Bonne question, et bien que je ne puisse pas vous donner de réponse spécifique, il est logique pour moi que le "pool d'entropie" ne soit pas simplement quelque chose qui devrait augmenter lorsqu'il n'est pas utilisé. /dev/randomest, après tout, quelque chose qui est utilisé à des fins cryptographiques sécurisées, et la mise en œuvre ne peut pas se permettre d'être naïve. Une explication pourrait être suggérée dans le dernier point ici: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (commençant par "Maintenir un chiffrement de flux avec une clé et un vecteur d'initialisation ...") -> le pool est remplacé chaque fois que cela est suffisant les données se sont accumulées.
goldilocks
Notez que dans tous les cas, le calcul d'entropie de Linux /dev/randomest à peu près faux - une fois que le pool d'entropie a été plein une fois, il /dev/urandomest tout aussi bon que /dev/random.
Gilles 'SO- arrête d'être méchant'
1
@techraf Wow, cette réponse est devenue très rapide. Je ne m'attendais pas à obtenir une réponse 2,5 ans plus tard.
wingedsubmariner

Réponses:

20

L'entropie n'est pas seulement perdue via /dev/{,u}random, le noyau en prend également. Par exemple, les nouveaux processus ont des adresses randomisées (ASLR) et les paquets réseau ont besoin de numéros de séquence aléatoires. Même le module du système de fichiers peut supprimer une certaine entropie. Voir les commentaires dans drivers / char / random.c . Notez également que cela entropy_availfait référence au pool d'entrée , pas aux pools de sortie (essentiellement le non-blocage /dev/urandomet le blocage /dev/random).

Si vous devez surveiller le pool d'entropie, ne l'utilisez pas watch cat, cela consommera l'entropie à chaque invocation de cat. Dans le passé, je voulais également regarder ce pool car GPG était très lent à générer des clés, j'ai donc écrit un programme C dans le seul but de regarder le pool d'entropie: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Notez qu'il peut y avoir des processus d'arrière-plan qui consomment également l'entropie. En utilisant des points de trace sur un noyau approprié, vous pouvez voir les processus qui modifient le pool d'entropie. Exemple d'utilisation qui enregistre tous les points de trace liés au sous-système aléatoire, y compris la chaîne d'appel ( -g) sur tous les CPU ( -a) commençant à mesurer après 1 seconde pour ignorer son propre processus ( -D 1000) et y compris les horodatages ( -T):

sudo perf record -e random:\* -g -a -D 1000 -T sleep 60

Lisez-le avec l'une de ces commandes (changez de propriétaire perf.datasi nécessaire):

perf report  # opens an interactive overview
perf script  # outputs events after each other with traces

La perf scriptsortie donne un aperçu intéressant et montre quand environ 8 octets (64 bits) d'entropie sont périodiquement drainés sur ma machine:

kworker / 0: 2 193 [000] 3292.235908: aléatoire: extract_entropy: ffffffff8173e956 pool: nbytes 8 entropy_count 921 appelant _xfer_secondary_pool
                  5eb857 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ebae6 push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293ce8 worker_thread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

kworker / 0: 2 193 [000] 3292.235911: aléatoire: debit_entropy: ffffffff8173e956: debit_bits 64
                  5eb3e8 account.part.12 (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb770 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ebae6 push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293ce8 worker_thread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

...

swapper 0 [002] 3292.507720: random: credit_entropy_bits: ffffffff8173e956 pool: bits 2 entropy_count 859 entropy_total 2 appelant add_interrupt_randomness
                  5eaab6 credit_entropy_bits (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ec644 add_interrupt_randomness (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d5729 handle_irq_event_percpu (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d58b9 handle_irq_event (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d8d1b handle_edge_irq (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  230e6a handle_irq (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c9abb do_IRQ (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7bc2 ret_from_intr (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  6756c7 cpuidle_enter (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2bd9fa call_cpuidle (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2bde18 cpu_startup_entry (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2510e5 start_secondary (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

Apparemment, cela se produit pour éviter le gaspillage d'entropie en transférant l'entropie du pool d'entrée aux pools de sortie:

/*
 * Credit (or debit) the entropy store with n bits of entropy.
 * Use credit_entropy_bits_safe() if the value comes from userspace
 * or otherwise should be checked for extreme values.
 */
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
    ...
        /* If the input pool is getting full, send some
         * entropy to the two output pools, flipping back and
         * forth between them, until the output pools are 75%
         * full.
         */

         ...
            schedule_work(&last->push_work);
}

/*
 * Used as a workqueue function so that when the input pool is getting
 * full, we can "spill over" some entropy to the output pools.  That
 * way the output pools can store some of the excess entropy instead
 * of letting it go to waste.
 */
static void push_to_pool(struct work_struct *work)
{
    ...
}
Lekensteyn
la source
2
+1 pour avoir souligné que même des opérations apparemment "innocentes" telles que le démarrage d'un programme peuvent drainer une petite quantité d'entropie.
un CVn
Cette explication est cependant un peu contradictoire avec la situation décrite dans la question, n'est-ce pas? Là, l'entropie (surveillée avec watch) croît régulièrement puis diminue fortement. Si l' watchentropie est consommée à chaque lecture, elle devrait en fait diminuer régulièrement.
techraf
@techraf Bonne observation, l'invocation périodique catdevrait en théorie avoir le même drain d'entropie qui ne devrait pas être visible. Il s'avère que l'entropie est déplacée vers un autre pool lorsqu'il y a entropie "suffisante".
Lekensteyn
4

lsof n'est pas le meilleur outil à surveiller/dev/randomcar une lecture par un processus est terminée en très peu de temps. Je ne connais pas de bonne méthode pour obtenir quel processus effectue une lecture, mais en utilisant,inotifyvous pouvez surveiller s'il y a une lecture.

Ici, il existe essentiellement deux façons:

  1. Obtenez un résumé après N secondes avec:

    inotifywatch -v -t 60 /dev/random 
    
  2. Afficher les événements d'accès en direct :

    inotifywait -m --timefmt '%H:%M:%S' --format '%T: %e' /dev/random
    

Aucun ne vous donnera de processus et ce dernier ne vous donnera pas de taille de lecture. Le premier vous donnera un résumé comme dans:

total  access  close_nowrite  open  filename
18     16      1              1     /dev/random

Si vous avez ça en marche et faites un dd if=/dev/random of=/tmp/foo bs=1 count=3, vous avez l'idée.

De toute façon. Cela ne vous donnera pas de tiques lorsque le noyau consomme à partir du pool.


Quand il s'agit de vérifier l'état de l'entropie à l'aide

watch cat /proc/sys/kernel/random/entropy_avail

n'est pas la meilleure idée car chacun catva consommer l'entropie. (Je vois maintenant qu'il est apparu une autre réponse qui mentionne également cela.) J'ai également un code C pour cela et j'ai essayé de le localiser hier. Je verrai si je peux le trouver et mettre à jour la réponse plus tard.

Runium
la source
auditd peut enregistrer les lectures /dev/random(je sais qu'il existe des exemples similaires sur ce site).
Gilles 'SO- arrête d'être méchant'
1
Que diriez-vous d'utiliser le perl suivant à la place de watch cat: use Fcntl 'SEEK_SET'; open(my $fh,"<", "/proc/sys/kernel/random/entropy_avail"); while (1) { print <$fh>; sleep(1); seek($fh,0,SEEK_SET); }
gmatht