From 97f7fe658d03c3a846d0aca004ba21e1a3f81799 Mon Sep 17 00:00:00 2001 From: Joshua Rogers Date: Sun, 12 Oct 2025 21:52:21 +0800 Subject: [PATCH] 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 --- crypto/rand/rand_egd.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c index f44b38d1a9..362cbeda2c 100644 --- a/crypto/rand/rand_egd.c +++ b/crypto/rand/rand_egd.c @@ -110,10 +110,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. */ @@ -128,9 +128,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 (;;) { @@ -173,6 +172,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; @@ -182,6 +189,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) @@ -198,6 +208,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; }