ControlMaster cwd is not /

raf ssh at
Fri Apr 9 16:48:21 AEST 2021

On Fri, Apr 09, 2021 at 02:31:14PM +0930, David Newall <openssh at> wrote:

> Just like stdout, stderr is essential for programs that the user runs on the
> remote machine.  Please don't close it unless and until the user does (e.g.
> ssh remote 'exec command 2>&-')

This is referring to the stderr of a separate process
to the main ssh process. When ControlMaster is in use,
and ssh is used to make a connection to a remote host,
a separate daemon/background process is started that
listens for subsequent attempts to connect to the same
remote host with ssh. It listens to a control socket
for a certain time period. This enables subsequent
connections to the same remote host to start up much
more quickly by re-using the setup work done by the
first connection rather than performing the same setup
work for every connection.

It's the stderr of that second daemon/background
process that gets closed, not the stderr of the primary
ssh process that makes the initial connection to the
remote host in question. It's only the primary ssh
process that is communicating with the remote host
(from the user's point of view), and therefore needs
its stdout and stderr to remain open, and they will
remain open even if the (duplicate) stderr of the
second daemon/background process is closed.

The closing of stderr in the daemon/background process
that listens to the control socket is already
happening, and has been happening for years. This
discussion does not affect that. It is only about
making the secondary daemon/background process also
change its current working directory to the root
directory (/), rather than leaving it as whatever
directory the user was in when starting the initial ssh
process, so as to prevent hampering a subsequent umount
of the file system that contains that current working

This change means that if the user's current working
directory was in a temporary file system such as a
removable USB stick, or an encrypted file system, and
the user subsequently wants to umount that
corresponding file system, the operating system won't
allow it if there are any processes that are still
using the file system.

When the daemon/background process's current working
directory is in the file system that the user wants to
umount, they won't be able to do so until they have
identified the daemon/background process and terminated
it manually. If that process had changed its working
directory to the root directory, then the umount would
just work.

It's normal practice for daemon processes to change
their current working directory to the root directory
for this reason, but ssh's secondary daemon/background
process that listens to the control socket doesn't do
this. I don't think that there was any particularly
good reason for this. It was probably just to minimise
the change to the ssh code when the call to daemon()
was introduced. Before the introduction of the call to
daemon(), there was no chdir(), so when daemon() was
added, it was called in a way that also didn't do a
chdir() (even though that isn't normal practice for
daemon processes). But a chdir() at that point would be
an improvement.


More information about the openssh-unix-dev mailing list