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);