]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
randutils: Keep track of randomness source
authorTobias Stoeckmann <tobias@stoeckmann.org>
Sat, 28 Mar 2026 15:37:15 +0000 (16:37 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 15 Apr 2026 10:15:55 +0000 (12:15 +0200)
The mcookie utility wants to report the source of randomness, but even
prints getrandom if it failed to retrieve data through it.

Fix this modifying the return data type of ul_random_get_bytes. Instead
of returning a boolean, the actual source is returned. This avoids any
potential TOCTOU or erroneous output.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
include/randutils.h
lib/randutils.c
libuuid/src/gen_uuid.c
misc-utils/mcookie.c

index bcea43df7e8831cfa721a48b569a12ae215f0737..e67745482aba6b9639dc15ca770e2d0c40823872 100644 (file)
@@ -4,8 +4,16 @@
 #ifndef UTIL_LINUX_RANDUTILS
 #define UTIL_LINUX_RANDUTILS
 
+/* command flags */
+typedef enum {
+       UL_RAND_WEAK = 0,       /* computed with libc functionality */
+       UL_RAND_GETRANDOM,      /* retrieved from getrandom(2) */
+       UL_RAND_RANDOM,         /* read from /dev/random */
+       UL_RAND_URANDOM         /* read from /dev/urandom */
+} ul_random_src_t;
+
 /* getrandom(2) based with fallback to /dev/(u)random and libc randomness */
-extern int ul_random_get_bytes(void *buf, size_t nbytes);
-extern const char *random_tell_source(void);
+extern ul_random_src_t ul_random_get_bytes(void *buf, size_t nbytes);
+extern const char *ul_random_tell_source(ul_random_src_t);
 
 #endif
index 155eded76f9cb90c29db8dd05908011b720b3cd3..ae6ee27ad529384f955f138dc67232e03708a1cc 100644 (file)
@@ -73,13 +73,16 @@ static void crank_random(void)
                rand();
 }
 
-static int random_get_fd(void)
+static int random_get_fd(ul_random_src_t *src)
 {
        int fd;
 
+       *src = UL_RAND_URANDOM;
        fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
-       if (fd == -1)
+       if (fd == -1) {
+               *src = UL_RAND_RANDOM;
                fd = open("/dev/random", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+       }
        crank_random();
        return fd;
 }
@@ -95,12 +98,13 @@ static int random_get_fd(void)
 /*
  * Write @nbytes random bytes into @buf.
  *
- * Returns 0 for good quality of random bytes or 1 for weak quality.
+ * Returns source of random bytes (0 for weak quality).
  */
-int ul_random_get_bytes(void *buf, size_t nbytes)
+ul_random_src_t ul_random_get_bytes(void *buf, size_t nbytes)
 {
        unsigned char *cp = (unsigned char *)buf;
        size_t i, n = nbytes;
+       ul_random_src_t src;
        int lose_counter = 0;
 
 #ifdef HAVE_GETRANDOM
@@ -123,6 +127,8 @@ int ul_random_get_bytes(void *buf, size_t nbytes)
                } else
                        break;
        }
+       if (n == 0)
+               return UL_RAND_GETRANDOM;
 
        if (errno == ENOSYS)
 #endif
@@ -132,7 +138,7 @@ int ul_random_get_bytes(void *buf, size_t nbytes)
         * as before
         */
        {
-               int fd = random_get_fd();
+               int fd = random_get_fd(&src);
 
                lose_counter = 0;
                if (fd >= 0) {
@@ -151,6 +157,8 @@ int ul_random_get_bytes(void *buf, size_t nbytes)
 
                        close(fd);
                }
+               if (n == 0)
+                       return src;
        }
        /*
         * We do this all the time, but this is the only source of
@@ -173,30 +181,33 @@ int ul_random_get_bytes(void *buf, size_t nbytes)
        }
 #endif
 
-       return n != 0;
+       return UL_RAND_WEAK;
 }
 
 
 /*
  * Tell source of randomness.
  */
-const char *random_tell_source(void)
+const char *ul_random_tell_source(ul_random_src_t src)
 {
-#ifdef HAVE_GETRANDOM
-       return _("getrandom() function");
-#else
-       size_t i;
-       static const char *const random_sources[] = {
-               "/dev/urandom",
-               "/dev/random"
-       };
-
-       for (i = 0; i < ARRAY_SIZE(random_sources); i++) {
-               if (!access(random_sources[i], R_OK))
-                       return random_sources[i];
+       const char *s;
+
+       switch (src) {
+       case UL_RAND_GETRANDOM:
+               s = _("getrandom() function");
+               break;
+       case UL_RAND_RANDOM:
+               s = "/dev/random";
+               break;
+       case UL_RAND_URANDOM:
+               s = "/dev/urandom";
+               break;
+       default:
+               s = _("libc pseudo-random functions");
+               break;
        }
-#endif
-       return _("libc pseudo-random functions");
+
+       return s;
 }
 
 #ifdef TEST_PROGRAM_RANDUTILS
index 13d6ecbde1246842e69102bd86b16a97da04c555..4cc32e964aadd188a947d477873b4ec1a5f9cdd0 100644 (file)
@@ -759,7 +759,7 @@ int __uuid_generate_random(uuid_t out, int *num)
                n = *num;
 
        for (i = 0; i < n; i++) {
-               if (ul_random_get_bytes(buf, sizeof(buf)))
+               if (ul_random_get_bytes(buf, sizeof(buf)) == UL_RAND_WEAK)
                        r = -1;
                uuid_unpack(buf, &uu);
 
index c837fb39ce9e828b6d1dc0f83d6c237cba801b32..38b17d394370b609de6b5e53846ce6ad5b5c693f 100644 (file)
@@ -143,6 +143,7 @@ int main(int argc, char **argv)
        unsigned char digest[UL_MD5LENGTH];
        unsigned char buf[RAND_BYTES];
        int c;
+       ul_random_src_t src;
 
        static const struct option longopts[] = {
                {"file", required_argument, NULL, 'f'},
@@ -189,12 +190,12 @@ int main(int argc, char **argv)
        randomness_from_files(&ctl);
        free(ctl.files);
 
-       ul_random_get_bytes(&buf, RAND_BYTES);
+       src = ul_random_get_bytes(&buf, RAND_BYTES);
        ul_MD5Update(&ctl.ctx, buf, RAND_BYTES);
        if (ctl.verbose)
                fprintf(stderr, P_("Got %d byte from %s\n",
                                   "Got %d bytes from %s\n", RAND_BYTES),
-                               RAND_BYTES, random_tell_source());
+                               RAND_BYTES, ul_random_tell_source(src));
 
        ul_MD5Final(digest, &ctl.ctx);
        for (i = 0; i < UL_MD5LENGTH; i++)