OpenBSD Journal

sshd(8) split into multiple binaries

Contributed by rueda on from the puffy-does-the-splits dept.

With the following commit, Damien Miller (djm@) commenced the process of splitting sshd(8) into multiple binaries:

Module name:	src
Changes by:	2024/05/16 18:30:24

Modified files:
	usr.bin/ssh    : Makefile auth-rhosts.c auth.c 
	                 auth.h auth2-gss.c auth2-hostbased.c 
	                 auth2-kbdint.c auth2-none.c auth2-passwd.c 
	                 auth2-pubkey.c auth2.c channels.c kex.c kex.h 
	                 kexgexs.c misc.c misc.h monitor.c monitor.h 
	                 monitor_wrap.c monitor_wrap.h msg.c packet.c 
	                 packet.h pathnames.h servconf.c servconf.h 
	                 serverloop.c session.c ssh_api.c sshd.c 
	usr.bin/ssh/sshd: Makefile 
Added files:
	usr.bin/ssh    : sshd-session.c 
	usr.bin/ssh/sshd-session: Makefile 

Log message:
Start the process of splitting sshd into separate binaries. This step
splits sshd into a listener and a session binary. More splits are
After this changes, the listener binary will validate the configuration,
load the hostkeys, listen on port 22 and manage MaxStartups only. All
session handling will be performed by a new sshd-session binary that the
listener fork+execs.

This reduces the listener process to the minimum necessary and sets us
up for future work on the sshd-session binary.

feedback/ok markus@ deraadt@

NB. if you're updating via source, please restart sshd after installing,
otherwise you run the risk of locking yourself out.
(Note the final paragraph in the commit message.)

With a single ssh client session, we now see:

$ pgrep -fl sshd 
20045 sshd-session: rueda@ttypb
15348 sshd-session: rueda [priv]
10510 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups

Previously, the "ssh-session" processes would have been "sshd".

The new sshd-session joins the ranks of binaries relinked on boot.

Security engineering work on OpenSSH is always pleasing. It will be interesting to see whether the developers will make similar changes to other daemons in the OpenBSD base system.

(Comments are closed)

  1. By Anonymous Coward ( on

    I'm curious about what the rationale behind splitting into separate binaries vs just forking separate processes, especially if you can't have one without the other anyway. Is there some security advantage to it? Ease of maintenance?

    Not a complaint, but I am designing some software that needs privsep which currently uses fork() to fork itself and pledge() in each process.

    I wish there was a better way to run different processes than fork/exec though, like the Windows CreateProcess[Ex]() function. There's posix_spawn() but that's just fork/exec in disguise. It seems pointless to fork a process with an identical copy of itself only for it to be replaced almost immediately with a totally new process.

    1. By Anonymous Coward ( on

      To clarify, i'm wondering if I would be better off separating things into separate binaries or just keep it all in the one binary.

      1. By System Operator ( on

        It depends. On your goals and objectives. On your design specification. On your intended isolation/separation.
        If you want better control separate more. That is how it's done for server programming and system programming.
        System programming requires better instantiation and generality for services provisioning for other processes.

        On the Windows point, definitely NO such thing in UNIX. Windows started as a very different system that's down
        stream of UNIX and UNIX-like systems. DOS/WIN took deliberately different and very incompatible decisions.. in
        every step as any other consumer single user system, over decades of cruft accumulation. That long deviance is
        largely irrelevant and counter-obstructive to the UNIX process model and multitasking in general.. Eventually,
        DOS/WIN really does become much more UNIX-like all the time & can break its backward compatibility internally,
        UNIX however is not an experimental consumer appliance so can't do that. UNIX had more in the very early days.

        The premises of these classes of operating systems are very different in goals and objectives so no way there.
        Yes, do separate and it complicates your design for small application programming, system programming is more.
        More important and more utilised and more critical and more evolved and more elaborate, in these finer points.

        What you're not understanding so far is that programs have different functional separation for logic and data,
        as grouped and common sections by activity routines and data structures. More complex server applications need
        to have these separated. For accessing operating system premises independently, for separation and throughput.

        The classic example is email servers. On the generic side, separation is modularity & reusability, componentry
        and thus solves many problems, by abstraction and better modeling. It is how you overcome the software crisis:

        Of course, process creation and destruction is expensive.. so is resource allocation in application space too.
        That's why server applications are resident and have various modes of pre-forking and worker threads. That can
        be separated as runtimes if they need not be the same.. they are typically not as a design and implementation.
        Remember system programming has very different requirements to application programming in every design aspect.

        Applications can and often take roles as intermediary dispatchers between the OS kernel and their subset tasks
        effectively creating a system within a system with partial system capability. That is overhead and bad design.
        The classic example is office/web client applications, as large monolithic monster binaries of many small and
        badly abstracted subprograms bundled together, resulting in horrific very irreparable damaging overhead waste.

        With the design of systems for modular-composable function blocks these systems engineering principles emerge.

        There is more than one way to do application and systems programming, there is only one direction to improve..

        1. By System Operator ( on

          Separation is also classification, as classifier system of intended purpose and compute execution delineation.
          It's specialisation & narrowing of the focus of program operation, reduces to functional block modular design.

          That is easier to work on independently, and avoids programmer and specification errors. Results are precision
          of separate control, operation and data planes, splits the horizon (scope) of shared data and logic functions.

          It's also a very efficient strategy for both performance and parallelism, and interception damages containment
          for remotely accessed sides becoming thus isolated from the other processing and control areas. That's modern,
          provides for easier applied use of capability, role and access normalisation and segmented framework measures.

          As a final gift which comes free from the clarity and definitions, refactoring and reorganisation for the data
          structures and logic model and state machines and feature augmentation become much more feasible & accessible.
          The end result is a much more comprehensible and fundamentally understandable design, which confirms validity.

          The specification can then be derived, inferred and verified by observability, and worked on in the long term.
          That benefits the documentation legibility and program functionality mental oversight, improving vastly usage!

          See the list of ideas & applied use of research publication in OpenBSD

          1. By Ted Bullock ( on

            This might be the least useful bit of technical hieroglyphic writing I've ever read.

            You didn't even attempt to answer the question and then ventured on a quest into some sort of parallel dimension.

            1. By System Operator ( on

              Read it again then. Yes.. Really. Read it again multiple times. You will understand it.. It is very important.
              It answers and explains the complete theoretic rationale. It is to the point. Precise and sharp, enthusiastic.
              By all means, if you disagree with the details, provide counter arguments. The berating remark is discarded...
              It's not even worth the time to reply to weak and pointless disqualification low effort trials which are spam.

    2. By Anonymous Cowherd (anonymouse) on

      One advantage of splitting out to separate binaries means they can link against different libraries (for example, if authentication requires use of a library, you may be able to avoid having that library loaded into the address space of a network-facing process). Another is that, it restricts the amount of code reachable, which may help with control flow attacks.

      Fork and exec (even when it's just executing the same process) can be pretty useful: it rolls the dice again for ASLR, but allows FDs to be passed across as a communications mechanism.


Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]