Commit e6aabdfb45 for openssl.org

commit e6aabdfb452de672f5c25ffc490ba35b82c6db76
Author: Joshua Rogers <MegaManSec@users.noreply.github.com>
Date:   Sun Oct 12 21:52:21 2025 +0800

    rand_egd: harden EGD I/O and bounds; defer fdopen until post connect

    Tighten RAND_query_egd_bytes and fix edge cases:

    * Reject nonpositive request sizes to avoid wrap when storing the
      length byte in tempbuf[1].
    * Treat server length byte as untrusted; bound by the requested size
      and by sizeof(tempbuf) to avoid overrunning caller or stack buffers.
    * Defer fdopen until after a successful connect. On HPE NonStop
      (OPENSSL_SYS_TANDEM) the connect retry path may swap the socket fd;
      creating the FILE* early could leave a stale stream pointing at a
      closed descriptor, causing EBADF or short I/O, and leaking the new
      socket. Creating the stream after connect avoids this.
    * Initialize fd to -1 and close the raw fd when fdopen fails; ensure
      we close either FILE* or the raw fd on all error paths.
    * Remove unused code.

    Behavior is unchanged on platforms that do not swap fds during connect.
    On TANDEM it prevents stale I/O and descriptor leaks. Overall this
    improves robustness and bounds checking for EGD interactions.

    Signed-off-by: Joshua Rogers <MegaManSec@users.noreply.github.com>

    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    Reviewed-by: Neil Horman <nhorman@openssl.org>
    MergeDate: Thu Mar 12 17:58:21 2026
    (Merged from https://github.com/openssl/openssl/pull/28905)

diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c
index ba8aa34dc2..6513f4e557 100644
--- a/crypto/rand/rand_egd.c
+++ b/crypto/rand/rand_egd.c
@@ -108,10 +108,10 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 {
     FILE *fp = NULL;
     struct sockaddr_un addr;
-    int mybuffer, ret = -1, i, numbytes, fd;
+    int mybuffer, ret = -1, i, numbytes, fd = -1;
     unsigned char tempbuf[255];

-    if (bytes > (int)sizeof(tempbuf))
+    if (bytes <= 0 || bytes > (int)sizeof(tempbuf))
         return -1;

     /* Make socket. */
@@ -126,9 +126,8 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 #else
     fd = socket(AF_UNIX, SOCK_STREAM, 0);
 #endif
-    if (fd == -1 || (fp = fdopen(fd, "r+")) == NULL)
+    if (fd == -1)
         return -1;
-    setbuf(fp, NULL);

     /* Try to connect */
     for (;;) {
@@ -171,6 +170,14 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
         }
     }

+    /* Create stream only after a successful connect to avoid stale FILE* on fd swap. */
+    fp = fdopen(fd, "r+");
+    if (fp == NULL) {
+        close(fd);
+        return -1;
+    }
+    setbuf(fp, NULL);
+
     /* Make request, see how many bytes we can get back. */
     tempbuf[0] = 1;
     tempbuf[1] = bytes;
@@ -180,6 +187,9 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
         goto err;
     numbytes = tempbuf[0];

+    if (numbytes <= 0 || numbytes > bytes || numbytes > (int)sizeof(tempbuf))
+        goto err;
+
     /* Which buffer are we using? */
     mybuffer = buf == NULL;
     if (mybuffer)
@@ -196,6 +206,8 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes)
 err:
     if (fp != NULL)
         fclose(fp);
+    else if (fd != -1)
+        close(fd);
     return ret;
 }