diff --git a/src/boot.c b/src/boot.c index 5e2ef245..65fcdc34 100644 --- a/src/boot.c +++ b/src/boot.c @@ -187,8 +187,9 @@ int internal_boot(struct ds_config *cfg) { return -1; } - /* Detect init system once - used for seccomp and cgroup setup */ - int is_systemd = is_systemd_rootfs(cfg->rootfs_path); + /* Init family was classified before fork in start_rootfs(). + * Boot-time setup only needs to know whether that family is systemd. */ + int is_systemd = (cfg->init_type == DS_INIT_SYSTEMD); /* 3. Setup volatile overlay INSIDE the container's mount namespace. * This MUST happen here (not in parent) so the overlay's connection to diff --git a/src/container.c b/src/container.c index 68f5e729..692111c8 100644 --- a/src/container.c +++ b/src/container.c @@ -224,6 +224,7 @@ static void cleanup_container_resources(struct ds_config *cfg, pid_t pid, * so start_rootfs() can detect the existing mount and reuse it. */ if (!skip_unmount) { remove_mount_path(cfg->pidfile); + remove_init_type(cfg->pidfile); if (cfg->pidfile[0]) unlink(cfg->pidfile); if (global_pidfile[0] && strcmp(cfg->pidfile, global_pidfile) != 0) @@ -436,6 +437,11 @@ int start_rootfs(struct ds_config *cfg) { unmount_rootfs_img(cfg->img_mount_point, cfg->foreground); return -1; } + + /* Classify the container init family while the normalized host rootfs + * path is already in scope. Detecting here avoids rebuilding the same + * probe path later solely for shutdown metadata. */ + cfg->init_type = detect_container_init(rootfs_norm); } /* 2b. Android Termux Bridge Preparation - only if flag is set */ @@ -1136,6 +1142,9 @@ int start_rootfs(struct ds_config *cfg) { if (cfg->is_img_mount) save_mount_path(cfg->pidfile, cfg->img_mount_point); + /* Also save init type */ + save_init_type(cfg->pidfile, cfg->init_type); + /* 11. Foreground or background finish */ if (cfg->foreground) { @@ -1261,8 +1270,13 @@ int stop_rootfs(struct ds_config *cfg, int skip_unmount) { ds_init_type_t init_type = DS_INIT_UNKNOWN; const char *probe_root = cfg->img_mount_point[0] ? cfg->img_mount_point : cfg->rootfs_path; - if (probe_root[0]) - init_type = detect_container_init(probe_root); + if (__builtin_expect( (read_init_type(cfg->pidfile, &init_type) != 0 || + init_type == DS_INIT_UNKNOWN), 0)) { + /* Fallback for containers launched before .init sidecars existed, + * or if runtime metadata was lost / non-informative. */ + if (__builtin_expect(probe_root[0], '/')) + init_type = detect_container_init(probe_root); + } switch (init_type) { case DS_INIT_PROCD: diff --git a/src/droidspace.h b/src/droidspace.h index 30fdfe01..e33bf929 100644 --- a/src/droidspace.h +++ b/src/droidspace.h @@ -128,6 +128,7 @@ #define DS_EXT_PID ".pid" #define DS_EXT_MOUNT ".mount" #define DS_EXT_LOCK ".lock" +#define DS_EXT_INIT ".init" /* Signals */ #define DS_SIG_STOP (SIGRTMIN + 3) @@ -271,6 +272,17 @@ struct ds_port_forward { */ #define DS_PRIV_FULL (0xFF) /* All above */ +typedef enum { + DS_INIT_UNKNOWN = 0, + DS_INIT_SYSTEMD, /* SIGRTMIN+3 */ + DS_INIT_PROCD, /* SIGUSR2 -- OpenWrt; SIGTERM = reboot there! */ + DS_INIT_OPENRC, /* SIGTERM */ + DS_INIT_RUNIT, /* SIGCONT */ + DS_INIT_S6, /* SIGUSR2 */ + DS_INIT_BUSYBOX, /* SIGUSR2 */ + DS_INIT_SYSVINIT, /* SIGTERM */ +} ds_init_type_t; + struct ds_config { /* Paths */ char rootfs_path[PATH_MAX]; /* --rootfs= */ @@ -309,6 +321,7 @@ struct ds_config { pid_t intermediate_pid; /* intermediate fork pid */ int is_img_mount; /* 1 if rootfs was loop-mounted from .img */ char img_mount_point[PATH_MAX]; /* where the .img was mounted */ + ds_init_type_t init_type; /* detected container PID 1 init family */ /* NAT networking synchronization pipes * Both pairs are initialised to {-1,-1} in main() after memset. @@ -386,6 +399,9 @@ int read_and_validate_pid(const char *pidfile, pid_t *pid_out); int save_mount_path(const char *pidfile, const char *mount_path); int read_mount_path(const char *pidfile, char *buf, size_t size); int remove_mount_path(const char *pidfile); +int save_init_type(const char *pidfile, ds_init_type_t init_type); +int read_init_type(const char *pidfile, ds_init_type_t *init_type_out); +int remove_init_type(const char *pidfile); void firmware_path_add(const char *fw_path); void firmware_path_remove(const char *fw_path); int run_command(char *const argv[]); @@ -399,17 +415,6 @@ void print_ds_banner(void); void print_privileged_warning(int privileged_mask); int is_systemd_rootfs(const char *path); -typedef enum { - DS_INIT_UNKNOWN = 0, - DS_INIT_SYSTEMD, /* SIGRTMIN+3 */ - DS_INIT_PROCD, /* SIGUSR2 -- OpenWrt; SIGTERM = reboot there! */ - DS_INIT_OPENRC, /* SIGTERM */ - DS_INIT_RUNIT, /* SIGCONT */ - DS_INIT_S6, /* SIGUSR2 */ - DS_INIT_BUSYBOX, /* SIGUSR2 */ - DS_INIT_SYSVINIT, /* SIGTERM */ -} ds_init_type_t; - ds_init_type_t detect_container_init(const char *path); int get_user_shell(const char *user, char *shell_buf, size_t size); void check_kernel_recommendation(void); diff --git a/src/pid.c b/src/pid.c index d11fc1db..4b2cee35 100644 --- a/src/pid.c +++ b/src/pid.c @@ -221,6 +221,7 @@ int count_running_containers(char *first_name, size_t size) { /* Explicit pruning during scan */ unlink(tmp_cfg.pidfile); remove_mount_path(tmp_cfg.pidfile); + remove_init_type(tmp_cfg.pidfile); } } } @@ -437,6 +438,7 @@ int show_containers(void) { /* Explicit pruning during scan */ unlink(tmp_cfg.pidfile); remove_mount_path(tmp_cfg.pidfile); + remove_init_type(tmp_cfg.pidfile); } } } @@ -676,6 +678,7 @@ int scan_containers(void) { /* Stale PID file, nuke it */ unlink(pf); remove_mount_path(pf); + remove_init_type(pf); } } closedir(d); diff --git a/src/utils.c b/src/utils.c index 393b4cd9..75c1b89f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -714,6 +714,95 @@ int remove_mount_path(const char *pidfile) { return unlink(mpath); } +/* --------------------------------------------------------------------------- + * Init-type sidecar files (.init) + * ---------------------------------------------------------------------------*/ + +static void pidfile_to_initfile(const char *pidfile, char *buf, size_t size) { + safe_strncpy(buf, pidfile, size); + char *dot = strrchr(buf, '.'); + if (dot && strcmp(dot, DS_EXT_PID) == 0) { + /* If it ends in .pid, replace it */ + snprintf(dot, size - (size_t)(dot - buf), DS_EXT_INIT); + } else { + /* Otherwise just append */ + strncat(buf, DS_EXT_INIT, size - strlen(buf) - 1); + } +} + +static const char *init_type_to_string(ds_init_type_t type) { + switch (type) { + case DS_INIT_SYSTEMD: + return "systemd"; + case DS_INIT_PROCD: + return "procd"; + case DS_INIT_OPENRC: + return "openrc"; + case DS_INIT_RUNIT: + return "runit"; + case DS_INIT_S6: + return "s6"; + case DS_INIT_BUSYBOX: + return "busybox"; + case DS_INIT_SYSVINIT: + return "sysvinit"; + case DS_INIT_UNKNOWN: + default: + return "unknown"; + } +} + +static ds_init_type_t init_type_from_string(const char *s) { + if (!s || s[0] == '\0') + return DS_INIT_UNKNOWN; + + if (strcmp(s, "systemd") == 0) + return DS_INIT_SYSTEMD; + if (strcmp(s, "procd") == 0) + return DS_INIT_PROCD; + if (strcmp(s, "openrc") == 0) + return DS_INIT_OPENRC; + if (strcmp(s, "runit") == 0) + return DS_INIT_RUNIT; + if (strcmp(s, "s6") == 0) + return DS_INIT_S6; + if (strcmp(s, "busybox") == 0) + return DS_INIT_BUSYBOX; + if (strcmp(s, "sysvinit") == 0) + return DS_INIT_SYSVINIT; + + return DS_INIT_UNKNOWN; +} + +int save_init_type(const char *pidfile, ds_init_type_t init_type) { + char ipath[PATH_MAX]; + pidfile_to_initfile(pidfile, ipath, sizeof(ipath)); + return write_file(ipath, init_type_to_string(init_type)); +} + +int read_init_type(const char *pidfile, ds_init_type_t *init_type_out) { + if (!init_type_out) + return -1; + + char ipath[PATH_MAX]; + char buf[64]; + + pidfile_to_initfile(pidfile, ipath, sizeof(ipath)); + + if (read_file(ipath, buf, sizeof(buf)) < 0) + return -1; + + buf[strcspn(buf, "\r\n")] = '\0'; + *init_type_out = init_type_from_string(buf); + return 0; +} + +int remove_init_type(const char *pidfile) { + char ipath[PATH_MAX]; + pidfile_to_initfile(pidfile, ipath, sizeof(ipath)); + return unlink(ipath); +} + /* --------------------------------------------------------------------------- * Kernel firmware search path management *