From: Joshua Rogers Date: Sun, 12 Oct 2025 13:52:21 +0000 (+0800) Subject: rand_egd: harden EGD I/O and bounds; defer fdopen until post connect X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e6aabdfb452de672f5c25ffc490ba35b82c6db76;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Eugene Syromiatnikov Reviewed-by: Tomas Mraz Reviewed-by: Neil Horman 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 ba8aa34dc20..6513f4e557f 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; }