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