sshd -i always exiting with exit status 255

Damien Miller djm at mindrot.org
Mon May 27 12:17:04 AEST 2024


On Fri, 24 May 2024, Donald Buczek wrote:

> Hi,
> 
> I've created a tool which utilizes sshd to enable users to get an interactive
> session on a Linux compute cluster. The tool submits a wrapper into the
> cluster. This wrapper creates the listen socket on a dynamic port number,
> accepts a connection on that socket and then calls sshd in inetd mode with
> '-i'. Everything works fine and as intended.
> 
> However, there is one nuisance: I've noticed that sshd always terminates with
> exit status 255 even if the interactive session is closed normally. Because of
> this I can't just exec() sshd from the wrapper as its last step, but need to
> fork sshd, wait for it, ignore its exit status and exit the wrapper with exit
> status 0 to communicate a normal exit to the cluster scheduler. This could
> cover real and unexpected errors.
> 
> I've used gdbserver to attach to the sshd process, so I can tell that the exit
> status of the main (the "privileged" process?) of sshd originates in
> mm_request_receive from the EPIPE errno check:
> 
> void
> mm_request_receive(int sock, struct sshbuf *m)
> {
>     u_char buf[4], *p = NULL;
>     u_int msg_len;
>     int r;
> 
>     debug3_f("entering");
> 
>     if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
>         if (errno == EPIPE)
>             cleanup_exit(255);
>         fatal_f("read: %s", strerror(errno));
>     }
> 
> Questions:
> 
> - Is this the expected exit point of `sshd -i` ?
> - If so, is there a reason to return a failure exit status?

No, it's probably that nobody has checked it before. This might help:


diff --git a/packet.c b/packet.c
index beb214f99..7d02379bd 100644
--- a/packet.c
+++ b/packet.c
@@ -1909,7 +1909,8 @@ sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap)
 		    ssh->state->server_side ? "from" : "to", remote_id);
 	case SSH_ERR_DISCONNECTED:
 		ssh_packet_clear_keys(ssh);
-		logdie("Disconnected from %s", remote_id);
+		logit("Disconnected from %s", remote_id);
+		cleanup_exit(0);
 	case SSH_ERR_SYSTEM_ERROR:
 		if (errno == ECONNRESET) {
 			ssh_packet_clear_keys(ssh);


More information about the openssh-unix-dev mailing list