[Solved] lighttpd is waiting for syscall_355 and/or /dev/urandom initialization

Added by dzavy about 7 years ago

My setup: x86, OpenWRT 15 - kernel 3.18.44, glibc 2.21. Modules: cgi and extforward only, very minimal but standard configuration, no custom patches.

lighttpd 1.4.38 is working fine

in version 1.4.42 it seems to be waiting for syscall_355, end of it matches with /dev/urandom initialization:

[ 10.841612] r8169 0000:04:00.0 eth0: link up
[ 10.841947] IPv6: ADDRCONF: eth0: link becomes ready
[ 361.374446] random: nonblocking pool is initialized

open("/lib/", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\36\207\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1213404, ...}) = 0
mmap2(NULL, 1221984, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7407000
mmap2(0xb752c000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x124000) = 0xb752c000
mmap2(0xb752f000, 9568, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb752f000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7406000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7406700, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb752c000, 8192, PROT_READ) = 0
mprotect(0xb7707000, 4096, PROT_READ) = 0
mprotect(0xb775f000, 4096, PROT_READ) = 0
time(NULL) = 1481232185
brk(0) = 0x8c5e000
brk(0x8c7f000) = 0x8c7f000
syscall_355(0x8075ae4, 0x6, 0, 0xb752e3c4, 0xc, 0x8075ae4

--- BIG GAP, couple minutes ---

) = 0x6
getpid() = 2816
open("/dev/urandom", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 3

This only happens after startup/until /dev/urandom is initalized. Further application restarts are fine.

As per 355 should be getrandom().

Replies (5)

RE: lighttpd is waiting for syscall_355 and/or /dev/urandom initialization - Added by gstrauss about 7 years ago

You are correct that SYS_getrandom is defined to 355:

See lighttpd src/rand.c

        /* */
        /* */
        int num = (int)syscall(SYS_getrandom, buf, buflen, 0);

lighttpd runs through this call path at startup (if you have not built with openssl and your OS does not have getrandom() in libc) in order to have some entropy for use with mod_auth (which is a fairly typical module) with HTTP Digest auth and one for which having good entropy is important.

I was unaware that this could cause such a delay in lighttpd startup and will look to see if I can find more info.

In the meantime, if you are not using mod_auth, then you might comment out the line further down in src/rand.c, around line 92, which calls

if (0 == li_getentropy(buf, (size_t)num)) return 1;

Note that this is not recommended since it may severely reduce the randomness of the entropy used by the lighttpd server when generating digests in mod_auth.

RE: lighttpd is waiting for syscall_355 and/or /dev/urandom initialization - Added by gstrauss about 7 years ago

Here's a workable solution for systems running systemd (not OpenWRT)

Similar ideas (save random seed at shutdown and restore at startup for faster entropy seeding) could be used on embedded systems (like those that run OpenWRT) which have simple operations and take time to gather good entropy.


For OpenWRT, I might be willing to help conjure command line so that someone running ./configure for target system running OpenWRT does not detect SYS_getrandom, and so avoids that blocking call. (Yes, lighttpd could also be patched so that the syscall uses GRND_NONBLOCK and does not block, but that may reduce the quality of the entropy.)


RE: lighttpd is waiting for syscall_355 and/or /dev/urandom initialization - Added by gstrauss about 7 years ago

Ubuntu also provides entropy as a service.

Should lighttpd provide a means to save a random seed and use that at lighttpd startup? It would probably be better if entropy initialization were done as a system-wide solution, initializing entropy pool for the system as early as possible at system startup.

Note that if lighttpd is built with openssl (or libressl), then lighttpd src/rand.c prefers to use the SSL library routine RAND_bytes() to obtain a random seed.

RE: lighttpd is waiting for syscall_355 and/or /dev/urandom initialization - Added by gstrauss about 7 years ago

If you'd like to test with lighttpd git master, I just pushed some changes which defer the (potentially blocking) initialization of the PRNG until the point at which li_rand_pseudo_bytes() is called at runtime, which currently occurs only in mod_auth HTTP Digest auth, and in mod_usertrack.

See 544ccee5 and 28c8fec4