]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ptyfwd: Imply PTY_FORWARD_READ_ONLY if stdin isn't readable
authorDaan De Meyer <daan@amutable.com>
Wed, 20 May 2026 12:14:52 +0000 (12:14 +0000)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 20 May 2026 16:04:13 +0000 (18:04 +0200)
if stdin is connected to a closed pipe or similar, imply
PTY_FORWARD_READ_ONLY so we don't even try to read from it
in the first place. Otherwise we'll immediately get a hangup
which will cause the forwarder to call sd_event_exit() and
shut down the event loop.

Debugged-by: Christian Brauner <brauner@kernel.org>
src/shared/ptyfwd.c

index 88cfd596d050828d78135c039c94a95fc1b1077c..fcc1500dc5c8bd91a8c918cf5b4f8a1d2d591aa0 100644 (file)
@@ -934,6 +934,24 @@ int pty_forward_new(
         assert(master >= 0);
         assert(ret);
 
+        if (!FLAGS_SET(flags, PTY_FORWARD_READ_ONLY)) {
+                /* If stdin isn't actually opened for reading, or refers to the read end of a pipe (or
+                 * socket) whose peer has already hung up, then there's nothing for us to forward — imply
+                 * read-only mode. */
+                r = RET_NERRNO(fcntl(STDIN_FILENO, F_GETFL));
+                if (r < 0 && r != -EBADF)
+                        return log_debug_errno(errno, "Failed to query stdin flags: %m");
+                if (r == -EBADF || (r & O_ACCMODE_STRICT) == O_WRONLY)
+                        flags |= PTY_FORWARD_READ_ONLY;
+                else {
+                        r = pipe_eof(STDIN_FILENO);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to check whether stdin is at EOF, ignoring: %m");
+                        else if (r > 0)
+                                flags |= PTY_FORWARD_READ_ONLY;
+                }
+        }
+
         f = new(PTYForward, 1);
         if (!f)
                 return -ENOMEM;