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
- rand_unix.c: open random devices on first use only Commit c7504aeb640a (pr #6432) fixed a regression for applications in chroot environments, which compensated the fact that the new OpenSSL CSPRNG (b... — committed to mspncp/openssl by mspncp 6 years ago
- rand_unix.c: open random devices on first use only Commit c7504aeb640a (pr #6432) fixed a regression for applications in chroot environments, which compensated the fact that the new OpenSSL CSPRNG (b... — committed to openssl/openssl by mspncp 6 years ago
- Workaround for an OpenSSL bug about not closing /dev/*random. This is a workaround for an issue in OpenSSL 1.1.1, where the /dev/random and /dev/urandom files remain open after all listening sockets ... — committed to nginx/unit by mar0x 3 years ago
Correct. When you configure
--with-rand-seed=getrandomthen the preprocessor constantOPENSSL_RAND_SEED_GETRANDOMis defined and no other constantsOPENSSL_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=osmaps to whatever is best for the platform, on Linux it’s equivalent to--with-rand-seed=getrandom,devrandom, seehttps://github.com/openssl/openssl/blob/ac765685d4b08a48cefffc71c434760045154dad/crypto/rand/rand_unix.c#L189-L195