GETRANDOM(2) Руководство программиста Linux GETRANDOM(2)

ИМЯ

getrandom - возвращает серию произвольных байт

ОБЗОР

#include <sys/random.h>

ssize_t getrandom(void *buf, size_t buflen, unsigned int flags);

ОПИСАНИЕ

Системный вызов getrandom() заполняет буфер, указанный в buf, произвольными байтами в количестве до buflen. Эти байты можно использовать как начальные значения в генераторах произвольных чисел пространства пользователя или с целями шифрования.

По умолчанию, getrandom() забирает энтропию из источника urandom (т. е., того же источника что и устройство /dev/urandom). Это поведение можно изменить через параметр flags.

Если источник urandom инициализирован, то из него можно прочитать не более 256 байт, но всегда возвращается столько байт, сколько запрошено и это не будет прерываться сигналами. Для буферов большего размера это не гарантируется. Например, если вызов прерывается обработчиком сигнала, то он может вернуть частично заполненный буфер или завершиться с ошибкой EINTR.

Если источник urandom ещё не инициализирован, то вызов getrandom() блокируется, если в flags не указано значение GRND_NONBLOCK.

Аргумент flags является битовой маской, которая может содержать ноль или более следующих флагов:

Если этот бит установлен, то произвольные байты берутся из источника random (т. е., того же источника что и устройство /dev/urandom), а не из источника urandom. Ограничение источника random следует из энтропии, которую можно получить из окружающего шума. Если количество доступных байт в random меньше запрашиваемых в buflen, то вызов завершается сразу после выдачи всех доступных произвольных байт. Если произвольных байт нет, то поведение зависит от наличия флага GRND_NONBLOCK в параметре flags.
По умолчанию, при чтении из источника random вызов getrandom() блокируется, если произвольные байты недоступны, и а при чтении из источника urandom блокируется, если ещё не инициализирован пул энтропии. Если указан флаг GRND_NONBLOCK, то в этих случаях getrandom() не блокируется, а сразу возвращает -1 и присваивает errno значение EAGAIN.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении getrandom() возвращает количество скопированных в буфер buf байт. Это значение может быть меньше, чем количество запрашиваемых в buflen байт, если в flags был указан GRND_RANDOM и нет достаточного количества энтропии в источнике random, или если системный вызов был прерван сигналом.

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.

ОШИБКИ

Запрошенное количество энтропии недоступно, и getrandom() заблокировался бы, если бы отсутствовал флаг GRND_NONBLOCK.
Адрес, указанный в buf, лежит вне доступного адресного пространства.
Вызов был прерван обработчиком сигнала; смотрите описание о прерывании вызовов read(2) при работе с «медленными» устройствами и при отсутствии флага SA_RESTART в справочной странице signal(7).
В flags указан неверный флаг.
Обёрточная функция в glibc для getrandom() определила, что используемое ядро не поддерживает данный системный вызов.

ВЕРСИИ

Вызов getrandom() появился в версии ядра Linux 3.17. Поддержка в glibc добавлена в версии 2.5.

СООТВЕТСТВИЕ СТАНДАРТАМ

Данный вызов есть только в Linux.

ЗАМЕЧАНИЯ

Обзор и сравнение возможных интерфейсов, через которые можно получать случайные данные, смотрите в random(7).

В отличие от /dev/random и /dev/urandom, в вызове getrandom() не используются пути или файловые дескрипторы. Таким образом, getrandom() полезен в случаях, когда chroot(2) делает пути /dev невидимыми и приложение (например, служба во время загрузки) закрывает файловый дескриптор одного из этих файлов, которые были открыты библиотекой.

Возвращается максимальное количество байтов

На момент Linux 3.19 существуют следующие ограничения:

  • При чтении из источника urandom в системах, где размер int равен 32 битам, один вызов getrandom() возвращает максимум 33554431 байт.
  • При чтении из источника random возвращается максимум 512 байт.

Прерывание обработчиком сигнала

При чтении из источника urandom (GRND_RANDOM не указан), getrandom() блокируется до тех пор, пока не специализируется пул энтропии (если не указан флаг GRND_NONBLOCK). Если запрос требует большого количества байт (больше 256), getrandom() будет заблокирован до тех пор, пока байты не будут сгенерированы и переданы из памяти ядра в buf. При чтении из random (указан GRND_RANDOM), getrandom() будет заблокирован до тех пор, пока какое-то количество произвольных байт не станет доступно (если не указан флаг GRND_NONBLOCK).

Поведение при прерывании обработчиком сигнала вызова getrandom(), заблокированного чтением источника urandom, зависит от состояния инициализации буфера энтропии и от запрашиваемого объёма buflen. Если энтропия ещё не инициализирована, то вызов завершается ошибкой EINTR. Если пул энтропии инициализирован и запрашиваемый объём большой (buflen > 256), то вызов или завершится успешно, вернув частично заполненный буфер, или завершится с ошибкой EINTR. Если пул энтропии инициализирован и запрашиваемый объём мал (buflen <= 256), то getrandom() завершится без ошибки EINTR. Вместо этого, он вернёт все запрашиваемый байты.

При чтении из источника random блокирующие запросы на любой объём могут быть прерваны обработчиком сигналом (вызов завершается с ошибкой EINTR).

Использование getrandom() для чтения маленьких буферов (<= 256 байт) из источника urandom — предпочтительный способ использования.

Специальный режим для маленького объёма buflen был разработан для совместимости с системным вызовом getentropy(3) из OpenBSD, который теперь поддерживается glibc.

Пользователь getrandom() всегда должен проверять возвращаемое значение, чтобы определить что возникла ошибка или возвращено меньшее количество запрошенных байт. В случае когда флаг GRND_RANDOM не указан и значение buflen меньше или равно 256, возврат меньшего количества байт чем запрошено никогда не происходит, но осторожный программист всегда проверяет значение!

ДЕФЕКТЫ

В Linux 3.19 существуют следующие дефекты:

*
В зависимости от загруженности ЦП, getrandom() не реагирует на прерывания, пока не прочитает все запрашиваемые байты.

СМОТРИТЕ ТАКЖЕ

getentropy(3), random(4), urandom(4), random(7), signal(7)

2017-09-15 Linux