jail: make sure jailed process is terminated
authorDaniel Golle <daniel@makrotopia.org>
Fri, 10 Dec 2021 13:48:59 +0000 (13:48 +0000)
committerDaniel Golle <daniel@makrotopia.org>
Sat, 11 Dec 2021 03:12:08 +0000 (03:12 +0000)
Don't ever send SIGKILL to ujail, as that will kill ujail but not the
jailed process.
Instead, let ujail send SIGKILL in case of SIGTERM not succeeding after
the term_timeout which procd now passes down to ujail.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
jail/jail.c
service/instance.c

index 6e9306d0888cd5f955cfb1deb41589d69ef1f67f..bfa2587b30550e7f79ddcaa733466b1d1488bed2 100644 (file)
@@ -69,7 +69,7 @@
 #endif
 
 #define STACK_SIZE     (1024 * 1024)
-#define OPT_ARGS       "cC:d:e:EfFG:h:ij:J:ln:NoO:pP:r:R:sS:uU:w:T:y"
+#define OPT_ARGS       "cC:d:e:EfFG:h:ij:J:ln:NoO:pP:r:R:sS:uU:w:t:T:y"
 
 #define OCI_VERSION_STRING "1.0.2"
 
@@ -153,6 +153,7 @@ static struct {
        char *ocibundle;
        bool immediately;
        struct blob_attr *annotations;
+       int term_timeout;
 } opts;
 
 static struct blob_buf ocibuf;
@@ -1093,11 +1094,17 @@ static void jail_handle_signal(int signo)
        if (hook_running) {
                DEBUG("forwarding signal %d to the hook process\n", signo);
                kill(hook_process.pid, signo);
+               /* set timeout to send SIGKILL hook process in case SIGTERM doesn't succeed */
+               if (signo == SIGTERM)
+                       uloop_timeout_set(&hook_process_timeout, opts.term_timeout * 1000);
        }
 
        if (jail_running) {
                DEBUG("forwarding signal %d to the jailed process\n", signo);
                kill(jail_process.pid, signo);
+               /* set timeout to send SIGKILL jail process in case SIGTERM doesn't succeed */
+               if (signo == SIGTERM)
+                       uloop_timeout_set(&jail_process_timeout, opts.term_timeout * 1000);
        }
 }
 
@@ -1112,7 +1119,7 @@ static void signals_init(void)
 
                if (!sigismember(&sigmask, i))
                        continue;
-               if ((i == SIGCHLD) || (i == SIGPIPE) || (i == SIGSEGV))
+               if ((i == SIGCHLD) || (i == SIGPIPE) || (i == SIGSEGV) || (i == SIGSTOP) || (i == SIGKILL))
                        continue;
 
                s.sa_handler = jail_handle_signal;
@@ -2577,6 +2584,9 @@ int main(int argc, char **argv)
        opts.setns.time = -1;
 #endif
 
+       /* default 5 seconds timeout after SIGTERM before SIGKILL is sent */
+       opts.term_timeout = 5;
+
        umask(022);
        mount_list_init();
        init_library_search();
@@ -2674,6 +2684,9 @@ int main(int argc, char **argv)
                case 'O':
                        opts.overlaydir = realpath(optarg, NULL);
                        break;
+               case 't':
+                       opts.term_timeout = atoi(optarg);
+                       break;
                case 'T':
                        opts.tmpoverlaysize = optarg;
                        break;
index 748c1e51eb0db0631a03c2f119372c226ab12340..9c74265dc4fa92f729aa728c636033856ebdbea0 100644 (file)
@@ -288,12 +288,17 @@ instance_gen_setns_argstr(struct blob_attr *attr)
 static inline int
 jail_run(struct service_instance *in, char **argv)
 {
+       char *term_timeout_str;
        struct blobmsg_list_node *var;
        struct jail *jail = &in->jail;
        int argc = 0;
 
        argv[argc++] = UJAIL_BIN_PATH;
 
+       asprintf(&term_timeout_str, "%d", in->term_timeout);
+       argv[argc++] = "-t";
+       argv[argc++] = term_timeout_str;
+
        if (jail->name) {
                argv[argc++] = "-n";
                argv[argc++] = jail->name;
@@ -867,7 +872,8 @@ instance_stop(struct service_instance *in, bool halt)
        in->halt = halt;
        in->restart = in->respawn = false;
        kill(in->proc.pid, SIGTERM);
-       uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
+       if (!in->has_jail)
+               uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
 }
 
 static void
@@ -884,7 +890,8 @@ instance_restart(struct service_instance *in)
        in->halt = true;
        in->restart = true;
        kill(in->proc.pid, SIGTERM);
-       uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
+       if (!in->has_jail)
+               uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
 }
 
 static void
@@ -1147,7 +1154,7 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
        blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb,
                blobmsg_data(attr), blobmsg_data_len(attr));
 
-       jail->argc = 2;
+       jail->argc = 4;
 
        if (tb[JAIL_ATTR_REQUIREJAIL] && blobmsg_get_bool(tb[JAIL_ATTR_REQUIREJAIL])) {
                in->require_jail = true;