From f6ef5b8dd3f1b8d6af104304a9988ff1f8edd182 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 8 May 2020 02:44:33 +0200 Subject: Implement a "subreaper" service flag For particularly hostile daemons. Signed-off-by: David Oberhollenzer --- initd/init.h | 1 + initd/runsvc.c | 15 ++++++++++++--- lib/include/service.h | 2 ++ lib/init/rdsvc.c | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/initd/init.h b/initd/init.h index 9e18b96..b1287ee 100644 --- a/initd/init.h +++ b/initd/init.h @@ -16,6 +16,7 @@ #include #include +#include #include #include diff --git a/initd/runsvc.c b/initd/runsvc.c index b30e8e3..144490b 100644 --- a/initd/runsvc.c +++ b/initd/runsvc.c @@ -132,13 +132,13 @@ static __attribute__((noreturn)) void argv_exec(exec_t *e) exit(EXIT_FAILURE); } -static int run_sequentially(exec_t *list) +static int run_sequentially(exec_t *list, bool direct_exec_last) { pid_t ret, pid; int status; for (; list != NULL; list = list->next) { - if (list->next == NULL) + if (list->next == NULL && direct_exec_last) argv_exec(list); pid = fork(); @@ -169,6 +169,7 @@ pid_t runsvc(service_t *svc) { sigset_t mask; pid_t pid; + int ret; pid = fork(); @@ -190,7 +191,15 @@ pid_t runsvc(service_t *svc) exit(EXIT_FAILURE); } - exit(run_sequentially(svc->exec)); + if (svc->flags & SVC_FLAG_SUB_REAPER) { + prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); + + ret = run_sequentially(svc->exec, false); + } else { + ret = run_sequentially(svc->exec, true); + } + + exit(ret); } return pid; diff --git a/lib/include/service.h b/lib/include/service.h index 0fbf018..05ab8de 100644 --- a/lib/include/service.h +++ b/lib/include/service.h @@ -39,6 +39,8 @@ enum { /* truncate stdout */ SVC_FLAG_TRUNCATE_OUT = 0x01, + SVC_FLAG_SUB_REAPER = 0x08, + SVC_FLAG_HAS_EXEC = 0x10, }; diff --git a/lib/init/rdsvc.c b/lib/init/rdsvc.c index 09ed156..c461d98 100644 --- a/lib/init/rdsvc.c +++ b/lib/init/rdsvc.c @@ -204,6 +204,22 @@ static int svc_target(void *user, char *arg, rdline_t *rd) return 0; } +static int svc_subreaper(void *user, char *arg, rdline_t *rd) +{ + service_t *svc = user; + + if (try_unescape(arg, rd)) + return -1; + + if (strcmp(arg, "yes") == 0 || strcmp(arg, "on") == 0 || + strcmp(arg, "true") == 0) { + svc->flags |= SVC_FLAG_SUB_REAPER; + } else { + svc->flags &= ~SVC_FLAG_SUB_REAPER; + } + return 0; +} + static const cfg_param_t svc_params[] = { { "description", 0, svc_desc }, { "exec", 1, svc_exec }, @@ -212,6 +228,7 @@ static const cfg_param_t svc_params[] = { { "tty", 0, svc_tty }, { "before", 0, svc_before }, { "after", 0, svc_after }, + { "subreaper", 0, svc_subreaper }, }; service_t *rdsvc(int dirfd, const char *filename) -- cgit v1.2.3