Browse Source

jail: make sure jailed process is terminated

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>
Daniel Golle 2 years ago
parent
commit
bb95fe8df7
2 changed files with 25 additions and 5 deletions
  1. 15 2
      jail/jail.c
  2. 10 3
      service/instance.c

+ 15 - 2
jail/jail.c

@@ -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;

+ 10 - 3
service/instance.c

@@ -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;