I'm confused about how sshd drops privs for incoming connections. I found this page which was very informative on a high level:


But I don't understand how the child of privileged sshd is unprivileged.

In my debug below privileged sshd is 28389 and calls clone() to create 29266, the unprivileged child. When I use ps to display the UID/EUID of the pids 29268 is UID 1002 as expected, but 29266, the unprivileged child of sshd, is zero, which seems to contradict the link above which says 'This is achieved by changing its uid/gid to an unused user'.

woOt@host:~$ sudo strace -p 28389 -e trace=clone
Process 28389 attached - interrupt to quit
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb7076d5a90) = 29266
^CProcess 28389 detached
woOt@host:~$ ps auxf | grep sshd
root     28389  0.0  0.0  49944  1244 ?        Ss   18:15   0:00 /usr/sbin/sshd
root     29266  0.0  0.2  54576  3308 ?        Ss   18:37   0:00  \_ sshd: test [priv]
test     29268  0.0  0.0  54576  1440 ?        S    18:37   0:00      \_ sshd: test@pts/2
woOt@host:~$ ps -eo pid,uid,euid | egrep 'PID|28389|29266|29268'
28389     0     0
29266     0     0
29268  1002  1002
woOt@host:~$ grep 1002 /etc/passwd

edited question to correctly illustrate:

unprivileged child (2406) of monitor process (2405)

root      2370  0.0  1.1  55592  5524 ?        Ss   00:12   0:00 /usr/sbin/sshd -D
root      2405  0.0  1.1  59008  5720 ?        Ss   00:12   0:00  \_ sshd: test [priv]
sshd      2406  0.0  0.6  56936  3072 ?        S    00:12   0:00      \_ sshd: test [net]

and user privileged child (2419) of monitor process post-auth:

root      2370  0.0  1.1  55592  5524 ?        Ss   00:12   0:00 /usr/sbin/sshd -D
root      2405  0.0  1.1  60224  5756 ?        Ss   00:12   0:00  \_ sshd: test [priv]
test      2419  0.0  0.7  60224  3888 ?        S    00:12   0:00      \_ sshd: test@pts/1

appreciate the answers, thanks

2 Answers 2


29266, the unprivileged child

This one is the privileged one, as the process title shows sshd: test [priv], the 29268 is unprivileged postauth child (user is already test instead of root).

But the main place where you can use privsep is before authentication:

root     11759  0.0  0.0  69928  6056 ?        Ss   Feb07   0:00 /usr/sbin/sshd -D
root     10071  0.2  0.0 119280  7096 ?        Ss   10:56   0:00  \_ sshd: unknown [priv]
sshd     10072  0.2  0.0  71272  3016 ?        S    10:56   0:00      \_ sshd: unknown [net] 

There you see the privileged process running under root privileges (10071) and net-child (sshd: user [net], running under sshd user, and usually under some sandbox which prevents most of the privilege escalation attacks, it there was a hole in the code.

So as already mentioned by tylerl, or you setuid is used to drop/change privileges from root to sshd or your user. But note that you need to point out to the correct process when trying to understand this constellation. Image is usually more than thousands words:


Where in the image corresponding to your example:

  • the first privileged is sshd daemon (your pid 28389)
  • the second one privileged is monitor (your pid 29266)
  • you don't have in your ps unprivileged network child (mind pid 10072)
  • the user privileged is child (your pid 29268)
  • Hey @Jakuje, I see my error, I missed the monitor process step, thanks for the explanation!
    – woOt
    Mar 27, 2016 at 11:26
  • Though the PID of the unprivileged child isn't mentioned in the question we can deduce what it must have been since there is only one possible number between 29266 and 29268.
    – kasperd
    Mar 27, 2016 at 13:20
  • @kasperd you can infer it yes, but it was important that Jakuje pointed it out as I had missed it.
    – woOt
    Mar 29, 2016 at 0:31
  • Follow up question (I know it has been some time): When running sshd from the command line on ubuntu (sudo /usr/sbin/sshd), it complains: "Missting privilege separation direcoty". This directory, as far as I can see is created in /etc/init.d/ssh. There is a function called check_privsep_dir, that does just that. After creating this folder manually, sshd can run from the command line. My question, however, is: Why this folder is necessary? how is it used? As far as I can see, I see no file in it. My question, however, is why this folder is necessary?
    – Uri
    Sep 24, 2019 at 17:38
  • 1
    @Uri that directory is used for privilege separation to limit what the unprivileged network child can do in case of bug, that would allow the attacker to gain the access of the process or execute arbitrary commands from it. This process is chrooted to the empty directory, which means it really does not see anything on the real filesystem.
    – Jakuje
    Sep 24, 2019 at 19:49

Here's how you do it:

You start out with a parent process, running as root.

That process forks itself, creating two identical clones, only one of them is the parent and one is the child (fork returns the child's PID for the parent process, and 0 for the child). NB: fork is the libc function name, under the hood it calls clone which is the syscall provided by the kernel.

In the child, you next perform any privileged operations that need to happen, setting up the environment as desired.

Once all the prep work is done, the child process calls setuid (actually probably some combination of setreuid setregid and possibly a few other calls) to switch to the UID/GID of the new unprivileged process owner.

Lastly, the child calls exec (probably execle or similar) to run whatever program the child is supposed to be executing, replacing the current process space with the new one, though keeping the same UID/GID/PID that the child process had before.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.