From 2618ffbe19d9d68d40f6d0b918a4673255bff60d Mon Sep 17 00:00:00 2001 From: Peter Volkov Date: Sat, 25 Jul 2026 15:23:27 +0300 Subject: [PATCH] openrc: avoid converting failed PTY reads to size_t openrc-run and rc_logger used read()'s return value as a size_t without checking for errors. Since read() returns an ssize_t, a failure return value -1 was converted to SIZE_MAX. This path was normally hidden because the reader processes retained slave_tty, preventing the master from reporting a hangup. However, read() may still fail for other reasons, so handle its result explicitly. With this path handled, it is also safe to close the unused slave_tty descriptors. --- src/openrc-run/openrc-run.c | 22 +++++++++++++++-- src/openrc/rc-logger.c | 48 ++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/openrc-run/openrc-run.c b/src/openrc-run/openrc-run.c index 380d4c7f9..39a84d1a7 100644 --- a/src/openrc-run/openrc-run.c +++ b/src/openrc-run/openrc-run.c @@ -416,6 +416,11 @@ svc_exec(const char *command) return 1; } + if (slave_tty >= 0) { + close(slave_tty); + slave_tty = -1; + } + posix_spawn_file_actions_destroy(&tty); free(openrc_sh); @@ -432,9 +437,22 @@ svc_exec(const char *command) break; } - if (fd[1].revents & (POLLIN | POLLHUP)) { + if (master_tty >= 0 && + (fd[1].revents & (POLLIN | POLLHUP))) { char buffer[BUFSIZ]; - write_prefix(buffer, read(master_tty, buffer, BUFSIZ), &prefixed); + ssize_t bytes; + + bytes = read(master_tty, buffer, BUFSIZ); + if (bytes > 0) + write_prefix(buffer, (size_t)bytes, &prefixed); + else if (bytes == 0 || + (bytes == -1 && errno != EINTR)) { + if (bytes == -1 && errno != EIO) + eerror("%s: read: %s", applet, strerror(errno)); + close(master_tty); + master_tty = -1; + fd[1].fd = -1; + } } /* signal_pipe receives service_pid's exit status */ diff --git a/src/openrc/rc-logger.c b/src/openrc/rc-logger.c index e57d38037..f90286c8b 100644 --- a/src/openrc/rc-logger.c +++ b/src/openrc/rc-logger.c @@ -155,6 +155,7 @@ rc_logger_open(const char *level) struct pollfd fd[2]; int s = 0; size_t bytes; + ssize_t bytes_read; FILE *log = NULL; FILE *plog = NULL; const char *logfile; @@ -191,6 +192,8 @@ rc_logger_open(const char *level) rc_in_logger = true; close(signal_pipe[1]); signal_pipe[1] = -1; + close(slave_tty); + slave_tty = -1; runlevel = level; xasprintf(&tmplog, "%s/rc.log", rc_svcdir()); @@ -217,25 +220,36 @@ rc_logger_open(const char *level) } else if (s == 0) continue; - if (fd[1].revents & (POLLIN | POLLHUP)) { + if (rc_logger_tty >= 0 && + (fd[1].revents & (POLLIN | POLLHUP))) { memset(buffer, 0, BUFSIZ); - bytes = read(rc_logger_tty, buffer, BUFSIZ); - if (write(STDOUT_FILENO, buffer, bytes) == -1) - eerror("write: %s", strerror(errno)); - - if (log) - write_log(fileno (log), buffer, bytes); - else { - if (logbuf_size - logbuf_len < bytes) { - logbuf_size += BUFSIZ * 10; - logbuf = xrealloc(logbuf, - sizeof(char ) * - logbuf_size); + bytes_read = read(rc_logger_tty, buffer, BUFSIZ); + if (bytes_read > 0) { + bytes = (size_t)bytes_read; + if (write(STDOUT_FILENO, buffer, bytes) == -1) + eerror("write: %s", strerror(errno)); + + if (log) + write_log(fileno (log), buffer, bytes); + else { + if (logbuf_size - logbuf_len < bytes) { + logbuf_size += BUFSIZ * 10; + logbuf = xrealloc(logbuf, + sizeof(char ) * + logbuf_size); + } + + memcpy(logbuf + logbuf_len, + buffer, bytes); + logbuf_len += bytes; } - - memcpy(logbuf + logbuf_len, - buffer, bytes); - logbuf_len += bytes; + } else if (bytes_read == 0 || + (bytes_read == -1 && errno != EINTR)) { + if (bytes_read == -1 && errno != EIO) + eerror("read: %s", strerror(errno)); + close(rc_logger_tty); + rc_logger_tty = -1; + fd[1].fd = -1; } }