O que continua drenando a entropia?

21

Se watch cat /proc/sys/kernel/random/entropy_availperceber, a entropia de meus sistemas aumenta lentamente ao longo do tempo, até atingir a faixa 180-190, quando cai para cerca de 120-130. As quedas na entropia parecem ocorrer a cada vinte segundos. Observo isso mesmo quando lsofdiz que nenhum processo tem /dev/randomou está /dev/urandomaberto. O que está drenando a entropia? O kernel também precisa de entropia ou talvez esteja reprocessando o pool maior em um pool menor e de melhor qualidade?

Esta é uma máquina bare-metal, sem conexões SSL / SSH / WPA.

wingedsubmariner
fonte
Boa pergunta, e embora eu não possa lhe dar uma resposta específica, faz sentido para mim que o "pool de entropia" não seja simplesmente algo que deve aumentar quando não utilizado. /dev/randomé, afinal, algo que é usado para fins criptográficos seguros e a implementação não pode se dar ao luxo de ser ingênua. Uma explicação pode ser sugerida no último ponto aqui: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (começando com "Manter uma cifra de fluxo com uma chave e o vetor de inicialização ...") -> o pool é substituído sempre que suficiente dados acumulados.
Goldilocks
Observe que, em qualquer caso, o cálculo de entropia do Linux /dev/randomé praticamente falso - uma vez que o conjunto de entropia esteja cheio uma vez, /dev/urandomé tão bom quanto /dev/random.
Gilles 'SO- stop be evil'
1
@ techech Uau, essa resposta ficou grande rapidamente. Eu nunca esperava obter uma resposta 2,5 anos depois.
wingedsubmariner

Respostas:

20

Entropia não é apenas perdida via /dev/{,u}random, o kernel também leva um pouco. Por exemplo, novos processos têm endereços aleatórios (ASLR) e pacotes de rede precisam de números de sequência aleatórios. Até o módulo do sistema de arquivos pode remover alguma entropia. Veja os comentários em drivers / char / random.c . Observe também que entropy_availse refere ao pool de entrada , não aos pools de saída (basicamente o não-bloqueio /dev/urandome o bloqueio /dev/random).

Se você precisar assistir ao pool de entropia, não use watch cat, que consumirá entropia a cada chamada de cat. No passado, eu também queria assistir a esse pool, pois o GPG era muito lento na geração de chaves; portanto, escrevi um programa C com o único objetivo de assistir ao pool de entropia: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Observe que pode haver processos em segundo plano que também consomem entropia. Usando pontos de rastreamento em um kernel apropriado, é possível ver os processos que modificam o pool de entropia. Exemplo de uso que registra todos os pontos de rastreamento relacionados ao subsistema aleatório, incluindo o callchain ( -g) em todas as CPUs ( -a) iniciando a medição após 1 segundo para ignorar seu próprio processo ( -D 1000) e incluindo registros de data e hora ( -T):

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

Leia-o com um destes comandos (altere o proprietário perf.dataconforme necessário):

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

A perf scriptsaída fornece uma visão interessante e mostra quando cerca de 8 bytes (64 bits) de entropia são drenados periodicamente na minha máquina:

kworker / 0: 2 193 [000] 3292.235908: aleatório: extract_entropy: ffffffff8173e956 pool: nbytes 8 entropy_count 921 chamador _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: aleatório: 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)

...

trocador 0 [002] 3292.507720: aleatório: credit_entropy_bits: ffffffff8173e956 pool: bits 2 entropy_count 859 entropy_total 2 chamador 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)

Aparentemente, isso acontece para evitar o desperdício de entropia, transferindo a entropia do conjunto de entrada para os conjuntos de saídas:

/*
 * 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
fonte
2
+1 por indicar que mesmo operações aparentemente "inócuas", como iniciar um programa, podem drenar uma pequena quantidade de entropia.
quer tocar
Essa explicação é no entanto um pouco contraditória à situação descrita na pergunta, não é? Lá, a entropia (monitorada com watch) cresce constantemente e depois cai acentuadamente. Se watchconsumida entropia em todas as leituras, deve realmente diminuir constantemente.
techraf
@techraf Boa observação, invocar periodicamente catdeve, em teoria, ter o mesmo dreno de entropia que não deve ser visível. Acontece que a entropia é movida para um pool diferente quando há entropia "suficiente".
Lekensteyn
4

Isof não é a melhor ferramenta para monitorar,/dev/randompois uma leitura de um processo termina em um período muito curto de tempo. Eu não conheço um bom método de obter qual processo está fazendo uma leitura, mas usandoinotifyvocê pode monitorar se há uma leitura.

Aqui existem basicamente duas maneiras:

  1. Obtenha um resumo após N segundos com:

    inotifywatch -v -t 60 /dev/random 
    
  2. Ver eventos de acesso ao vivo :

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

Nem o processo será processado, nem o último, o tamanho da leitura. O primeiro fornecerá um resumo como em:

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

Se você tem essa execução e faz um dd if=/dev/random of=/tmp/foo bs=1 count=3, você obtém a ideia.

De qualquer forma. Isso não lhe dará tiques quando o kernel consome do pool.


Quando se trata de verificar o status da entropia usando

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

não é a melhor ideia, pois cada catum deles consumirá entropia. (Vejo agora que apareceu outra resposta que também menciona isso.) Eu também tenho um código C para isso e tentei localizá-lo ontem. Vou ver se consigo encontrá-lo e atualizar a resposta mais tarde.

Runium
fonte
O auditd pode registrar leituras de /dev/random(sei que existem exemplos semelhantes neste site).
Gilles 'SO- stop be evil'
1
Que tal usar o seguinte perl no lugar 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 6/15