New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Linux-specific getrandom call to obtain random data. #75

Merged
merged 1 commit into from Jun 18, 2018

Conversation

Projects
None yet
3 participants
@Lastique
Member

Lastique commented Jun 17, 2018

getrandom is the base implementation for getentropy on Linux. It is also
available in the form of a syscall, which can be called directly on systems with
glibc versions older than 2.25 which don't yet provide wrappers for getrandom or
getentropy but have a recent enough Linux kernel (for example, Debian Stretch).

On systems other than Linux (e.g. Solaris) getentropy is documented as a
source for initialization of a user-space PRNG instead of a direct source
for random data. Since we use the random data directly to initialize UUIDs,
using getrandom on other platforms, where available, would be more preferable
than getentropy. Unfortunately, the only other platform that is known to support
both getentropy and getrandom (Solaris) documents getrandom to return 0
on error, which is a valid return value on Linux. It's not clear if this is
a documentation error or a true incompatibility, and I have no way to test,
so do not use getrandom on Solaris for now. For this reason (and in case
if it is also used on some other platforms) getentropy backend is still
preserved.

@jeking3

Is the performance difference between getentropy and getrandom so much that it warrants another code path?

In the test Jamfile you may want to add explicit cases that force both of the linux implementations to execute in positive and negative test cases to ensure test coverage. Without that, most (maybe all) CI builds will test getrandom and nothing will be testing getentropy any more.

@@ -15,6 +15,8 @@
# include <boost/uuid/detail/random_provider_arc4random.ipp>
#elif defined(BOOST_UUID_RANDOM_PROVIDER_BCRYPT)
# include <boost/uuid/detail/random_provider_bcrypt.ipp>
#elif defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM)

This comment has been minimized.

@jeking3

jeking3 Jun 17, 2018

Collaborator

Was trying to keep these in alphabetical order :)

{
#if defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM)
return BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM(buf, size, flags);
#elif defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER)

This comment has been minimized.

@jeking3

jeking3 Jun 17, 2018

Collaborator

To implement the unit test could you have the mock implement ::getrandom and have the mock header define BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER? Unfortunately we're going to have a drop in coverage on the syscall since that (probably) can't be mocked.

This comment has been minimized.

@Lastique

Lastique Jun 17, 2018

Member

I don't like redefining system functions. I've seen you did this with getentropy and I deliberately did not follow this route. I think, that mock should be changed as well, but didn't do it in this PR as it was unrelated.

#if BOOST_LIB_C_GNU >= BOOST_VERSION_NUMBER(2, 25, 0)
#define BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER
#elif defined(__has_include)
#if __has_include(<sys/random.h>)

This comment has been minimized.

@jeking3

jeking3 Jun 17, 2018

Collaborator

I've never seen __has_include before. I was just thinking about how nice it would be to have the following include syntax in C++:

#include <boost/uuid/sha1.hpp> or <boost/uuid/detail/sha1.hpp>

To handle headers that move without leaving behind forwarding headers.

This comment has been minimized.

@Lastique

Lastique Jun 17, 2018

Member

I've never seen __has_include before.

It's one of the SD-6 macros most recent compilers support.

https://en.cppreference.com/w/cpp/experimental/feature_test

@Lastique

This comment has been minimized.

Member

Lastique commented Jun 17, 2018

Is the performance difference between getentropy and getrandom so much that it warrants another code path?

I don't expect performance to be significantly different. The main reasons for this backend are (a) supporting more platforms (glibc < 2.25) and (b) using the more appropriate API for random data generation. As I noted, getentropy is mostly targeted for seeding user-space PRNGs. I.e. read some (not much) random data to initialize a UPRNG and then obtain most of the random data from UPRNG. Given that on Linux getentropy is based on getrandom, this part is mostly puristic, but still worth mentioning. It may be significant on other systems.

In the test Jamfile you may want to add explicit cases that force both of the linux implementations to execute in positive and negative test cases to ensure test coverage. Without that, most (maybe all) CI builds will test getrandom and nothing will be testing getentropy any more.

I'm not sure it is worth doing. On Linux, getentropy backend is not going to be used, ever, so why test it there. I guess, you probably want to "emulate" other systems by forcing getentropy?

@jeking3

This comment has been minimized.

Collaborator

jeking3 commented Jun 17, 2018

Yes, since we don't have a Solaris CI environment, it's nice to ensure the code doesn't rot somehow.

Add support for Linux-specific getrandom call to obtain random data.
getrandom is the base implementation for getentropy on Linux. It is also
available in the form of a syscall, which can be called directly on systems with
glibc versions older than 2.25 which don't yet provide wrappers for getrandom or
getentropy but have a recent enough Linux kernel (for example, Debian Stretch).

On systems other than Linux (e.g. Solaris) getentropy is documented as a
source for initialization of a user-space PRNG instead of a direct source
for random data. Since we use the random data directly to initialize UUIDs,
using getrandom on other platforms, where available, would be more preferable
than getentropy. Unfortunately, the only other platform that is known to support
both getentropy and getrandom (Solaris) documents getrandom to return 0
on error, which is a valid return value on Linux. It's not clear if this is
a documentation error or a true incompatibility, and I have no way to test,
so do not use getrandom on Solaris for now. For this reason (and in case
if it is also used on some other platforms) getentropy backend is still
preserved.

For running tests in the CI on the getentropy backend added the
BOOST_UUID_RANDOM_PROVIDER_DISABLE_GETRANDOM macro, which will disable getrandom
if one is detected. Currently, the macro is only used for tests on Linux.

@Lastique Lastique force-pushed the Lastique:add_getrandom_backend branch from c0cebdc to 6c060f6 Jun 17, 2018

@codecov

This comment has been minimized.

codecov bot commented Jun 17, 2018

Codecov Report

Merging #75 into develop will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff            @@
##           develop      #75   +/-   ##
========================================
  Coverage    78.34%   78.34%           
========================================
  Files           13       13           
  Lines          605      605           
  Branches       156      156           
========================================
  Hits           474      474           
  Misses          17       17           
  Partials       114      114

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0d0aa87...6c060f6. Read the comment docs.

@Lastique

This comment has been minimized.

Member

Lastique commented Jun 17, 2018

I've updated the PR. For tests, I've added the internal BOOST_UUID_RANDOM_PROVIDER_DISABLE_GETRANDOM macro, which is only used by tests on Linux, currently. I've also updated the docs.

@jeking3 jeking3 merged commit 405f961 into boostorg:develop Jun 18, 2018

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@Lastique Lastique deleted the Lastique:add_getrandom_backend branch Jun 20, 2018

@bajizhh

This comment has been minimized.

bajizhh commented Oct 10, 2018

::syscall(SYS_getrandom, buf, size, flags) failed on ubuntu 16.04.1

throws an exception blow:
boost::exception_detail::clone_impl<boost::exception_detail::error_info_injectorboost::uuids::entropy_error >

system kernel info:
Linux app2 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

@Lastique

This comment has been minimized.

Member

Lastique commented Oct 10, 2018

I've replied in #79.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment