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_avail
fait référence au pool d'entrée , pas aux pools de sortie (essentiellement le non-blocage /dev/urandom
et 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.data
si nécessaire):
perf report # opens an interactive overview
perf script # outputs events after each other with traces
La perf script
sortie 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)
{
...
}
/dev/random
est, 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.