openssl: RAND_keep_random_devices_open not working

Using OpenSSL 1.1.1 in Arch linux, when checking lsof on a long-running application I noticed that /dev/random/ and /dev/urandom were being opened by something. Some digging around found that a relatively recent OpenSSL change was to blame and that using RAND_keep_random_devices_open(0); would stop that behavior (This program execs itself to refresh its binary without dropping established connections, so leaving them open was causing a descriptor leak). The man page says it takes effect immediately and should be called during initialization, but I found that it working is very dependent on when in the program the function is called – use it before any other OpenSSL routines that use random numbers, and the descriptors will be left open.

Consider this demonstration program:

#include <openssl/rand.h>
#include <openssl/bn.h>
#include <unistd.h>
#include <stdlib.h>
int main(void) {
  BIGNUM *bn;
  BN_CTX *ctx;
  RAND_keep_random_devices_open(0);
  ctx = BN_CTX_new();
  bn = BN_new();
  BN_set_word(bn, 1567);
  BN_is_prime_ex(bn, BN_prime_checks, ctx, NULL);
  sleep(10);
  return 0;
}

and the relevant strace output:

openat(AT_FDCWD, "/dev/urandom", O_RDONLY) = 3
fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
openat(AT_FDCWD, "/dev/random", O_RDONLY) = 4
fstat(4, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0
openat(AT_FDCWD, "/dev/srandom", O_RDONLY) = -1 ENOENT (No such file or directory)
futex(0x7f7ebc7db948, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f7ebc7db7f8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f7ebc7db7ec, FUTEX_WAKE_PRIVATE, 2147483647) = 0
getrandom("\x5b\xcd\xab\xc5\xa8\x3c\x89\x84\x8f\xcd\x97\x85\x90\x1a\x00\x22\xb3\x42\x4d\x53\x6b\xa6\xef\xa6\xad\x5e\xb2\x83\x2d\x99\x67\x8d", 32, 0) = 32
getpid()                                = 21486
clock_gettime(CLOCK_REALTIME, {tv_sec=1539757629, tv_nsec=856678890}) = 0
futex(0x7f7ebc7db918, FUTEX_WAKE_PRIVATE, 2147483647) = 0
nanosleep({tv_sec=10, tv_nsec=0}, 0x7ffea2d3c070) = 0
futex(0x7f7ebc7db6a4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
close(3)                                = 0
fstat(4, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0
close(4)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

It only closes the descriptors (3 and 4) when the program exits normally. If it instead execs another program, they’re left open and unused in it. If I move the RAND_keep_random_devices_open() call to just below the sleep(), they get closed right then, though. Instead of having to figure out by trial and error where to call the function, it’d be nice if it behaved as advertised. (I’m also not sure why it’s opening the random device files at all when it uses the getrandom() syscall instead to seed things, or why it’s opening both more than one…)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (13 by maintainers)

Commits related to this issue

Most upvoted comments

Correct. When you configure --with-rand-seed=getrandom then the preprocessor constant OPENSSL_RAND_SEED_GETRANDOM is defined and no other constants OPENSSL_RAND_SEED_XXX, so the following code is not compiled at all:

https://github.com/openssl/openssl/blob/ac765685d4b08a48cefffc71c434760045154dad/crypto/rand/rand_unix.c#L317-L326

Note: the default --with-rand-seed=os maps to whatever is best for the platform, on Linux it’s equivalent to --with-rand-seed=getrandom,devrandom, see

https://github.com/openssl/openssl/blob/ac765685d4b08a48cefffc71c434760045154dad/crypto/rand/rand_unix.c#L189-L195