[sshd] Clean up children before exiting

Fixed: b/337122544
Change-Id: I76e9c1ad2c17ec2f24e7b9de6639218e8fe41ae7
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/openssh-portable/+/1041518
Reviewed-by: Suraj Malhotra <surajmalhotra@google.com>
Reviewed-by: Steven Grady <slgrady@google.com>
Commit-Queue: Casey Dahlin <sadmac@google.com>
diff --git a/fuchsia/fuchsia-compat.c b/fuchsia/fuchsia-compat.c
index 6049873..3d29870 100644
--- a/fuchsia/fuchsia-compat.c
+++ b/fuchsia/fuchsia-compat.c
@@ -24,13 +24,14 @@
 #include <lib/fdio/unsafe.h>
 #include <lib/zircon-internal/paths.h>
 #include <threads.h>
+#include <zircon/process.h>
 #include <zircon/processargs.h>
 #include <zircon/status.h>
 #include <zircon/syscalls.h>
 #include <zircon/syscalls/port.h>
 
-#include "includes.h"
 #include "fuchsia/loader-wrapper.h"
+#include "includes.h"
 #include "misc.h"
 #include "openbsd-compat/bsd-misc.h"
 #include "xmalloc.h"
@@ -38,6 +39,40 @@
 static async_loop_t* loop;
 static thrd_t loop_thread;
 static loader_service_t* ldsvc;
+static zx_handle_t container_job = ZX_HANDLE_INVALID;
+
+static void cleanup_container_job(void) {
+  if (container_job == ZX_HANDLE_INVALID) {
+    return;
+  }
+
+  if (zx_task_kill(container_job) != ZX_OK) {
+    fprintf(stderr, "warning: failed to kill container job on shutdown\n");
+    return;
+  }
+
+  zx_time_t now = zx_clock_get_monotonic();
+  zx_signals_t observed;
+  if (zx_object_wait_one(container_job, ZX_JOB_TERMINATED, now + ZX_SEC(5), &observed) ==
+      ZX_ERR_TIMED_OUT) {
+    fprintf(stderr, "warning: timed out waiting for container job to terminate\n");
+  }
+}
+
+static zx_handle_t get_container_job(void) {
+  if (container_job != ZX_HANDLE_INVALID) {
+    return container_job;
+  }
+
+  if (zx_job_create(zx_job_default(), 0, &container_job) != ZX_OK) {
+    fprintf(stderr, "fatal: failed to create job to contain ssh processes\n");
+    exit(1);
+  }
+
+  atexit(cleanup_container_job);
+
+  return container_job;
+}
 
 async_dispatcher_t* get_async() { return async_loop_get_dispatcher(loop); }
 
@@ -231,7 +266,7 @@
   };
 
   uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_UTC_CLOCK;
-  return fdio_spawn_etc(ZX_HANDLE_INVALID, flags, argv[0], argv, (const char* const*)env, 4,
+  return fdio_spawn_etc(get_container_job(), flags, argv[0], argv, (const char* const*)env, 4,
                         actions, proc, err_msg);
 }