[lxc-devel] [lxc/master] fix handler use-after-free

tych0 on Github lxc-bot at linuxcontainers.org
Thu Mar 15 15:32:48 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 880 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180315/57f5c325/attachment.bin>
-------------- next part --------------
From a3b4f3d68054eb31b86a7192bfc8ffabba011bff Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho at tycho.ws>
Date: Thu, 15 Mar 2018 15:29:27 +0000
Subject: [PATCH] fix handler use-after-free

The problem here is that __lxc_start frees the handler, so any use
afterwards is invalid. Since we don't have access to the actual struct
lxc_container object in __lxc_start, let's pass a pointer to error_num in
so it can be returned.

Unfortunately, I'm a little too paranoid to change the return type of
lxc_start, since it returns failure if some of the cleanup fails, which
may be useful in some cases. So let's keep this out of band.

Closes #2218
Closes #2219

Reported-by: Felix Abecassis <fabecassis at nvidia.com>
Signed-off-by: Tycho Andersen <tycho at tycho.ws>
---
 src/lxc/execute.c      | 4 ++--
 src/lxc/lxc.h          | 4 ++--
 src/lxc/lxccontainer.c | 5 ++---
 src/lxc/start.c        | 8 +++++---
 src/lxc/start.h        | 3 ++-
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/src/lxc/execute.c b/src/lxc/execute.c
index 40856a337..6adef9bf2 100644
--- a/src/lxc/execute.c
+++ b/src/lxc/execute.c
@@ -120,7 +120,7 @@ static struct lxc_operations execute_start_ops = {
 
 int lxc_execute(const char *name, char *const argv[], int quiet,
 		struct lxc_handler *handler, const char *lxcpath,
-		bool backgrounded)
+		bool backgrounded, int *error_num)
 {
 	struct execute_args args = {.argv = argv, .quiet = quiet};
 
@@ -129,5 +129,5 @@ int lxc_execute(const char *name, char *const argv[], int quiet,
 
 	handler->conf->is_execute = 1;
 	return __lxc_start(name, handler, &execute_start_ops, &args, lxcpath,
-			   backgrounded);
+			   backgrounded, error_num);
 }
diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
index c9064ff08..d3c08ddf2 100644
--- a/src/lxc/lxc.h
+++ b/src/lxc/lxc.h
@@ -54,7 +54,7 @@ struct lxc_handler;
  */
 extern int lxc_start(const char *name, char *const argv[],
 		     struct lxc_handler *handler, const char *lxcpath,
-		     bool backgrounded);
+		     bool backgrounded, int *error_num);
 
 /*
  * Start the specified command inside an application container
@@ -67,7 +67,7 @@ extern int lxc_start(const char *name, char *const argv[],
  */
 extern int lxc_execute(const char *name, char *const argv[], int quiet,
 		       struct lxc_handler *handler, const char *lxcpath,
-		       bool backgrounded);
+		       bool backgrounded, int *error_num);
 
 /*
  * Close the fd associated with the monitoring
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index ede0be58f..ecb770f48 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1066,10 +1066,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
 	}
 
 	if (useinit)
-		ret = lxc_execute(c->name, argv, 1, handler, c->config_path, daemonize);
+		ret = lxc_execute(c->name, argv, 1, handler, c->config_path, daemonize, &c->error_num);
 	else
-		ret = lxc_start(c->name, argv, handler, c->config_path, daemonize);
-	c->error_num = handler->exit_status;
+		ret = lxc_start(c->name, argv, handler, c->config_path, daemonize, &c->error_num);
 
 	if (conf->reboot == 1) {
 		INFO("Container requested reboot");
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 4e2f8a433..c728a62be 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1824,7 +1824,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 
 int __lxc_start(const char *name, struct lxc_handler *handler,
 		struct lxc_operations* ops, void *data, const char *lxcpath,
-		bool backgrounded)
+		bool backgrounded, int *error_num)
 {
 	int ret, status;
 	struct lxc_conf *conf = handler->conf;
@@ -1920,6 +1920,8 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
 
 	lxc_monitor_send_exit_code(name, status, handler->lxcpath);
 	lxc_error_set_and_log(handler->pid, status);
+	if (error_num)
+		*error_num = handler->exit_status;
 
 out_fini:
 	lxc_delete_network(handler);
@@ -1965,13 +1967,13 @@ static struct lxc_operations start_ops = {
 };
 
 int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler,
-	      const char *lxcpath, bool backgrounded)
+	      const char *lxcpath, bool backgrounded, int *error_num)
 {
 	struct start_args start_arg = {
 		.argv = argv,
 	};
 
-	return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, backgrounded);
+	return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, backgrounded, error_num);
 }
 
 static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 64e5a937e..e6aabe78c 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -165,7 +165,8 @@ extern void lxc_fini(const char *name, struct lxc_handler *handler);
 extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall,
 			       int *fds_to_ignore, size_t len_fds);
 extern int __lxc_start(const char *, struct lxc_handler *,
-		       struct lxc_operations *, void *, const char *, bool);
+		       struct lxc_operations *, void *, const char *, bool,
+		       int *);
 
 extern int resolve_clone_flags(struct lxc_handler *handler);
 


More information about the lxc-devel mailing list