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 является битовой маской, которая может содержать ноль или более следующих флагов:
При успешном выполнении getrandom() возвращает количество скопированных в буфер buf байт. Это значение может быть меньше, чем количество запрашиваемых в buflen байт, если в flags был указан GRND_RANDOM и нет достаточного количества энтропии в источнике random, или если системный вызов был прерван сигналом.
В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.
Вызов getrandom() появился в версии ядра Linux 3.17. Поддержка в glibc добавлена в версии 2.5.
Данный вызов есть только в Linux.
Обзор и сравнение возможных интерфейсов, через которые можно получать случайные данные, смотрите в random(7).
В отличие от /dev/random и /dev/urandom, в вызове getrandom() не используются пути или файловые дескрипторы. Таким образом, getrandom() полезен в случаях, когда chroot(2) делает пути /dev невидимыми и приложение (например, служба во время загрузки) закрывает файловый дескриптор одного из этих файлов, которые были открыты библиотекой.
На момент Linux 3.19 существуют следующие ограничения:
При чтении из источника 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 существуют следующие дефекты:
2017-09-15 | Linux |