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;
}