5

Doing fuser -v /dev/urandom tells me which processes currently have /dev/urandom open, but only that. Is there any was to determine anything about how much entropy each one is using up over time? For instance, it might be that one process is using up about 1 bit of entropy every minute, while a different one is using up about 8 bits per second; I'd like some way of determining that.

1
  • /dev/urandom is not really an entropy source, it is a PRNG reusing what is fed into /dev/random - estimating its entropy is questionable at best.
    – peterph
    Oct 9 '13 at 7:48
8

The short answer is 0, because entropy is not consumed.

There is a common misconception that entropy is consumed — that each time you read a random bit, this removes some entropy from the random source. This is wrong. You do not “consume” entropy. Yes, the Linux documentation gets it wrong.

During the life cycle of a Linux system, there are two stages:

  1. Initially, there is not enough entropy. /dev/random will block until it thinks it has amassed enough entropy; /dev/urandom happily provides low-entropy data.
  2. After a while, enough entropy is present in the random generator pool. /dev/random assigns a bogus rate of “entropy leek” and blocks now and then; /dev/urandom happily provides crypto-quality random data.

FreeBSD gets it right: on FreeBSD, /dev/random (or /dev/urandom, which is the same thing) blocks if it doesn't have enough entropy, and once it does, it keeps spewing out random data. On Linux, neither /dev/random nor /dev/urandom is the useful thing.

In practice, use /dev/urandom, and make sure when you provision your system that the entropy pool is fed (from disk, network and mouse activity, from a hardware source, from an external machine, …).

While you could try to read how many bytes get read from /dev/urandom, this is completely pointless. Reading from /dev/urandom does not deplete the entropy pool. Each consumer uses up 0 bits of entropy per any unit of time you care to name.

5
  • 6
    Although the answer is correct, it sort of misses the point I believe. The kernel does have an estimate on the amount of entropy available (readable from /proc/sys/kernel/random/entropy_avail) - and although it is not a reasonable practice, reading from /dev/urandom consumes it and makes processes reading from /dev/random block. So it is a perfectly reasonable thing to attempt to account which processes read /dev/urandom and how much, even if it does not make cryptographic sense.
    – Nakedible
    Apr 17 '14 at 10:50
  • 1
    See 2uo.de/myths-about-urandom for details on why this answer is correct and which entropy is not quite the problem people think it is.
    – Walter
    Nov 17 '16 at 1:53
  • From a practical Linux perspective, I've found it very useful to look at /proc/sys/kernel/random/entropy_avail over time, particularly for Java workloads. (some versions of Java, before 8u??? read from /dev/random as well as / in stead of /dev/urandom by default, and this makes things like J2EE workloads start up very slowly and stall). Particularly on a VM where there is no keyboard-mouse activity. Note also that dd if=/dev/urandom of=/tmp/bigfile will also deplete entropy_avail and cause reads form /dev/urandom to block. Jan 7 '20 at 1:51
  • 1
    @CameronKerr From a cryptographic perspective, entropy_avail is not useful for the same reason /dev/random is not useful. From a practical perspective, entropy_avail is useful only to investigate why a program may be blocked reading /dev/random. Jan 7 '20 at 11:45
  • 1
    @Gilles'SO-stopbeingevil': exactly right; entropy_avail is highly useful from an operational concern (why are some workloads freezing occassionally?), which is presumably the OPs motivation behind trying to determine where the demand is coming from. Jan 8 '20 at 19:55
1

While not automated, you could use a tool like strace to watch for reads from the file descriptor(s) related to urandom. Then see how much data is read over a specific time period to get the read rate.

0

There are a few ways you could approach the problem if you don't know (or don't suspect) which process may be depleting entropy_available on Linux.

As mentioned, you could use strace, which is great for getting useful insight into which processes you might want to look at.

You could use auditd to audit which processes open /dev/random or /dev/urandom, but that won't tell you how much data is read (to prevent logging issues). Here are some commands do list the rules and then add two watches

auditctl -l
auditctl -w /dev/random
auditctl -w /dev/urandom
auditctl -l

Now SSH into the box (or do something else you know should resulting in opening /dev/urandom or similar, such as dd).

ausearch -ts recent | aureport -f

In my case, I see something like the following:

[root@metrics-d02 vagrant]# ausearch -ts recent | aureport -f

File Report
===============================================
# date time file syscall success exe auid event
===============================================
1. 07/01/20 01:13:36 /dev/urandom 2 yes /usr/bin/dd 1000 6383
2. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6389
3. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6388
4. 07/01/20 01:16:43 /dev/urandom 2 yes /usr/sbin/sshd -1 6390
5. 07/01/20 01:16:44 /dev/urandom 2 yes /usr/sbin/sshd 1000 6408

Do disable those watches

auditctl -W /dev/random
auditctl -W /dev/urandom

Remember though that this only will capture data for system calls that aren't read/write etc. so if there is anything that already has it open, you won't see it being read.

However, I noticed (using Prometheus and node_exporter) that I was still seeing a sawtooth pattern whereby the VM (CentOS 7 with nothing to collect entropy) was reporting entropy_available raising up to nearly 200 and upon doing so would plummet back down to 0.

Does lsof (of fuser if you prefer) offer anything?

[root@metrics-d02 vagrant]# lsof /dev/random /dev/urandom
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chronyd 2184 chrony    3r   CHR    1,9      0t0 5339 /dev/urandom
tuned   2525   root    5r   CHR    1,9      0t0 5339 /dev/urandom

Note though the character device major and minor numbers; testing another way... (I'm not sure if this would be useful, just thinking in terms of things like Docker, which is not running on this VM)

[root@metrics-d02 vagrant]# ls -l /dev/*random
crw-rw-rw-. 1 root root 1, 8 Dec 19 01:24 /dev/random
crw-rw-rw-. 1 root root 1, 9 Dec 19 01:24 /dev/urandom

[root@metrics-d02 vagrant]# lsof | grep '1,[89]'
chronyd    2184           chrony    3r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525             root    5r      CHR                1,9      0t0       5339 /dev/urandom
gmain      2525  2714       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2715       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2717       root    5r      CHR                1,9      0t0       5339 /dev/urandom
tuned      2525  2754       root    5r      CHR                1,9      0t0       5339 /dev/urandom

Okay, so we have two processes, chronyd and tuned. Let's use strace. lsof told us chrony had /dev/urandom open for reading using file-discriptor 3

[root@metrics-d02 vagrant]# strace -p 2184 -f
strace: Process 2184 attached
select(6, [1 2 5], NULL, NULL, {98, 516224}
.... (I'm waiting)

So chronyd is waiting for some activity, with a timeout of 98 seconds from when it started this system call.

While I wait, I should highlight that my activity on the system is likely to create increase the kernels estimation of available random bits. (entropy_available)... so sit back and just watch the Prometheus graph...

Prometheus graph showing node_entropy_available_bits over time with descriptions

We can repeat with tuned too... (this time adding some timestamps and a grep filter just for file-descriptor 5 (the read etc. calls would have this as the first argument)

[root@metrics-d02 vagrant]# strace -p 2525 -f -tt -T 2>&1 | grep '(5,'

Red Hat have a blog that further discusses CSPRNG (Cryptographically Secure Psuedo Random Number Generator). It discusses some other ways that processes can get access to random numbers:

  • getrandom() system call <-- recommended for RHEL7.4+, high quality without blocking after entropy pool has been initialised
  • /dev/random <-- will easily block
  • /dev/urandom <-- problem when used before pool has been initiased. Will 'never block'; should be what most applications should use.
  • AT_RANDOM <-- sets 16 random bytes once at execve-time

While AT_RANDOM is not useful, it is present for every process, so just the act of starting a process should drain at least a little bit.

You'll realise now that what I've shown above using lsof is not enough, it doesn't reveal use of getrandom(). But since getrandom() is a system-call, we should be able to reveal use of it using auditctl

[root@metrics-d02 vagrant]# auditctl -a exit,always -F arch=b64 -S getrandom
[root@metrics-d02 vagrant]# auditctl -l
-a always,exit -F arch=b64 -S getrandom
[root@metrics-d02 vagrant]# tail -F -n0 /var/log/audit/audit.log 
... (now we wait)

I got bored and ssh'd into the box, and I saw a lot of interesting cool stuff, but no getrandom(), which shouldn't come as a surprise as we saw it using the /dev/urandom API earlier.

So, trying to account for the depressions in the graph, nothing is opening /dev/*random, and nothing that has it open is currently using it, and nothing seems to be calling getrandom()... Is there anything else that would consume data from the [pool behind /dev/random]? What about the kernel? Consider functionality such as Address Space Layout Randomisation (ASLR):

https://access.redhat.com/solutions/44460 [requires subscription]

[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space 
2

'2' here means that in addition to randomizing where things like mmap and stack (etc.) get loaded it will also enable heap randomization. What happens if we turn that off

[root@metrics-d02 vagrant]# echo 0 > /proc/sys/kernel/randomize_va_space
[root@metrics-d02 vagrant]# cat /proc/sys/kernel/randomize_va_space 
0

(Answer: same thing... perhaps someone else can illustrate this further)

The kernel will also be where AT_RANDOM is set. Here's a simple example which you can use strace to observe that it doesn't call /dev/*random or getrandom()

[vagrant@metrics-d02 ~]$ cat at_random.c 
#include <stdio.h>
#include <stdint.h>
#include <sys/auxv.h>

#define AT_RANDOM_LEN 16

int main(int argc, char *argv[])
{
    uintptr_t at_random;
    int i;

    at_random = getauxval(AT_RANDOM);

    for (i=0; i<AT_RANDOM_LEN; i++) {
        printf("%02x", ((uint8_t *)at_random)[i]);
    }
    printf("\n");

    /* show that it's a one-time thing */

    for (i=0; i<AT_RANDOM_LEN; i++) {
        printf("%02x", ((uint8_t *)at_random)[i]);
    }
    printf("\n");
}
[vagrant@metrics-d02 ~]$ make at_random
cc     at_random.c   -o at_random
[vagrant@metrics-d02 ~]$ ./at_random 
255f8d5711b9aecf9b5724aa53bc968b
255f8d5711b9aecf9b5724aa53bc968b
[vagrant@metrics-d02 ~]$ ./at_random 
ef4b25faf9f435b3a879a17d0f5c1a62
ef4b25faf9f435b3a879a17d0f5c1a62

Hope that's useful.

Practically, I would first look to Java workloads first as that's where I've typically been bitten by this the most. See https://blogs.oracle.com/luzmestre/why-does-my-weblogic-server-takes-a-long-time-to-start for an example.

1
  • None of which actually answers the question, which is how much entropy is being depleted by /dev/urandom. It's in the title and body of the question.
    – JdeBP
    Jan 8 '20 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.