Что продолжает истощать энтропию?

21

Если я это сделаю, watch cat /proc/sys/kernel/random/entropy_availто увижу, что энтропия моей системы постепенно увеличивается со временем, пока не достигнет диапазона 180-190, и в этот момент она падает примерно до 120-130. Падение энтропии, по-видимому, происходит примерно каждые двадцать секунд. Я наблюдаю это, даже когда lsofговорит, что ни один процесс не имеет /dev/randomили не /dev/urandomоткрыт. Что истощает энтропию? Нужно ли ядру энтропию, или, может быть, оно перерабатывает больший пул в меньший пул лучшего качества?

Это на чистом компьютере без соединений SSL / SSH / WPA.

wingedsubmariner
источник
Хороший вопрос, и хотя я не могу дать вам конкретный ответ, для меня имеет смысл, что «пул энтропии» - это не просто что-то, что должно увеличиваться, если не используется. /dev/randomв конце концов, это то, что используется для безопасных криптографических целей, и реализация не может быть наивной. В последнем пункте может быть дано одно объяснение: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (начиная с «Поддерживать потоковый шифр с ключом и вектором инициализации ...») -> пул заменяется всякий раз, когда достаточно данные накопились.
Златовласка
Обратите внимание, что в любом случае подсчет энтропии в Linux в /dev/randomзначительной степени фальшивый - как только пул энтропии будет заполнен один раз, /dev/urandomон так же хорош, как и /dev/random.
Жиль "ТАК ... перестать быть злым"
1
@techraf Ух ты, этот ответ стал большим быстро. Я никогда не ожидал получить ответ через 2,5 года.
wingedsubmariner

Ответы:

20

Энтропия теряется не только через /dev/{,u}randomядро, но и через некоторое. Например, новые процессы имеют рандомизированные адреса (ASLR), а сетевым пакетам требуются случайные порядковые номера. Даже модуль файловой системы может убрать некоторую энтропию. Смотрите комментарии в drivers / char / random.c . Также обратите внимание, что entropy_availотносится к входному пулу , а не к выходным пулам (в основном неблокирующим /dev/urandomи блокирующим /dev/random).

Если вам нужно следить за пулом энтропии, не используйте watch cat, это будет потреблять энтропию при каждом вызове cat. В прошлом я также хотел наблюдать за этим пулом, поскольку GPG очень медленно генерировал ключи, поэтому я написал программу на C с единственной целью - наблюдать за пулом энтропии: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Обратите внимание, что могут быть фоновые процессы, которые также потребляют энтропию. Используя точки трассировки в соответствующем ядре, вы можете видеть процессы, которые изменяют пул энтропии. Пример использования, в котором записываются все точки трассировки, связанные со случайной подсистемой, включая callchain ( -g) на всех процессорах ( -a), начинающих измерение через 1 секунду, чтобы игнорировать свой собственный process ( -D 1000) и включающих timestamps ( -T):

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

Прочтите его одной из следующих команд (при perf.dataнеобходимости измените владельца ):

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

perf scriptВыход дает интересную информацию и показывает , когда около 8 байт (64 бит) энтропии периодически сливают на моей машине:

kworker / 0: 2 193 [000] 3292.235908: случайный: extract_entropy: ffffffff8173e956 пул: nbytes 8 entropy_count 921 абонент _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: случайный: 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: случайный: credit_entropy_bits: ffffffff8173e956 пул: биты 2 entropy_count 859 entropy_total 2 вызывающая сторона 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)

Очевидно, это происходит для предотвращения потери энтропии путем передачи энтропии из входного пула в выходные пулы:

/*
 * 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
источник
2
+1 за указание на то, что даже, казалось бы, «безобидные» операции, такие как запуск программы, могут истощить небольшое количество энтропии.
CVn
Это объяснение, однако, немного противоречит ситуации, описанной в вопросе, не так ли? Там энтропия (контролируемая watch) неуклонно растет, а затем резко падает. Если watchэнтропия потребляется при каждом чтении, она должна постепенно уменьшаться.
techraf
@techraf Хорошее наблюдение, периодически вызывая, catтеоретически должен иметь такой же энтропийный сток, который не должен быть виден. Оказывается, энтропия перемещается в другой пул, когда существует «достаточная» энтропия.
Лекенштейн
4

lsof - не лучший инструмент для мониторинга,/dev/randomпоскольку одно чтение процесса завершается за очень короткое время. Я не знаю хорошего метода получения информации о том, какой процесс выполняет чтение, но с помощьюinotifyнего можно отслеживать , есть ли чтение.

Здесь есть в основном два пути:

  1. Получить сводку через N секунд с помощью:

    inotifywatch -v -t 60 /dev/random 
    
  2. Просмотр событий прямого доступа:

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

Ни один из них не даст вам процесс, а последний не даст вам размер прочитанного. Первый даст вам резюме, как в:

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

Если у вас есть что работает и сделать dd if=/dev/random of=/tmp/foo bs=1 count=3, вы получите идею.

Так или иначе. Это не даст вам галочки, когда ядро ​​потребляет из пула.


Когда дело доходит до проверки состояния энтропии с помощью

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

не лучшая идея, поскольку каждый catсобирается потреблять энтропию. (Я вижу, что теперь выскочил другой ответ, в котором также упоминается об этом.) У меня также есть некоторый C-код для этого и я пытался найти его вчера. Я посмотрю, смогу ли я найти его и обновить ответ позже.

Runium
источник
audd может регистрировать чтения /dev/random(я знаю, что на этом сайте есть похожие примеры).
Жиль "ТАК ... перестать быть злым"
1
Как насчет использования следующего Perl вместо 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