mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
Add fallback for random number generator
`getrandom()` is available since Linux 3.17 (2014/10/05) yet there are older devices that don't meet this requirement. Closes #22691. PR #22723.
This commit is contained in:
parent
9133b16431
commit
f51ad39ad9
4 changed files with 49 additions and 8 deletions
|
@ -42,7 +42,7 @@
|
|||
|
||||
uint32_t Utils::Random::rand(const uint32_t min, const uint32_t max)
|
||||
{
|
||||
static RandomLayer layer;
|
||||
static const RandomLayer layer;
|
||||
|
||||
// new distribution is cheap: https://stackoverflow.com/a/19036349
|
||||
std::uniform_int_distribution<uint32_t> uniform(min, max);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
|
@ -44,6 +45,27 @@ namespace
|
|||
|
||||
RandomLayer()
|
||||
{
|
||||
if (::getrandom(nullptr, 0, 0) < 0)
|
||||
{
|
||||
if (errno == ENOSYS)
|
||||
{
|
||||
// underlying kernel does not implement this system call
|
||||
// fallback to `urandom`
|
||||
m_randDev = fopen("/dev/urandom", "rb");
|
||||
if (!m_randDev)
|
||||
qFatal("Failed to open /dev/urandom. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
qFatal("getrandom() error. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~RandomLayer()
|
||||
{
|
||||
if (m_randDev)
|
||||
fclose(m_randDev);
|
||||
}
|
||||
|
||||
static constexpr result_type min()
|
||||
|
@ -56,7 +78,15 @@ namespace
|
|||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
result_type operator()() const
|
||||
{
|
||||
if (!m_randDev)
|
||||
return getRandomViaAPI();
|
||||
return getRandomViaFile();
|
||||
}
|
||||
|
||||
private:
|
||||
result_type getRandomViaAPI() const
|
||||
{
|
||||
const int RETRY_MAX = 3;
|
||||
|
||||
|
@ -68,10 +98,21 @@ namespace
|
|||
return buf;
|
||||
|
||||
if (result < 0)
|
||||
qFatal("getrandom() error. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
qFatal("getrandom() error. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
qFatal("getrandom() failed. Reason: too many retries.");
|
||||
}
|
||||
|
||||
result_type getRandomViaFile() const
|
||||
{
|
||||
result_type buf = 0;
|
||||
if (fread(&buf, sizeof(buf), 1, m_randDev) == 1)
|
||||
return buf;
|
||||
|
||||
qFatal("Read /dev/urandom error. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
FILE *m_randDev = nullptr;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace
|
|||
: m_randDev {fopen("/dev/urandom", "rb")}
|
||||
{
|
||||
if (!m_randDev)
|
||||
qFatal("Failed to open /dev/urandom. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
qFatal("Failed to open /dev/urandom. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
~RandomLayer()
|
||||
|
@ -67,10 +67,10 @@ namespace
|
|||
result_type operator()() const
|
||||
{
|
||||
result_type buf = 0;
|
||||
if (fread(&buf, sizeof(buf), 1, m_randDev) != 1)
|
||||
qFatal("Read /dev/urandom error. Reason: %s. Error code: %d.", std::strerror(errno), errno);
|
||||
|
||||
if (fread(&buf, sizeof(buf), 1, m_randDev) == 1)
|
||||
return buf;
|
||||
|
||||
qFatal("Read /dev/urandom error. Reason: \"%s\". Error code: %d.", std::strerror(errno), errno);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace
|
|||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
result_type operator()()
|
||||
result_type operator()() const
|
||||
{
|
||||
result_type buf = 0;
|
||||
const bool result = m_processPrng(reinterpret_cast<PBYTE>(&buf), sizeof(buf));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue