Cosa continua a drenare l'entropia?


21

Se lo faccio, watch cat /proc/sys/kernel/random/entropy_availvedo che l'entropia dei miei sistemi aumenta lentamente nel tempo, fino a quando non raggiunge l'intervallo 180-190 a quel punto scende a circa 120-130. Le cadute di entropia sembrano verificarsi circa ogni venti secondi. Lo osservo anche quando lsofdice che nessun processo ha /dev/randomo /dev/urandomaperto. Cosa sta drenando l'entropia? Anche il kernel ha bisogno di entropia o forse sta rielaborando il pool più grande in un pool più piccolo e di migliore qualità?

Questo è su una macchina bare metal, senza connessioni SSL / SSH / WPA.


Bella domanda, e anche se non posso darti una risposta specifica, per me ha senso che il "pool di entropia" non sia semplicemente qualcosa che dovrebbe aumentare quando non viene utilizzato. /dev/randomè, dopotutto, qualcosa che viene utilizzato per scopi crittografici sicuri e l'implementazione non può permettersi di essere ingenua. Una spiegazione potrebbe essere accennata nell'ultimo punto qui: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (a partire da "Mantieni un codice di flusso con una chiave e un vettore di inizializzazione ...") -> il pool viene sostituito ogni volta che è sufficiente i dati si sono accumulati.
Riccioli d'oro

Si noti che in ogni caso, il calcolo dell'entropia di Linux /dev/randomè praticamente falso - una volta che il pool di entropia è stato riempito una volta, /dev/urandomè altrettanto buono /dev/random.
Gilles 'SO- smetti di essere malvagio' il

1
@techraf Wow, quella risposta è diventata molto veloce. Non mi sarei mai aspettato di ottenere una risposta 2,5 anni dopo.
wingedsubmariner

Risposte:


20

L'entropia non si perde solo via /dev/{,u}random, ma ne prende anche un po 'il kernel. Ad esempio, i nuovi processi hanno indirizzi randomizzati (ASLR) e i pacchetti di rete richiedono numeri di sequenza casuali. Anche il modulo del filesystem può rimuovere qualche entropia. Vedi i commenti in drivers / char / random.c . Si noti inoltre che si entropy_availriferisce al pool di input , non ai pool di output (fondamentalmente il non-blocco /dev/urandome il blocco /dev/random).

Se hai bisogno di guardare il pool di entropia, non utilizzarlo watch cat, che consumerà entropia ad ogni invocazione di cat. In passato volevo anche guardare questo pool poiché GPG era molto lento nel generare chiavi, quindi ho scritto un programma C con l'unico scopo di guardare il pool di entropia: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Si noti che potrebbero esserci processi in background che consumano anche entropia. Utilizzando i punti di traccia su un kernel appropriato è possibile visualizzare i processi che modificano il pool di entropia. Esempio di utilizzo che registra tutti i punti di traccia relativi al sottosistema casuale incluso il callchain ( -g) su tutte le CPU ( -a) che iniziano la misurazione dopo 1 secondo per ignorare il proprio processo ( -D 1000) e includendo i timestamp ( -T):

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

Leggilo con uno di questi comandi (cambia proprietario perf.datacome necessario):

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

L' perf scriptoutput fornisce una visione interessante e mostra quando circa 8 byte (64 bit) di entropia vengono periodicamente scaricati sulla mia macchina:

kworker / 0: 2 193 [000] 3292.235908: random: extract_entropy: ffffffff8173e956 pool: nbytes 8 entropy_count 921 chiamante _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: random: 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: bit 2 entropy_count 859 entropy_total 2 caller 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)

Apparentemente ciò accade per prevenire lo spreco di entropia trasferendo l'entropia dal pool di input ai pool di output:

/*
 * 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)
{
    ...
}

2
+1 per il fatto che anche operazioni apparentemente "incoerenti" come l'avvio di un programma possono drenare una piccola quantità di entropia.
un CVn

Questa spiegazione è tuttavia un po 'contraddittoria rispetto alla situazione descritta nella domanda, non è vero? Lì l'entropia (monitorata con watch) cresce costantemente, poi scende acutamente. Se watchconsumato entropia ad ogni lettura, dovrebbe effettivamente diminuire costantemente.
techraf,

@techraf Una buona osservazione, invocando periodicamente, catin teoria, dovrebbe avere lo stesso drenaggio entropico che non dovrebbe essere visibile. Si scopre che l'entropia viene spostata in un pool diverso quando c'è entropia "sufficiente".
Lekensteyn,

4

lsof non è il miglior strumento per monitorare/dev/randomcome una lettura da un processo è finito in un molto breve lasso di tempo. Non conosco un buon metodo per ottenere quale processo sta facendo una lettura, ma usandoinotifyte puoi monitorare se c'è una lettura.

Qui ci sono sostanzialmente due modi:

  1. Ottieni un riepilogo dopo N secondi con:

    inotifywatch -v -t 60 /dev/random 
    
  2. Visualizza eventi di accesso live :

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

Né ti darà il processo e quest'ultimo non ti darà la dimensione della lettura. Il primo ti darà un riepilogo come in:

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

Se hai quello in esecuzione e fai un dd if=/dev/random of=/tmp/foo bs=1 count=3, hai l'idea.

Comunque. Questo non ti darà segni di spunta quando il kernel consuma dal pool.


Quando si tratta di controllare lo stato dell'entropia usando

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

non è la migliore idea in quanto ognuno catconsumerà entropia. (Vedo che è spuntata un'altra risposta che menziona anche questo.) Ho anche un po 'di codice C per questo e ho cercato di individuarlo ieri. Vedrò se riesco a trovarlo e ad aggiornare la risposta più tardi.


auditd può registrare le letture da /dev/random(so che ci sono esempi simili su questo sito).
Gilles 'SO- smetti di essere malvagio' il

1
Che ne dici di usare il seguente perl al posto di 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.