O que mantém a entropia de drenagem?

17

Se eu fizer watch cat /proc/sys/kernel/random/entropy_avail , vejo que a entropia de meus sistemas aumenta lentamente com o tempo, até atingir a faixa de 180-190, altura em que cai para cerca de 120-130. As quedas na entropia parecem ocorrer a cada vinte segundos. Observo isso mesmo quando lsof diz que nenhum processo tem /dev/random ou /dev/urandom open. 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?

Isso está em uma máquina bare-metal, sem conexões SSL / SSH / WPA.

    
por wingedsubmariner 20.10.2013 / 16:10

2 respostas

17

Entropy não é apenas perdido via /dev/{,u}random , o kernel também leva alguns. Por exemplo, novos processos têm endereços randomizados (ASLR) e os pacotes de rede precisam de números de seqüência aleatórios. Até mesmo 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_avail refere-se ao conjunto de entrada , não aos conjuntos de saída (basicamente, o% de não-bloqueio/dev/urandom e o% de bloqueio/dev/random).

Se você precisar observar o pool de entropia, não use watch cat , que consumirá entropia a cada invocação de cat . No passado, eu também queria assistir a este pool, pois o GPG era muito lento na geração de chaves, portanto eu escrevi um programa em C com o único propósito de observar o pool de entropia: link .

Observe que pode haver processos em segundo plano que também consomem entropia. Usando pontos de rastreio em um kernel apropriado, você pode ver os processos que modificam o pool de entropia. Exemplo de uso que registra todos os pontos de rastreio 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 timestamps ( -T ) :

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

Leia com um desses comandos (altere o proprietário de perf.data conforme necessário):

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

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

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

Aparentemente, isso evita o desperdício de entropia ao transferir a entropia do conjunto de entrada para os conjuntos de saída:

/*
 * 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)
{
    ...
}
    
por 21.10.2013 / 13:31
4

lsof não é a melhor ferramenta para monitorar /dev/random quando uma leitura de um processo termina em um muito curto período de tempo . Eu não sei de um bom método de obter o processo que está fazendo uma leitura, mas usando inotify você pode monitorar se houver uma leitura.

Aqui há basicamente duas maneiras:

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

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

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

Nem vai dar processo e este último não lhe dará o tamanho da leitura. O primeiro lhe dará um resumo como em:

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

Se você tiver essa execução e fizer um dd if=/dev/random of=/tmp/foo bs=1 count=3 , terá a ideia.

De qualquer forma. Isso não lhe dará sinais 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 idéia, pois cada cat consumirá entropia. (Eu vejo agora ele apareceu outra resposta que também mencionam isso.) Eu também tenho um código C para isso e tentei localizá-lo ontem. Vou ver se consigo encontrar e atualizar a resposta depois.

    
por 21.10.2013 / 14:10

Tags