[lxc-devel] [lxc/master] [lxc-top] add future to show memsw

anevenchanniy on Github lxc-bot at linuxcontainers.org
Sat May 6 16:15:45 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 609 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170506/da55716e/attachment.bin>
-------------- next part --------------
From e73bcbbee9bf040512585099cd68677bff02c130 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Thu, 7 Apr 2016 17:10:20 +0200
Subject: [PATCH 001/334] lxc-attach: attach even without sigwinch handler

lxc_console_create() calls lxc_console_peer_default() which in turn calls
lxc_console_sigwinch_init() which sets up the lxc_tty_state struct for the
current pty. Prior to this commit lxc_console_sigwinch_init() would consider
failures to install a SIGWINCH handler fatal and and return NULL. This commit
makes failures to install a SIGWINCH handler non-fatal. In such cases the
lxc_tty_state struct will still be set up but the sigfd member, which contains
the fd which receives SIGWINCH events, will be set to -1. (This also entails
that the sigset_t oldmaks field is meaningless.) Callers of
lxc_console_sigwinch_init() and lxc_console_sigwinch_fini() should thus make
sure that sigfd >= 0 or sigfd != -1 before trying to register a SIGWINCH handler
in e.g. an lxc_mainloop or resetting the sigmask (cf. lxc_attach.c).

These changes also imply that lxc_console_sigwinch_init() only fails with
ENOMEM. Thus, all cases where lxc_console_sigwinch_init() returns NULL are to be
considered fatal. This wasn't the case before this commit.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c    | 50 +++++++++++++++++++++++++-------------------------
 src/lxc/console.h    |  4 +++-
 src/lxc/lxc_attach.c | 21 +++++++++++++--------
 3 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index 5df73e4..2ce3cc4 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -118,9 +118,9 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd)
 		return NULL;
 
 	memset(ts, 0, sizeof(*ts));
-	ts->stdinfd  = srcfd;
+	ts->stdinfd = srcfd;
 	ts->masterfd = dstfd;
-	ts->sigfd    = -1;
+	ts->sigfd = -1;
 
 	/* add tty to list to be scanned at SIGWINCH time */
 	lxc_list_add_elem(&ts->node, ts);
@@ -129,26 +129,20 @@ struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd)
 	sigemptyset(&mask);
 	sigaddset(&mask, SIGWINCH);
 	if (sigprocmask(SIG_BLOCK, &mask, &ts->oldmask)) {
-		SYSERROR("failed to block SIGWINCH");
-		goto err1;
+		SYSERROR("failed to block SIGWINCH.");
+		ts->sigfd = -1;
+		return ts;
 	}
 
 	ts->sigfd = signalfd(-1, &mask, 0);
 	if (ts->sigfd < 0) {
-		SYSERROR("failed to get signalfd");
-		goto err2;
+		SYSERROR("failed to get signalfd.");
+		sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
+		ts->sigfd = -1;
+		return ts;
 	}
 
 	DEBUG("%d got SIGWINCH fd %d", getpid(), ts->sigfd);
-	goto out;
-
-err2:
-	sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
-err1:
-	lxc_list_del(&ts->node);
-	free(ts);
-	ts = NULL;
-out:
 	return ts;
 }
 
@@ -207,7 +201,7 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console)
 			WARN("console peer not added to mainloop");
 	}
 
-	if (console->tty_state) {
+	if (console->tty_state && console->tty_state->sigfd != -1) {
 		if (lxc_mainloop_add_handler(console->descr,
 					     console->tty_state->sigfd,
 					     lxc_console_cb_sigwinch_fd,
@@ -291,7 +285,7 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
 
 static void lxc_console_peer_proxy_free(struct lxc_console *console)
 {
-	if (console->tty_state) {
+	if (console->tty_state && console->tty_state->sigfd != -1) {
 		lxc_console_sigwinch_fini(console->tty_state);
 		console->tty_state = NULL;
 	}
@@ -446,9 +440,11 @@ static void lxc_console_peer_default(struct lxc_console *console)
 		goto err1;
 
 	ts = lxc_console_sigwinch_init(console->peer, console->master);
-	if (!ts)
-		WARN("Unable to install SIGWINCH");
 	console->tty_state = ts;
+	if (!ts) {
+		WARN("Unable to install SIGWINCH");
+		goto err1;
+	}
 
 	lxc_console_winsz(console->peer, console->master);
 
@@ -471,6 +467,7 @@ static void lxc_console_peer_default(struct lxc_console *console)
 	console->peer = -1;
 out:
 	DEBUG("no console peer");
+	return;
 }
 
 void lxc_console_delete(struct lxc_console *console)
@@ -695,11 +692,13 @@ int lxc_console(struct lxc_container *c, int ttynum,
 		goto err3;
 	}
 
-	ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
-				       lxc_console_cb_sigwinch_fd, ts);
-	if (ret) {
-		ERROR("failed to add handler for SIGWINCH fd");
-		goto err4;
+	if (ts->sigfd != -1) {
+		ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
+				lxc_console_cb_sigwinch_fd, ts);
+		if (ret) {
+			ERROR("failed to add handler for SIGWINCH fd");
+			goto err4;
+		}
 	}
 
 	ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
@@ -727,7 +726,8 @@ int lxc_console(struct lxc_container *c, int ttynum,
 err4:
 	lxc_mainloop_close(&descr);
 err3:
-	lxc_console_sigwinch_fini(ts);
+	if (ts->sigfd != -1)
+		lxc_console_sigwinch_fini(ts);
 err2:
 	close(masterfd);
 	close(ttyfd);
diff --git a/src/lxc/console.h b/src/lxc/console.h
index 1f0a070..d3ccd8b 100644
--- a/src/lxc/console.h
+++ b/src/lxc/console.h
@@ -47,7 +47,9 @@ struct lxc_tty_state
 	const char *winch_proxy;
 	/* Path of the container to forward the SIGWINCH event to. */
 	const char *winch_proxy_lxcpath;
-	/* File descriptor that accepts SIGWINCH signals. */
+	/* File descriptor that accepts SIGWINCH signals. If set to -1 no
+	 * SIGWINCH handler could be installed. This also means that
+	 * the sigset_t oldmask member is meaningless. */
 	int sigfd;
 	sigset_t oldmask;
 };
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index ffcd3d1..cdc56d6 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -264,7 +264,6 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 	 * always do the correct thing. strdup() must be used since console.path
 	 * is free()ed when we call lxc_container_put(). */
 	free(conf->console.path);
-	conf->console.path = NULL;
 	conf->console.path = strdup("/dev/tty");
 	if (!conf->console.path)
 		return -1;
@@ -326,12 +325,17 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 		goto err2;
 	}
 
-	/* Register sigwinch handler in mainloop. */
-	ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
-			lxc_console_cb_sigwinch_fd, ts);
-	if (ret) {
-		ERROR("failed to add handler for SIGWINCH fd");
-		goto err3;
+	/* Register sigwinch handler in mainloop. When ts->sigfd == -1 it means
+	 * we weren't able to install a sigwinch handler in
+	 * lxc_console_create(). We don't consider this fatal and just move on.
+	 */
+	if (ts->sigfd != -1) {
+		ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
+				lxc_console_cb_sigwinch_fd, ts);
+		if (ret) {
+			ERROR("failed to add handler for SIGWINCH fd");
+			goto err3;
+		}
 	}
 
 	/* Register i/o callbacks in mainloop. */
@@ -359,7 +363,8 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 err3:
 	lxc_mainloop_close(&descr);
 err2:
-	lxc_console_sigwinch_fini(ts);
+	if (ts->sigfd != -1)
+		lxc_console_sigwinch_fini(ts);
 err1:
 	lxc_console_delete(&conf->console);
 

From d3e3b1885a13dbe97433f11c26dbcc9d70dd9d4f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Fri, 8 Apr 2016 15:53:36 +0200
Subject: [PATCH 002/334] simplify pty allocation and implement pty logging

lxc-attach allocated a pty in a manner that relied on ts->stdinfd and
ts->stdoutfd to be set. We had to resort to a trick to get it working when
output is redirected. The new implementation gets rid of the black magic and
also simplifies the code.

This commit also implements pty logging for lxc-attach. Users will now be able
to log commands and corresponding output to a file given that lxc-attach
allocates a pty.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c    | 12 +++++----
 src/lxc/console.h    |  2 +-
 src/lxc/lxc_attach.c | 71 ++++++++--------------------------------------------
 src/lxc/start.c      |  2 +-
 4 files changed, 20 insertions(+), 67 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index 2ce3cc4..f874172 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -27,10 +27,10 @@
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/epoll.h>
-#include <sys/types.h>
 #include <termios.h>
 #include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
 
 #include <lxc/lxccontainer.h>
 
@@ -163,6 +163,9 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
 	char buf[1024];
 	int r,w;
 
+	if (events & EPOLLHUP)
+		return 1;
+
 	w = r = read(fd, buf, sizeof(buf));
 	if (r < 0) {
 		SYSERROR("failed to read");
@@ -212,10 +215,9 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console)
 	}
 }
 
-int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
-			     struct lxc_handler *handler)
+extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
+				    struct lxc_conf *conf)
 {
-	struct lxc_conf *conf = handler->conf;
 	struct lxc_console *console = &conf->console;
 
 	if (conf->is_execute) {
diff --git a/src/lxc/console.h b/src/lxc/console.h
index d3ccd8b..fefdb19 100644
--- a/src/lxc/console.h
+++ b/src/lxc/console.h
@@ -102,7 +102,7 @@ extern void lxc_console_free(struct lxc_conf *conf, int fd);
 /*
  * Register pty event handlers in an open mainloop
  */
-extern int  lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_handler *);
+extern int  lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_conf *);
 
 /*
  * Handle SIGWINCH events on the allocated ptys.
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index cdc56d6..f02ef26 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -64,6 +64,7 @@ static const struct option my_longopts[] = {
 	{"keep-env", no_argument, 0, 501},
 	{"keep-var", required_argument, 0, 502},
 	{"set-var", required_argument, 0, 'v'},
+	{"pty-log", required_argument, 0, 'L'},
 	LXC_COMMON_OPTIONS
 };
 
@@ -149,6 +150,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
 			return -1;
 		}
 		break;
+	case 'L':
+		args->console_log = arg;
+		break;
 	}
 
 	return 0;
@@ -191,6 +195,8 @@ Options :\n\
       --keep-env    Keep all current environment variables. This\n\
                     is the current default behaviour, but is likely to\n\
                     change in the future.\n\
+  -L, --pty-log=FILE\n\
+		    Log pty output to FILE\n\
   -v, --set-var     Set an additional variable that is seen by the\n\
                     attached program in the container. May be specified\n\
                     multiple times.\n\
@@ -254,7 +260,10 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 
 	conf = c->lxc_conf;
 	free(conf->console.log_path);
-	conf->console.log_path = NULL;
+	if (my_args.console_log)
+		conf->console.log_path = strdup(my_args.console_log);
+	else
+		conf->console.log_path = NULL;
 
 	/* In the case of lxc-attach our peer pty will always be the current
 	 * controlling terminal. We clear whatever was set by the user for
@@ -272,39 +281,6 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 	if (lxc_console_create(conf) < 0)
 		return -1;
 	ts = conf->console.tty_state;
-	/*
-	 * We need to make sure that the ouput that is produced inside the
-	 * container is received on the host. Suppose we want to run
-	 *
-	 *	lxc-attach -n a -- /bin/sh -c 'hostname >&2' > /dev/null
-	 *
-	 * This command produces output on stderr inside the container. On the
-	 * host we close stdout by redirecting it to /dev/null. But stderr is,
-	 * as expected, still connected to a tty. We receive the output produced
-	 * on stderr in the container on stderr on the host.
-	 *
-	 * For the command
-	 *
-	 *	lxc-attach -n a -- /bin/sh -c 'hostname >&2' 2> /dev/null
-	 *
-	 * the logic is analogous but because we now have closed stderr on the
-	 * host no output will be received.
-	 *
-	 * Finally, imagine a more complicated case
-	 *
-	 *	lxc-attach -n a -- /bin/sh -c 'echo OUT; echo ERR >&2' > /tmp/out 2> /tmp/err
-	 *
-	 * Here, we produce output in the container on stdout and stderr. On the
-	 * host we redirect stdout and stderr to files. Because of that stdout
-	 * and stderr are not dup2()ed. Thus, they are not connected to a pty
-	 * and output on stdout and stderr is redirected to the corresponding
-	 * files as expected.
-	 */
-	if (!isatty(STDOUT_FILENO) && isatty(STDERR_FILENO))
-		ts->stdoutfd = STDERR_FILENO;
-	else
-		ts->stdoutfd = STDOUT_FILENO;
-
 	conf->console.descr = &descr;
 
 	/* Shift ttys to container. */
@@ -325,33 +301,8 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 		goto err2;
 	}
 
-	/* Register sigwinch handler in mainloop. When ts->sigfd == -1 it means
-	 * we weren't able to install a sigwinch handler in
-	 * lxc_console_create(). We don't consider this fatal and just move on.
-	 */
-	if (ts->sigfd != -1) {
-		ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
-				lxc_console_cb_sigwinch_fd, ts);
-		if (ret) {
-			ERROR("failed to add handler for SIGWINCH fd");
-			goto err3;
-		}
-	}
-
-	/* Register i/o callbacks in mainloop. */
-	ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
-			lxc_console_cb_tty_stdin, ts);
-	if (ret) {
-		ERROR("failed to add handler for stdinfd");
-		goto err3;
-	}
-
-	ret = lxc_mainloop_add_handler(&descr, ts->masterfd,
-			lxc_console_cb_tty_master, ts);
-	if (ret) {
-		ERROR("failed to add handler for masterfd");
+	if (lxc_console_mainloop_add(&descr, conf) < 0)
 		goto err3;
-	}
 
 	ret = lxc_mainloop(&descr, -1);
 	if (ret) {
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 5be0077..d9d5814 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -365,7 +365,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
 		goto out_mainloop_open;
 	}
 
-	if (lxc_console_mainloop_add(&descr, handler)) {
+	if (lxc_console_mainloop_add(&descr, handler->conf)) {
 		ERROR("failed to add console handler to mainloop");
 		goto out_mainloop_open;
 	}

From 32bf178747090118fc6fcc25ae6550643cd521f8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Fri, 8 Apr 2016 20:28:59 +0200
Subject: [PATCH 003/334] use lxc_read_nointr() and lxc_write_nointr()

Using EPOLLHUP to determine when to exit the loop is unreliable. Let's exit
clean when read() returns -1 && errno != EINTR or 0.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c    | 22 +++++++---------------
 src/lxc/lxc_attach.c |  4 +++-
 2 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index f874172..a8d09ca 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -161,33 +161,25 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
 {
 	struct lxc_console *console = (struct lxc_console *)data;
 	char buf[1024];
-	int r,w;
-
-	if (events & EPOLLHUP)
-		return 1;
-
-	w = r = read(fd, buf, sizeof(buf));
-	if (r < 0) {
-		SYSERROR("failed to read");
-		return 1;
-	}
+	int r, w;
 
-	if (!r) {
+	w = r = lxc_read_nointr(fd, buf, sizeof(buf));
+	if (r <= 0) {
 		INFO("console client on fd %d has exited", fd);
 		lxc_mainloop_del_handler(descr, fd);
 		close(fd);
-		return 0;
+		return 1;
 	}
 
 	if (fd == console->peer)
-		w = write(console->master, buf, r);
+		w = lxc_write_nointr(console->master, buf, r);
 
 	if (fd == console->master) {
 		if (console->log_fd >= 0)
-			w = write(console->log_fd, buf, r);
+			w = lxc_write_nointr(console->log_fd, buf, r);
 
 		if (console->peer >= 0)
-			w = write(console->peer, buf, r);
+			w = lxc_write_nointr(console->peer, buf, r);
 	}
 
 	if (w != r)
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index f02ef26..ed3ba0d 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -301,8 +301,10 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 		goto err2;
 	}
 
-	if (lxc_console_mainloop_add(&descr, conf) < 0)
+	if (lxc_console_mainloop_add(&descr, conf) < 0) {
+		ERROR("Failed to add handlers to lxc mainloop.");
 		goto err3;
+	}
 
 	ret = lxc_mainloop(&descr, -1);
 	if (ret) {

From 08be058f9f3dad9ce88583c4fa2a17aae767844c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Fri, 8 Apr 2016 20:38:49 +0200
Subject: [PATCH 004/334] fix lxc_console_cb_tty_*()

Clean exit when read() == -1 && errno != EINTR or read() == 0.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c | 26 ++++++++------------------
 1 file changed, 8 insertions(+), 18 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index a8d09ca..a346377 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -571,14 +571,9 @@ int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
 	struct lxc_tty_state *ts = cbdata;
 	char c;
 
-	if (events & EPOLLHUP)
-		return 1;
-
 	assert(fd == ts->stdinfd);
-	if (read(ts->stdinfd, &c, 1) < 0) {
-		SYSERROR("failed to read");
+	if (lxc_read_nointr(ts->stdinfd, &c, 1) <= 0)
 		return 1;
-	}
 
 	if (ts->escape != -1) {
 		/* we want to exit the console with Ctrl+a q */
@@ -593,10 +588,8 @@ int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
 		ts->saw_escape = 0;
 	}
 
-	if (write(ts->masterfd, &c, 1) < 0) {
-		SYSERROR("failed to write");
+	if (lxc_write_nointr(ts->masterfd, &c, 1) <= 0)
 		return 1;
-	}
 
 	return 0;
 }
@@ -608,18 +601,15 @@ int lxc_console_cb_tty_master(int fd, uint32_t events, void *cbdata,
 	char buf[1024];
 	int r, w;
 
-	if (events & EPOLLHUP)
-		return 1;
-
 	assert(fd == ts->masterfd);
-	r = read(fd, buf, sizeof(buf));
-	if (r < 0) {
-		SYSERROR("failed to read");
+	r = lxc_read_nointr(fd, buf, sizeof(buf));
+	if (r <= 0)
 		return 1;
-	}
 
-	w = write(ts->stdoutfd, buf, r);
-	if (w < 0 || w != r) {
+	w = lxc_write_nointr(ts->stdoutfd, buf, r);
+	if (w <= 0) {
+		return 1;
+	} else if (w != r) {
 		SYSERROR("failed to write");
 		return 1;
 	}

From 004fc78469ea7f4752e8216792faa128fded09a3 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn at ubuntu.com>
Date: Fri, 8 Apr 2016 16:18:04 -0500
Subject: [PATCH 005/334] cgfsng: defer to cgfs if needed subsystems are not
 available

This requires us to check that at cgfsng_ops_init, rather than
cgfs_init.  Cache the hierarchy and cgroup.use info globally
rather than putting it into the per-container info, as cgmanager
does.  This is ok as both cgroup.use and the list of usable
hierarchies are in fact global to a lxc run.

Closes #952

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/cgfsng.c | 196 ++++++++++++++++++++++---------------------------------
 1 file changed, 78 insertions(+), 118 deletions(-)

diff --git a/src/lxc/cgfsng.c b/src/lxc/cgfsng.c
index cf75319..fad0be4 100644
--- a/src/lxc/cgfsng.c
+++ b/src/lxc/cgfsng.c
@@ -72,10 +72,6 @@ struct hierarchy {
 
 /*
  * The cgroup data which is attached to the lxc_handler.
- * @hierarchies - a NULL-terminated array of struct hierarchy, one per
- *   hierarchy.  No duplicates.  First sufficient, writeable mounted
- *   hierarchy wins
- * @cgroup_use - a copy of the lxc.cgroup.use
  * @cgroup_pattern - a copy of the lxc.cgroup.pattern
  * @container_cgroup - if not null, the cgroup which was created for
  *   the container.  For each hierarchy, it is created under the
@@ -84,13 +80,23 @@ struct hierarchy {
  * @name - the container name
  */
 struct cgfsng_handler_data {
-	struct hierarchy **hierarchies;
-	char *cgroup_use;
 	char *cgroup_pattern;
 	char *container_cgroup; // cgroup we created for the container
 	char *name; // container name
 };
 
+/*
+ * @hierarchies - a NULL-terminated array of struct hierarchy, one per
+ *   hierarchy.  No duplicates.  First sufficient, writeable mounted
+ *   hierarchy wins
+ */
+struct hierarchy **hierarchies;
+
+/*
+ * @cgroup_use - a copy of the lxc.cgroup.use
+ */
+char *cgroup_use;
+
 static void free_string_list(char **clist)
 {
 	if (clist) {
@@ -218,25 +224,8 @@ static void must_append_controller(char **klist, char **nlist, char ***clist, ch
 	(*clist)[newentry] = copy;
 }
 
-static void free_hierarchies(struct hierarchy **hlist)
-{
-	if (hlist) {
-		int i;
-
-		for (i = 0; hlist[i]; i++) {
-			free(hlist[i]->mountpoint);
-			free(hlist[i]->base_cgroup);
-			free(hlist[i]->fullcgpath);
-			free_string_list(hlist[i]->controllers);
-		}
-		free(hlist);
-	}
-}
-
 static void free_handler_data(struct cgfsng_handler_data *d)
 {
-	free_hierarchies(d->hierarchies);
-	free(d->cgroup_use);
 	free(d->cgroup_pattern);
 	free(d->container_cgroup);
 	free(d->name);
@@ -247,15 +236,15 @@ static void free_handler_data(struct cgfsng_handler_data *d)
  * Given a handler's cgroup data, return the struct hierarchy for the
  * controller @c, or NULL if there is none.
  */
-struct hierarchy *get_hierarchy(struct cgfsng_handler_data *d, const char *c)
+struct hierarchy *get_hierarchy(const char *c)
 {
 	int i;
 
-	if (!d || !d->hierarchies)
+	if (!hierarchies)
 		return NULL;
-	for (i = 0; d->hierarchies[i]; i++) {
-		if (string_in_list(d->hierarchies[i]->controllers, c))
-			return d->hierarchies[i];
+	for (i = 0; hierarchies[i]; i++) {
+		if (string_in_list(hierarchies[i]->controllers, c))
+			return hierarchies[i];
 	}
 	return NULL;
 }
@@ -422,10 +411,10 @@ static bool controller_found(struct hierarchy **hlist, char *entry)
  * found.  The required list is systemd, freezer, and anything in
  * lxc.cgroup.use.
  */
-static bool all_controllers_found(struct cgfsng_handler_data *d)
+static bool all_controllers_found(void)
 {
 	char *p, *saveptr = NULL;
-	struct hierarchy ** hlist = d->hierarchies;
+	struct hierarchy ** hlist = hierarchies;
 
 	if (!controller_found(hlist, "name=systemd")) {
 		ERROR("no systemd controller mountpoint found");
@@ -436,9 +425,9 @@ static bool all_controllers_found(struct cgfsng_handler_data *d)
 		return false;
 	}
 
-	if (!d->cgroup_use)
+	if (!cgroup_use)
 		return true;
-	for (p = strtok_r(d->cgroup_use, ",", &saveptr); p;
+	for (p = strtok_r(cgroup_use, ",", &saveptr); p;
 			p = strtok_r(NULL, ",", &saveptr)) {
 		if (!controller_found(hlist, p)) {
 			ERROR("no %s controller mountpoint found", p);
@@ -508,8 +497,7 @@ static bool is_cgroupfs(char *line)
 }
 
 /* Add a controller to our list of hierarchies */
-static void add_controller(struct cgfsng_handler_data *d, char **clist,
-			   char *mountpoint, char *base_cgroup)
+static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
 {
 	struct hierarchy *new;
 	int newentry;
@@ -520,8 +508,8 @@ static void add_controller(struct cgfsng_handler_data *d, char **clist,
 	new->base_cgroup = base_cgroup;
 	new->fullcgpath = NULL;
 
-	newentry = append_null_to_list((void ***)&d->hierarchies);
-	d->hierarchies[newentry] = new;
+	newentry = append_null_to_list((void ***)&hierarchies);
+	hierarchies[newentry] = new;
 }
 
 /*
@@ -732,16 +720,16 @@ static void print_init_debuginfo(struct cgfsng_handler_data *d)
 
 	printf("Cgroup information:\n");
 	printf("  container name: %s\n", d->name);
-	printf("  lxc.cgroup.use: %s\n", d->cgroup_use ? d->cgroup_use : "(none)");
+	printf("  lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(none)");
 	printf("  lxc.cgroup.pattern: %s\n", d->cgroup_pattern);
 	printf("  cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(none)");
-	if (!d->hierarchies) {
+	if (!hierarchies) {
 		printf("  No hierarchies found.\n");
 		return;
 	}
 	printf("  Hierarchies:\n");
-	for (i = 0; d->hierarchies[i]; i++) {
-		struct hierarchy *h = d->hierarchies[i];
+	for (i = 0; hierarchies[i]; i++) {
+		struct hierarchy *h = hierarchies[i];
 		int j;
 		printf("  %d: base_cgroup %s\n", i, h->base_cgroup);
 		printf("      mountpoint %s\n", h->mountpoint);
@@ -769,7 +757,7 @@ static void print_basecg_debuginfo(char *basecginfo, char **klist, char **nlist)
  * At startup, parse_hierarchies finds all the info we need about
  * cgroup mountpoints and current cgroups, and stores it in @d.
  */
-static bool parse_hierarchies(struct cgfsng_handler_data *d)
+static bool parse_hierarchies(void)
 {
 	FILE *f;
 	char * line = NULL, *basecginfo;
@@ -808,7 +796,7 @@ static bool parse_hierarchies(struct cgfsng_handler_data *d)
 		if (!controller_list)
 			continue;
 
-		if (controller_list_is_dup(d->hierarchies, controller_list)) {
+		if (controller_list_is_dup(hierarchies, controller_list)) {
 			free(controller_list);
 			continue;
 		}
@@ -835,7 +823,7 @@ static bool parse_hierarchies(struct cgfsng_handler_data *d)
 			free(base_cgroup);
 			continue;
 		}
-		add_controller(d, controller_list, mountpoint, base_cgroup);
+		add_controller(controller_list, mountpoint, base_cgroup);
 	}
 
 	free_string_list(klist);
@@ -846,35 +834,39 @@ static bool parse_hierarchies(struct cgfsng_handler_data *d)
 	fclose(f);
 	free(line);
 
-	print_init_debuginfo(d);
-
 	/* verify that all controllers in cgroup.use and all crucial
 	 * controllers are accounted for
 	 */
-	if (!all_controllers_found(d))
+	if (!all_controllers_found())
 		return false;
 
 	return true;
 }
 
+static bool collect_hierarchy_info(void)
+{
+	const char *tmp;
+	errno = 0;
+	tmp = lxc_global_config_value("lxc.cgroup.use");
+	if (!cgroup_use && errno != 0) { // lxc.cgroup.use can be NULL
+		SYSERROR("cgfsng: error reading list of cgroups to use");
+		return false;
+	}
+	cgroup_use = must_copy_string(tmp);
+
+	return parse_hierarchies();
+}
+
 static void *cgfsng_init(const char *name)
 {
 	struct cgfsng_handler_data *d;
-	const char *cgroup_use, *cgroup_pattern;
+	const char *cgroup_pattern;
 
 	d = must_alloc(sizeof(*d));
 	memset(d, 0, sizeof(*d));
 
 	d->name = must_copy_string(name);
 
-	errno = 0;
-	cgroup_use = lxc_global_config_value("lxc.cgroup.use");
-	if (!cgroup_use && errno != 0) { // lxc.cgroup.use can be NULL
-		SYSERROR("Error reading list of cgroups to use");
-		goto out_free;
-	}
-	d->cgroup_use = must_copy_string(cgroup_use);
-
 	cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
 	if (!cgroup_pattern) { // lxc.cgroup.pattern is only NULL on error
 		ERROR("Error getting cgroup pattern");
@@ -882,9 +874,6 @@ static void *cgfsng_init(const char *name)
 	}
 	d->cgroup_pattern = must_copy_string(cgroup_pattern);
 
-	if (!parse_hierarchies(d))
-		goto out_free;
-
 	print_init_debuginfo(d);
 
 	return d;
@@ -1006,10 +995,10 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
 	if (!d)
 		return;
 
-	if (d->container_cgroup && d->hierarchies) {
+	if (d->container_cgroup && hierarchies) {
 		int i;
-		for (i = 0; d->hierarchies[i]; i++) {
-			struct hierarchy *h = d->hierarchies[i];
+		for (i = 0; hierarchies[i]; i++) {
+			struct hierarchy *h = hierarchies[i];
 			if (h->fullcgpath) {
 				recursive_destroy(h->fullcgpath, conf);
 				free(h->fullcgpath);
@@ -1023,6 +1012,8 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
 
 struct cgroup_ops *cgfsng_ops_init(void)
 {
+	if (!collect_hierarchy_info())
+		return NULL;
 	return &cgfsng_ops;
 }
 
@@ -1080,14 +1071,14 @@ static inline bool cgfsng_create(void *hdata)
 	}
 	if (idx)
 		snprintf(offset, 5, "-%d", idx);
-	for (i = 0; d->hierarchies[i]; i++) {
-		if (!create_path_for_hierarchy(d->hierarchies[i], cgname)) {
+	for (i = 0; hierarchies[i]; i++) {
+		if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
 			int j;
-			SYSERROR("Failed to create %s: %s", d->hierarchies[i]->fullcgpath, strerror(errno));
-			free(d->hierarchies[i]->fullcgpath);
-			d->hierarchies[i]->fullcgpath = NULL;
+			SYSERROR("Failed to create %s: %s", hierarchies[i]->fullcgpath, strerror(errno));
+			free(hierarchies[i]->fullcgpath);
+			hierarchies[i]->fullcgpath = NULL;
 			for (j = 0; j < i; j++)
-				remove_path_for_hierarchy(d->hierarchies[j], cgname);
+				remove_path_for_hierarchy(hierarchies[j], cgname);
 			idx++;
 			goto again;
 		}
@@ -1110,7 +1101,6 @@ static const char *cgfsng_canonical_path(void *hdata)
 
 static bool cgfsng_enter(void *hdata, pid_t pid)
 {
-	struct cgfsng_handler_data *d = hdata;
 	char pidstr[25];
 	int i, len;
 
@@ -1118,8 +1108,8 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
 	if (len < 0 || len > 25)
 		return false;
 
-	for (i = 0; d->hierarchies[i]; i++) {
-		char *fullpath = must_make_path(d->hierarchies[i]->fullcgpath,
+	for (i = 0; hierarchies[i]; i++) {
+		char *fullpath = must_make_path(hierarchies[i]->fullcgpath,
 						"cgroup.procs", NULL);
 		if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
 			SYSERROR("Failed to enter %s", fullpath);
@@ -1148,7 +1138,6 @@ struct chown_data {
 static int chown_cgroup_wrapper(void *data)
 {
 	struct chown_data *arg = data;
-	struct cgfsng_handler_data *d = arg->d;
 	uid_t destuid;
 	int i;
 
@@ -1161,8 +1150,8 @@ static int chown_cgroup_wrapper(void *data)
 
 	destuid = get_ns_uid(arg->origuid);
 
-	for (i = 0; d->hierarchies[i]; i++) {
-		char *fullpath, *path = d->hierarchies[i]->fullcgpath;
+	for (i = 0; hierarchies[i]; i++) {
+		char *fullpath, *path = hierarchies[i]->fullcgpath;
 
 		if (chown(path, destuid, 0) < 0) {
 			SYSERROR("Error chowning %s to %d", path, (int) destuid);
@@ -1334,9 +1323,9 @@ static bool cgfsng_mount(void *hdata, const char *root, int type)
 			root) < 0)
 		goto  bad;
 
-	for (i = 0; d->hierarchies[i]; i++) {
+	for (i = 0; hierarchies[i]; i++) {
 		char *controllerpath, *path2;
-		struct hierarchy *h = d->hierarchies[i];
+		struct hierarchy *h = hierarchies[i];
 		char *controller = strrchr(h->mountpoint, '/');
 		int r;
 
@@ -1431,9 +1420,9 @@ static int cgfsng_nrtasks(void *hdata) {
 	char *path;
 	int count;
 
-	if (!d || !d->container_cgroup || !d->hierarchies)
+	if (!d || !d->container_cgroup || !hierarchies)
 		return -1;
-	path = must_make_path(d->hierarchies[0]->fullcgpath, NULL);
+	path = must_make_path(hierarchies[0]->fullcgpath, NULL);
 	count = recursive_count_nrtasks(path);
 	free(path);
 	return count;
@@ -1455,9 +1444,9 @@ static bool cgfsng_escape()
 		return false;
 	}
 
-	for (i = 0; d->hierarchies[i]; i++) {
-		char *fullpath = must_make_path(d->hierarchies[i]->mountpoint,
-						d->hierarchies[i]->base_cgroup,
+	for (i = 0; hierarchies[i]; i++) {
+		char *fullpath = must_make_path(hierarchies[i]->mountpoint,
+						hierarchies[i]->base_cgroup,
 						"cgroup.procs", NULL);
 		if (lxc_write_to_file(fullpath, "0", 2, false) != 0) {
 			SYSERROR("Failed to escape to %s", fullpath);
@@ -1478,11 +1467,10 @@ static bool cgfsng_escape()
 
 static bool cgfsng_unfreeze(void *hdata)
 {
-	struct cgfsng_handler_data *d = hdata;
 	char *fullpath;
-	struct hierarchy *h = get_hierarchy(d, "freezer");
+	struct hierarchy *h = get_hierarchy("freezer");
 
-	if (!d || !h)
+	if (!h)
 		return false;
 	fullpath = must_make_path(h->fullcgpath, "freezer.state", NULL);
 	if (lxc_write_to_file(fullpath, THAWED, THAWED_LEN, false) != 0) {
@@ -1495,12 +1483,7 @@ static bool cgfsng_unfreeze(void *hdata)
 
 static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem)
 {
-	struct cgfsng_handler_data *d = hdata;
-	struct hierarchy *h;
-	if (!d)
-		return NULL;
-
-	h = get_hierarchy(d, subsystem);
+	struct hierarchy *h = get_hierarchy(subsystem);
 	if (!h)
 		return NULL;
 
@@ -1527,7 +1510,6 @@ static char *build_full_cgpath_from_monitorpath(struct hierarchy *h,
 
 static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
 {
-	struct cgfsng_handler_data *d;
 	char pidstr[25];
 	int i, len;
 
@@ -1535,13 +1517,9 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
 	if (len < 0 || len > 25)
 		return false;
 
-	d = cgfsng_init(name);
-	if (!d)
-		return false;
-
-	for (i = 0; d->hierarchies[i]; i++) {
+	for (i = 0; hierarchies[i]; i++) {
 		char *path, *fullpath;
-		struct hierarchy *h = d->hierarchies[i];
+		struct hierarchy *h = hierarchies[i];
 
 		path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
 		if (!path) // not running
@@ -1552,13 +1530,11 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
 		if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
 			SYSERROR("Failed to attach %d to %s", (int)pid, fullpath);
 			free(fullpath);
-			free_handler_data(d);
 			return false;
 		}
 		free(fullpath);
 	}
 
-	free_handler_data(d);
 	return true;
 }
 
@@ -1570,7 +1546,6 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
 static int cgfsng_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
 {
 	char *subsystem, *p, *path;
-	struct cgfsng_handler_data *d;
 	struct hierarchy *h;
 	int ret = -1;
 
@@ -1583,20 +1558,13 @@ static int cgfsng_get(const char *filename, char *value, size_t len, const char
 	if (!path) // not running
 		return -1;
 
-	d = cgfsng_init(name);
-	if (!d) {
-		free(path);
-		return false;
-	}
-
-	h = get_hierarchy(d, subsystem);
+	h = get_hierarchy(subsystem);
 	if (h) {
 		char *fullpath = build_full_cgpath_from_monitorpath(h, path, filename);
 		ret = lxc_read_from_file(fullpath, value, len);
 		free(fullpath);
 	}
 
-	free_handler_data(d);
 	free(path);
 
 	return ret;
@@ -1610,7 +1578,6 @@ static int cgfsng_get(const char *filename, char *value, size_t len, const char
 static int cgfsng_set(const char *filename, const char *value, const char *name, const char *lxcpath)
 {
 	char *subsystem, *p, *path;
-	struct cgfsng_handler_data *d;
 	struct hierarchy *h;
 	int ret = -1;
 
@@ -1623,20 +1590,13 @@ static int cgfsng_set(const char *filename, const char *value, const char *name,
 	if (!path) // not running
 		return -1;
 
-	d = cgfsng_init(name);
-	if (!d) {
-		free(path);
-		return false;
-	}
-
-	h = get_hierarchy(d, subsystem);
+	h = get_hierarchy(subsystem);
 	if (h) {
 		char *fullpath = build_full_cgpath_from_monitorpath(h, path, filename);
 		ret = lxc_write_to_file(fullpath, value, strlen(value), false);
 		free(fullpath);
 	}
 
-	free_handler_data(d);
 	free(path);
 
 	return ret;
@@ -1657,7 +1617,7 @@ static int lxc_cgroup_set_data(const char *filename, const char *value, struct c
 	if ((p = strchr(subsystem, '.')) != NULL)
 		*p = '\0';
 
-	h = get_hierarchy(d, subsystem);
+	h = get_hierarchy(subsystem);
 	if (h) {
 		char *fullpath = must_make_path(h->fullcgpath, filename, NULL);
 		ret = lxc_write_to_file(fullpath, value, strlen(value), false);
@@ -1685,7 +1645,7 @@ static bool cgfsng_setup_limits(void *hdata, struct lxc_list *cgroup_settings,
 	}
 
 	if (do_devices) {
-		h = get_hierarchy(d, "devices");
+		h = get_hierarchy("devices");
 		if (!h) {
 			ERROR("No devices cgroup setup for %s", d->name);
 			return false;

From 74d4266f734b778dd2abdd03345a825c590ce38b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Fri, 8 Apr 2016 22:43:51 +0200
Subject: [PATCH 006/334] adapt lxc-attach tests & add test for pty logging

The current tests for lxc-attach pty allocation and I/O redirection rely on the
standard file descriptors of the test script to refer to a pty. If they do not
the tests are effectively useless with respect to pty allocation. We need a test
environment with the standard file descriptors refering to a pty as well. One
solution is to run this test under the script command.

This commit also adds a test whether pty logging works. This test is only
executed when all standard file descriptors refer to a pty.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/tests/lxc-test-lxc-attach | 70 +++++++++++++++++++++++++++++--------------
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/src/tests/lxc-test-lxc-attach b/src/tests/lxc-test-lxc-attach
index 664b028..27062e3 100755
--- a/src/tests/lxc-test-lxc-attach
+++ b/src/tests/lxc-test-lxc-attach
@@ -43,6 +43,8 @@ set -e
 #       stdout --> attached to pty
 #       stderr --> attached to pty
 
+allocate_pty="nopty"
+
 FAIL() {
 	echo -n "Failed " >&2
 	echo "$*" >&2
@@ -55,44 +57,53 @@ lxc-create -t busybox -n busy || FAIL "creating busybox container"
 lxc-start -n busy -d || FAIL "starting busybox container"
 lxc-wait -n busy -s RUNNING || FAIL "waiting for busybox container to run"
 
+if [ -t 0 ] && [ -t 1 ] && [ -t 2 ]; then
+	allocate_pty="pty"
+	echo "All standard file descriptors refer to a pty."
+	echo "Tests for lxc-attach pty allocation and I/O redirection"
+	echo "will be performed correctly."
+fi
+
 # stdin  --> attached to pty
 # stdout --> attached to pty
 # stderr --> attached to pty
-attach=$(lxc-attach -n busy -- hostname || FAIL " to allocate or setup pty")
-if [ "$attach" != "busy" ]; then
-        FAIL " simple attach"
-fi
+for i in `seq 1 100`; do
+	attach=$(lxc-attach -n busy -- hostname || FAIL "to allocate or setup pty")
+	if [ "$attach" != "busy" ]; then
+		FAIL "lxc-attach -n busy -- hostname"
+	fi
+done
 
 # stdin  --> /dev/null
 # stdout --> attached to pty
 # stderr --> attached to pty
-attach=$(lxc-attach -n busy -- hostname < /dev/null || FAIL " to allocate or setup pty")
+attach=$(lxc-attach -n busy -- hostname < /dev/null || FAIL "to allocate or setup pty")
 if [ "$attach" != "busy" ]; then
-        FAIL " lxc-attach -n busy -- hostname < /dev/null"
+        FAIL "lxc-attach -n busy -- hostname < /dev/null"
 fi
 
 # stdin  --> attached to pty
 # stdout --> /dev/null
 # stderr --> attached to pty
-attach=$(lxc-attach -n busy -- hostname > /dev/null || FAIL " to allocate or setup pty")
+attach=$(lxc-attach -n busy -- hostname > /dev/null || FAIL "to allocate or setup pty")
 if [ -n "$attach" ]; then
-        FAIL " lxc-attach -n busy -- hostname > /dev/null"
+        FAIL "lxc-attach -n busy -- hostname > /dev/null"
 fi
 
 # stdin  --> attached to pty
 # stdout --> attached to pty
 # stderr --> /dev/null
-attach=$(lxc-attach -n busy -- hostname 2> /dev/null || FAIL " to allocate or setup pty")
+attach=$(lxc-attach -n busy -- hostname 2> /dev/null || FAIL "to allocate or setup pty")
 if [ "$attach" != "busy" ]; then
-        FAIL " lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
+        FAIL "lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
 fi
 
 # stdin  --> /dev/null
 # stdout --> attached to pty
 # stderr --> /dev/null
-attach=$(lxc-attach -n busy -- hostname 2> /dev/null < /dev/null || FAIL " to allocate or setup pty")
+attach=$(lxc-attach -n busy -- hostname 2> /dev/null < /dev/null || FAIL "to allocate or setup pty")
 if [ "$attach" != "busy" ]; then
-        FAIL " lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
+        FAIL "lxc-attach -n busy -- hostname 2> /dev/null < /dev/null"
 fi
 
 # Use a synthetic reproducer in container to produce output on stderr. stdout on
@@ -103,9 +114,9 @@ fi
 # stdin  --> attached to pty
 # stdout --> /dev/null
 # stderr --> attached to pty
-attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null ) 2>&1 || FAIL " to allocate or setup pty")
+attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null ) 2>&1 || FAIL "to allocate or setup pty")
 if [ "$attach" != "busy" ]; then
-        FAIL " lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null"
+        FAIL "lxc-attach -n busy -- sh -c 'hostname >&2' > /dev/null"
 fi
 
 # Use a synthetic reproducer in container to produce output on stderr. stderr on
@@ -115,9 +126,9 @@ fi
 # stdin  --> attached to pty
 # stdout --> attach to pty
 # stderr --> /dev/null
-attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null ) 2>&1 || FAIL " to allocate or setup pty")
+attach=$( ( lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null ) 2>&1 || FAIL "to allocate or setup pty")
 if [ -n "$attach" ]; then
-        FAIL " lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null"
+        FAIL "lxc-attach -n busy -- sh -c 'hostname >&2' 2> /dev/null"
 fi
 
 
@@ -127,7 +138,7 @@ fi
 # (As we expect the exit code of the command to be 1 we ignore it.)
 attach=$(lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null || true)
 if [ -n "$attach" ]; then
-        FAIL " lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null"
+        FAIL "lxc-attach -n busy -- sh -c 'rm 2>&1' > /dev/null"
 fi
 
 
@@ -137,15 +148,15 @@ fi
 # (As we expect the exit code of the command to be 1 we ignore it.)
 attach=$(lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null || true)
 if [ -z "$attach" ]; then
-        FAIL " lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null"
+        FAIL "lxc-attach -n busy -- sh -c 'rm 2>&1' 2> /dev/null"
 fi
 
 # stdin  --> $in
 # stdout --> attached to pty
 # stderr --> attached to pty
-attach=$(echo hostname | lxc-attach -n busy -- || FAIL " to allocate or setup pty")
+attach=$(echo hostname | lxc-attach -n busy -- || FAIL "to allocate or setup pty")
 if [ "$attach" != "busy" ]; then
-        FAIL " echo hostname | lxc-attach -n busy --"
+        FAIL "echo hostname | lxc-attach -n busy --"
 fi
 
 # stdin  --> attached to pty
@@ -154,13 +165,15 @@ fi
 out=$(mktemp /tmp/out_XXXX)
 err=$(mktemp /tmp/err_XXXX)
 trap "rm -f $out $err" EXIT INT QUIT PIPE
-lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err || FAIL " to allocate or setup pty"
+lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err || FAIL "to allocate or setup pty"
 outcontent=$(cat $out)
 errcontent=$(cat $err)
 if [ "$outcontent" != "OUT" ] || [ "$errcontent" != "ERR" ]; then
-        FAIL " lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err"
+        FAIL "lxc-attach -n busy -- sh -c 'echo OUT; echo ERR >&2' > $out 2> $err"
 fi
 
+rm -f $out $err
+
 # stdin  --> $in
 # stdout --> $out
 # stderr --> $err
@@ -172,9 +185,20 @@ echo "hostname; rm" | lxc-attach -n busy > $out 2> $err || true
 outcontent=$(cat $out)
 errcontent=$(cat $err)
 if [ "$outcontent" != "busy" ] || [ -z "$errcontent" ]; then
-        FAIL " echo 'hostname; rm' | lxc-attach -n busy > $out 2> $err"
+        FAIL "echo 'hostname; rm' | lxc-attach -n busy > $out 2> $err"
 fi
 
+rm -f $out $err
+
+# Test whether logging pty output to a file works.
+trap "rm -f /tmp/ptylog" EXIT INT QUIT PIPE
+lxc-attach -n busy -L /tmp/ptylog -- hostname || FAIL "to allocate or setup pty"
+if [ $allocate_pty == "pty" ] && [ ! -s /tmp/ptylog ]; then
+        FAIL "lxc-attach -n busy -L /tmp/ptylog -- hostname"
+fi
+
+rm -f /tmp/ptylog
+
 lxc-destroy -n busy -f
 
 exit 0

From ad87e08c4e98ad271bb895a54efc5cd44b4b5249 Mon Sep 17 00:00:00 2001
From: staticfox <staticfox at staticfox.net>
Date: Mon, 11 Apr 2016 10:54:44 -0400
Subject: [PATCH 007/334] Ignore temporary files generated by doxygen

Signed-off-by: Matt Ullman <staticfox at staticfox.net>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 626fb8f..adc965e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -144,3 +144,4 @@ tags
 TAGS
 
 doc/api/doxygen_sqlite3.db
+doc/api/*.tmp

From 6ad1226343b309a6a54b54151b4dd2ad61004494 Mon Sep 17 00:00:00 2001
From: staticfox <staticfox at staticfox.net>
Date: Mon, 11 Apr 2016 10:36:37 -0400
Subject: [PATCH 008/334] Use size_t as an iteration point over int

This cleans up some sign-compare warnings as well as avoids any
possibilities of unintended signed offsets for indices during
iteration.

Signed-off-by: Matt Ullman <staticfox at staticfox.net>
---
 src/lxc/arguments.c       |  2 +-
 src/lxc/bdev/bdev.c       |  6 +++---
 src/lxc/bdev/lxcoverlay.c |  2 +-
 src/lxc/conf.c            |  3 ++-
 src/lxc/confile.c         | 11 ++++++-----
 src/lxc/network.c         |  2 +-
 src/lxc/nl.c              |  2 +-
 src/lxc/parse.c           |  2 +-
 src/lxc/utils.c           |  2 +-
 9 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/lxc/arguments.c b/src/lxc/arguments.c
index e021143..c2f7b67 100644
--- a/src/lxc/arguments.c
+++ b/src/lxc/arguments.c
@@ -40,7 +40,7 @@ static int build_shortopts(const struct option *a_options,
 			   char *a_shortopts, size_t a_size)
 {
 	const struct option *opt;
-	int i = 0;
+	size_t i = 0;
 
 	if (!a_options || !a_shortopts || !a_size)
 		return -1;
diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 6b29115..1534cc9 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -823,7 +823,7 @@ static struct bdev *do_bdev_create(const char *dest, const char *type,
 
 static struct bdev *bdev_get(const char *type)
 {
-	int i;
+	size_t i;
 	struct bdev *bdev;
 
 	for (i = 0; i < numbdevs; i++) {
@@ -843,7 +843,7 @@ static struct bdev *bdev_get(const char *type)
 
 static const struct bdev_type *get_bdev_by_name(const char *name)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < numbdevs; i++) {
 		if (strcmp(bdevs[i].name, name) == 0)
@@ -856,7 +856,7 @@ static const struct bdev_type *get_bdev_by_name(const char *name)
 
 static const struct bdev_type *bdev_query(struct lxc_conf *conf, const char *src)
 {
-	int i;
+	size_t i;
 
 	if (conf->rootfs.bdev_type)
 		return get_bdev_by_name(conf->rootfs.bdev_type);
diff --git a/src/lxc/bdev/lxcoverlay.c b/src/lxc/bdev/lxcoverlay.c
index 86181d9..3caadbc 100644
--- a/src/lxc/bdev/lxcoverlay.c
+++ b/src/lxc/bdev/lxcoverlay.c
@@ -569,7 +569,7 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
 	char old_upper[MAXPATHLEN];
 	char old_work[MAXPATHLEN];
 	char *cleanpath = NULL;
-	int i;
+	size_t i;
 	int fret = -1;
 	int ret = 0;
 	struct lxc_list *iterator;
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 3b023ef..e8dfaae 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1989,7 +1989,8 @@ static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list
 static int parse_cap(const char *cap)
 {
 	char *ptr = NULL;
-	int i, capid = -1;
+	size_t i;
+	int capid = -1;
 
 	if (!strcmp(cap, "none"))
 		return -2;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 7f34164..8c366c8 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -274,7 +274,7 @@ static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
 
 extern struct lxc_config_t *lxc_getconfig(const char *key)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < config_size; i++)
 		if (!strncmp(config[i].name, key,
@@ -297,7 +297,8 @@ extern struct lxc_config_t *lxc_getconfig(const char *key)
 
 int lxc_listconfigs(char *retv, int inlen)
 {
-	int i, fulllen = 0, len;
+	size_t i;
+	int fulllen = 0, len;
 
 	if (!retv)
 		inlen = 0;
@@ -607,7 +608,7 @@ static int macvlan_mode(int *valuep, const char *value)
 		{ "passthru", MACVLAN_MODE_PASSTHRU },
 	};
 
-	int i;
+	size_t i;
 
 	for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
 		if (strcmp(m[i].name, value))
@@ -1350,7 +1351,7 @@ static int rt_sig_num(const char *signame)
 }
 
 static int sig_parse(const char *signame) {
-	int n;
+	size_t n;
 
 	if (isdigit(*signame)) {
 		return sig_num(signame);
@@ -2055,7 +2056,7 @@ signed long lxc_config_parse_arch(const char *arch)
 	};
 	size_t len = sizeof(pername) / sizeof(pername[0]);
 
-	int i;
+	size_t i;
 
 	for (i = 0; i < len; i++) {
 		if (!strcmp(pername[i].name, arch))
diff --git a/src/lxc/network.c b/src/lxc/network.c
index 31c82bb..86c3ee5 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -1507,7 +1507,7 @@ static const char padchar[] =
 char *lxc_mkifname(char *template)
 {
 	char *name = NULL;
-	int i = 0;
+	size_t i = 0;
 	FILE *urandom;
 	unsigned int seed;
 	struct ifaddrs *ifaddr, *ifa;
diff --git a/src/lxc/nl.c b/src/lxc/nl.c
index 19a3a6c..f194efc 100644
--- a/src/lxc/nl.c
+++ b/src/lxc/nl.c
@@ -54,7 +54,7 @@ static int nla_put(struct nlmsg *nlmsg, int attr,
 	struct rtattr *rta;
 	size_t rtalen = RTA_LENGTH(len);
 	size_t tlen = NLMSG_ALIGN(nlmsg->nlmsghdr->nlmsg_len) + RTA_ALIGN(rtalen);
-	
+
 	if (tlen > nlmsg->cap)
 		return -ENOMEM;
 
diff --git a/src/lxc/parse.c b/src/lxc/parse.c
index 5852ca4..b8eef7f 100644
--- a/src/lxc/parse.c
+++ b/src/lxc/parse.c
@@ -66,7 +66,7 @@ int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
 
 int lxc_char_left_gc(const char *buffer, size_t len)
 {
-	int i;
+	size_t i;
 	for (i = 0; i < len; i++) {
 		if (buffer[i] == ' ' ||
 		    buffer[i] == '\t')
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 61567e3..5c35ae8 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -941,7 +941,7 @@ void **lxc_append_null_to_array(void **array, size_t count)
 	if (count) {
 		temp = realloc(array, (count + 1) * sizeof(*array));
 		if (!temp) {
-			int i;
+			size_t i;
 			for (i = 0; i < count; i++)
 				free(array[i]);
 			free(array);

From 0627ac1559958a6161579f0d2647326b92027652 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Mon, 11 Apr 2016 17:13:16 +0200
Subject: [PATCH 009/334] lxc-create: fix -B best option

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_create.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
index 0634397..5fd5a29 100644
--- a/src/lxc/lxc_create.c
+++ b/src/lxc/lxc_create.c
@@ -241,7 +241,9 @@ int main(int argc, char *argv[])
 		my_args.bdevtype = "dir";
 
 	// Final check whether the user gave use a valid bdev type.
-	if (!is_valid_bdev_type(my_args.bdevtype) && strcmp(my_args.bdevtype, "_unset")) {
+	if (strcmp(my_args.bdevtype, "best") &&
+	    strcmp(my_args.bdevtype, "_unset") &&
+	    !is_valid_bdev_type(my_args.bdevtype)) {
 		fprintf(stderr, "%s is not a valid backing storage type.\n", my_args.bdevtype);
 		exit(EXIT_FAILURE);
 	}

From 54e478606b53e5983aba84c1f6619d55923ff605 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Mon, 11 Apr 2016 18:13:09 +0200
Subject: [PATCH 010/334] lxc-attach: add logging option to manpage

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 doc/lxc-attach.sgml.in | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/doc/lxc-attach.sgml.in b/doc/lxc-attach.sgml.in
index c1937d9..2b7203f 100644
--- a/doc/lxc-attach.sgml.in
+++ b/doc/lxc-attach.sgml.in
@@ -58,6 +58,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
+      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -235,6 +236,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 	</listitem>
       </varlistentry>
 
+      <varlistentry>
+	<term>
+	  <option>-L, --pty-log <replaceable>file</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	Specify a file where the output of <command>lxc-attach</command> will be
+	logged.
+	  </para>
+	  <para>
+	    <emphasis>Important:</emphasis>  When a standard file descriptor
+	    does not refer to a pty ouput produced on it will not be logged.
+	  </para>
+	</listitem>
+      </varlistentry>
+
      </variablelist>
 
   </refsect1>

From 3421ec289d783cb5d9f3dada429ad2860ede7ee2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Mon, 11 Apr 2016 23:57:29 +0200
Subject: [PATCH 011/334] lxc-destroy: avoid double print

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_destroy.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/lxc/lxc_destroy.c b/src/lxc/lxc_destroy.c
index c6e3454..b521739 100644
--- a/src/lxc/lxc_destroy.c
+++ b/src/lxc/lxc_destroy.c
@@ -18,16 +18,18 @@
  */
 
 #define _GNU_SOURCE
-#include <lxc/lxccontainer.h>
+#include "config.h"
 
-#include <stdio.h>
 #include <libgen.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 
-#include "lxc.h"
-#include "log.h"
+#include <lxc/lxccontainer.h>
+
 #include "arguments.h"
+#include "log.h"
+#include "lxc.h"
 #include "utils.h"
 
 lxc_log_define(lxc_destroy_ui, lxc);
@@ -251,9 +253,6 @@ static bool do_destroy_with_snapshots(struct lxc_container *c)
 	else
 		bret = do_destroy(c);
 
-	if (bret && !quiet)
-		printf("Destroyed container %s including snapshots \n", my_args.name);
-
 	return bret;
 }
 

From 3dfe1009b4dd157ab70d8101c12cd9e76109118d Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Tue, 12 Apr 2016 19:20:10 +0200
Subject: [PATCH 012/334] nicer date format and support for SOURCE_DATE_EPOCH
 in LXC_GENERATE_DATE

Using $(date) for LXC_GENERATE_DATE has various flaws:
* formating depends on the locale of the system we execute configure on
* the output is not really a date but more a timestamp

Let's use $(date --utc '+%Y-%m-%d') instead.

While at it, also support SOURCE_DATE_EPOCH [1] to make the build
reproducible

[1] https://reproducible-builds.org/specs/source-date-epoch/

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 84f8699..9475b0e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -545,7 +545,7 @@ AS_AC_EXPAND(LXC_DEFAULT_CONFIG, "$sysconfdir/lxc/default.conf")
 AS_AC_EXPAND(DATADIR, "$datadir")
 AS_AC_EXPAND(LOCALSTATEDIR, "$localstatedir")
 AS_AC_EXPAND(DOCDIR, "$docdir")
-AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date)")
+AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date --utc --date=@${SOURCE_DATE_EPOCH:-$(date +%s)} '+%Y-%m-%d')")
 AS_AC_EXPAND(LXCPATH, "$with_config_path")
 AS_AC_EXPAND(LXC_GLOBAL_CONF, "$with_global_conf")
 AS_AC_EXPAND(LXC_USERNIC_CONF, "$with_usernic_conf")

From de3c507c777e322a13724c9fdf4fb85df8a7d31f Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn at ubuntu.com>
Date: Tue, 12 Apr 2016 12:34:28 -0500
Subject: [PATCH 013/334] cgfsng: don't require that systemd subsystem be
 mounted

Note that is_crucial_subsystem still lists name=systemd.  That is
used in cgfs and cgmanager.  Cgmanager is typically setup to create
name=systemd, so it is ok.  cgfs uses is_crucial_subsystem() only
to decide whether failure to create or chown a directory should be
terminal.  That's ok, because (a) if name=systemd is not mounted then
we won't hit that, and (b) if name=systemd is mounted, then we'd
really still like to set it up for containers.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/cgfsng.c | 9 ++-------
 src/lxc/cgroup.c | 7 ++++++-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/lxc/cgfsng.c b/src/lxc/cgfsng.c
index fad0be4..1e72347 100644
--- a/src/lxc/cgfsng.c
+++ b/src/lxc/cgfsng.c
@@ -407,19 +407,14 @@ static bool controller_found(struct hierarchy **hlist, char *entry)
 }
 
 /*
- * Return true if all of the controllers which we require have been
- * found.  The required list is systemd, freezer, and anything in
- * lxc.cgroup.use.
+ * Return true if all of the controllers which we require have been found.
+ * The required list is  freezer and anything in * lxc.cgroup.use.
  */
 static bool all_controllers_found(void)
 {
 	char *p, *saveptr = NULL;
 	struct hierarchy ** hlist = hierarchies;
 
-	if (!controller_found(hlist, "name=systemd")) {
-		ERROR("no systemd controller mountpoint found");
-		return false;
-	}
 	if (!controller_found(hlist, "freezer")) {
 		ERROR("no freezer controller mountpoint found");
 		return false;
diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index 1a92ef4..91ef359 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -226,7 +226,12 @@ void prune_init_scope(char *cg)
 
 /*
  * Return true if this is a subsystem which we cannot do
- * without
+ * without.
+ *
+ * systemd is questionable here.  The way callers currently
+ * use this, if systemd is not mounted then it will be ignored.
+ * But if systemd is mounted, then it must be setup so that lxc
+ * can create cgroups in it, else containers will fail.
  */
 bool is_crucial_cgroup_subsystem(const char *s)
 {

From d683847986364025be2eb9b70e59491425e4fd16 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Wed, 13 Apr 2016 15:23:35 +0200
Subject: [PATCH 014/334] lxc-attach: error on -L/--pty-log + redirection

pty logging only works correctly when stdout and stderr refer to a pty. If they
do not, we do not dup2() them and lxc_console_cb_con() will never write to the
corresponding log file descriptor.

When redirection on stdout and stderr is used we can safely assume that the user
is already logging to a file or /dev/null and creating an additional pty log
doesn't seem to make sense.

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_attach.c | 56 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 20 deletions(-)

diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index ed3ba0d..58f658b 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -21,7 +21,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define _GNU_SOURCE
+#include "config.h"
+
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -38,7 +39,6 @@
 #include "attach.h"
 #include "arguments.h"
 #include "caps.h"
-#include "config.h"
 #include "confile.h"
 #include "console.h"
 #include "log.h"
@@ -254,7 +254,7 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 	INFO("Trying to allocate a pty on the host");
 
 	if (!isatty(args->ptyfd)) {
-		ERROR("stdin is not a tty");
+		ERROR("Standard file descriptor does not refer to a pty\n.");
 		return -1;
 	}
 
@@ -324,28 +324,40 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 	return ret;
 }
 
+static int stdfd_is_pty(void)
+{
+	if (isatty(STDIN_FILENO))
+		return STDIN_FILENO;
+	if (isatty(STDOUT_FILENO))
+		return STDOUT_FILENO;
+	if (isatty(STDERR_FILENO))
+		return STDERR_FILENO;
+
+	return -1;
+}
+
 int main(int argc, char *argv[])
 {
-	int ret = -1;
+	int ret = -1, r;
 	int wexit = 0;
 	pid_t pid;
 	lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
 	lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL};
 
-	ret = lxc_caps_init();
-	if (ret)
+	r = lxc_caps_init();
+	if (r)
 		exit(EXIT_FAILURE);
 
-	ret = lxc_arguments_parse(&my_args, argc, argv);
-	if (ret)
+	r = lxc_arguments_parse(&my_args, argc, argv);
+	if (r)
 		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
-	ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
+	r = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			   my_args.progname, my_args.quiet, my_args.lxcpath[0]);
-	if (ret)
+	if (r)
 		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
@@ -388,19 +400,23 @@ int main(int argc, char *argv[])
 		command.argv = (char**)my_args.argv;
 	}
 
-	if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)) {
-		struct wrapargs wrap = (struct wrapargs){
-			.command = &command,
+	struct wrapargs wrap = (struct wrapargs){
+		.command = &command,
 			.options = &attach_options
-		};
-		if (isatty(STDIN_FILENO))
-			wrap.ptyfd = STDIN_FILENO;
-		else if (isatty(STDOUT_FILENO))
-			wrap.ptyfd = STDOUT_FILENO;
-		else if (isatty(STDERR_FILENO))
-			wrap.ptyfd = STDERR_FILENO;
+	};
+
+	wrap.ptyfd = stdfd_is_pty();
+	if (wrap.ptyfd >= 0) {
+		if ((!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) && my_args.console_log) {
+			fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n");
+			goto out;
+		}
 		ret = get_pty_on_host(c, &wrap, &pid);
 	} else {
+		if (my_args.console_log) {
+			fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n");
+			goto out;
+		}
 		if (command.program)
 			ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid);
 		else

From e6487e89824c184f99bf3478122aa3bc2bed86d8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Wed, 13 Apr 2016 15:41:58 +0200
Subject: [PATCH 015/334] only execute last test when we are a pty

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/tests/lxc-test-lxc-attach | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/tests/lxc-test-lxc-attach b/src/tests/lxc-test-lxc-attach
index 27062e3..380a6db 100755
--- a/src/tests/lxc-test-lxc-attach
+++ b/src/tests/lxc-test-lxc-attach
@@ -190,14 +190,16 @@ fi
 
 rm -f $out $err
 
-# Test whether logging pty output to a file works.
-trap "rm -f /tmp/ptylog" EXIT INT QUIT PIPE
-lxc-attach -n busy -L /tmp/ptylog -- hostname || FAIL "to allocate or setup pty"
-if [ $allocate_pty == "pty" ] && [ ! -s /tmp/ptylog ]; then
-        FAIL "lxc-attach -n busy -L /tmp/ptylog -- hostname"
-fi
+if [ $allocate_pty = "pty" ]; then
+	# Test whether logging pty output to a file works.
+	trap "rm -f /tmp/ptylog" EXIT INT QUIT PIPE
+	lxc-attach -n busy -L /tmp/ptylog -- hostname || FAIL "to allocate or setup pty"
+	if [ ! -s /tmp/ptylog ]; then
+		FAIL "lxc-attach -n busy -L /tmp/ptylog -- hostname"
+	fi
 
-rm -f /tmp/ptylog
+	rm -f /tmp/ptylog
+fi
 
 lxc-destroy -n busy -f
 

From 66188b02b8009075a2e0e2b89a14688c50565bf4 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Wed, 13 Apr 2016 17:54:55 +0200
Subject: [PATCH 016/334] add missing lsb headers to sysvinit scripts

original patch by Daniel Baumann

closes #308

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/sysvinit/lxc-containers.in | 4 ++++
 config/init/sysvinit/lxc-net.in        | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/config/init/sysvinit/lxc-containers.in b/config/init/sysvinit/lxc-containers.in
index 7a55c3b..f4ce8ea 100644
--- a/config/init/sysvinit/lxc-containers.in
+++ b/config/init/sysvinit/lxc-containers.in
@@ -7,6 +7,10 @@
 #
 ### BEGIN INIT INFO
 # Provides: lxc
+# Required-Start: $syslog $remote_fs
+# Required-Stop: $syslog $remote_fs
+# Should-Start:
+# Should-Stop:
 # Default-Start: 2 3 4 5
 # Default-Stop: 0 1 6
 # Short-Description: Bring up/down LXC autostart containers
diff --git a/config/init/sysvinit/lxc-net.in b/config/init/sysvinit/lxc-net.in
index f6892c1..95be399 100644
--- a/config/init/sysvinit/lxc-net.in
+++ b/config/init/sysvinit/lxc-net.in
@@ -7,6 +7,10 @@
 #
 ### BEGIN INIT INFO
 # Provides: lxc-net
+# Required-Start: $syslog $remote_fs
+# Required-Stop: $syslog $remote_fs
+# Should-Start:
+# Should-Stop:
 # Default-Start: 2 3 4 5
 # Default-Stop: 1
 # Short-Description: Bring up/down LXC Network Bridge

From 8d3b3b77bb00c9a0998f1a02ae7cd57fbf7d99c6 Mon Sep 17 00:00:00 2001
From: Aron Podrigal <aronp at guaranteedplus.com>
Date: Thu, 14 Apr 2016 00:21:08 -0400
Subject: [PATCH 017/334] Fixed python-lxc reference to var before assignment

```
>>> c = lxc.Container('ct')
>>> c.create('debian', args=('-r', 'jessie'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/lxc/__init__.py", line 229, in
create
    template_args['args'] = tuple(tmp_args)
UnboundLocalError: local variable 'tmp_args' referenced before
assignment
```

Signed-off-by: Aron Podrigal <aronp at guaranteedplus.com>
---
 src/python-lxc/lxc/__init__.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/python-lxc/lxc/__init__.py b/src/python-lxc/lxc/__init__.py
index 30ebd1b..de02102 100644
--- a/src/python-lxc/lxc/__init__.py
+++ b/src/python-lxc/lxc/__init__.py
@@ -222,11 +222,12 @@ def create(self, template=None, flags=0, args=(), bdevtype=None):
             for item in args.items():
                 tmp_args.append("--%s" % item[0])
                 tmp_args.append("%s" % item[1])
+            args = tmp_args
         template_args = {}
         if template:
     	    template_args['template'] = template
         template_args['flags'] = flags
-        template_args['args'] = tuple(tmp_args)
+        template_args['args'] = tuple(args)
         if bdevtype:
             template_args['bdevtype'] = bdevtype
         return _lxc.Container.create(self, **template_args)

From 0eb12ed50454dc5310fd415ecd36ab77d4895aa0 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Thu, 14 Apr 2016 18:03:29 +0200
Subject: [PATCH 018/334] drop obsolete syslog.target from lxc.service.in

the target is obsolete since systemd v38 which everybody should have.

original patch by Daniel Baumann

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/systemd/lxc.service.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/init/systemd/lxc.service.in b/config/init/systemd/lxc.service.in
index 3b49c75..fd26e83 100644
--- a/config/init/systemd/lxc.service.in
+++ b/config/init/systemd/lxc.service.in
@@ -1,6 +1,6 @@
 [Unit]
 Description=LXC Container Initialization and Autoboot Code
-After=syslog.target network.target lxc-net.service
+After=network.target lxc-net.service
 Wants=lxc-net.service
 
 [Service]

From 02fdb536a98e116232548dff6c2faed849e8796f Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Fri, 15 Apr 2016 20:45:09 +0200
Subject: [PATCH 019/334] don't make sysv init scripts dependant on
 distribution specifics

- /etc(/rc.d)?/init.d/functions does not exist on all distributions
- LSB does not define a message function without an explicit status
- Debian-derived systems add a log_daemon_msg for that

lets define an own log_daemon_msg as echo and try to load LSB init
functions afterwards, which might overload it with a nicer version

that way the init scripts should work on any system, without hard
dependencies on neither LSB nor /etc/init.d/functions

Closes #309 #310 #311

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/sysvinit/lxc-containers.in | 28 ++++++++++++----------------
 config/init/sysvinit/lxc-net.in        | 28 ++++++++++++----------------
 2 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/config/init/sysvinit/lxc-containers.in b/config/init/sysvinit/lxc-containers.in
index f4ce8ea..3b38393 100644
--- a/config/init/sysvinit/lxc-containers.in
+++ b/config/init/sysvinit/lxc-containers.in
@@ -17,30 +17,26 @@
 # Description: Bring up/down LXC autostart containers
 ### END INIT INFO
 
-sysconfdir="@SYSCONFDIR@"
-
-# Source function library.
-test ! -r "$sysconfdir"/rc.d/init.d/functions ||
-        . "$sysconfdir"/rc.d/init.d/functions
+# To be replaced by LSB functions, if they can be found
+# Defined here for distributions that don't have log_daemon_msg
+log_daemon_msg () {
+    echo $@
+}
 
-# provide action() fallback
-if ! type action >/dev/null 2>&1; then
-    # Real basic fallback for sysvinit "action" verbage.
-    action() {
-        echo -n "$1	"
-        shift
-        "$@" && echo "OK" || echo "Failed"
-    }
-fi
+# Try to source LSB init functions to define LSB log_* functions.
+test ! -r /lib/lsb/init-functions ||
+        . /lib/lsb/init-functions
 
 start() {
     # Setup host /dev for autodev containers.
     @LIBEXECDIR@/lxc/lxc-devsetup
-    action $"Starting LXC autoboot containers: " @LIBEXECDIR@/lxc/lxc-containers start
+    log_daemon_msg "Starting LXC autoboot containers: "
+    @LIBEXECDIR@/lxc/lxc-containers start
 }
 
 stop() {
-    action $"Stopping LXC containers: " @LIBEXECDIR@/lxc/lxc-containers stop
+    log_daemon_msg "Stopping LXC containers: "
+    @LIBEXECDIR@/lxc/lxc-containers stop
 }
 
 # See how we were called.
diff --git a/config/init/sysvinit/lxc-net.in b/config/init/sysvinit/lxc-net.in
index 95be399..187feed 100644
--- a/config/init/sysvinit/lxc-net.in
+++ b/config/init/sysvinit/lxc-net.in
@@ -17,28 +17,24 @@
 # Description: Bring up/down LXC Network Bridge
 ### END INIT INFO
 
-sysconfdir="@SYSCONFDIR@"
-
-# Source function library.
-test ! -r "$sysconfdir"/rc.d/init.d/functions ||
-        . "$sysconfdir"/rc.d/init.d/functions
+# To be replaced by LSB functions, if they can be found
+# Defined here for distributions that don't have log_daemon_msg
+log_daemon_msg () {
+    echo $@
+}
 
-# provide action() fallback
-if ! type action >/dev/null 2>&1; then
-    # Real basic fallback for sysvinit "action" verbage.
-    action() {
-        echo -n "$1	"
-        shift
-        "$@" && echo "OK" || echo "Failed"
-    }
-fi
+# Try to source LSB init functions to define LSB log_* functions.
+test ! -r /lib/lsb/init-functions ||
+        . /lib/lsb/init-functions
 
 start() {
-    action $"Starting LXC network bridge: " @LIBEXECDIR@/lxc/lxc-net start
+    log_daemon_msg "Starting LXC network bridge: "
+    @LIBEXECDIR@/lxc/lxc-net start
 }
 
 stop() {
-    action $"Stopping LXC network bridge: " @LIBEXECDIR@/lxc/lxc-net stop
+    log_daemon_msg "Stopping LXC network bridge: "
+    @LIBEXECDIR@/lxc/lxc-net stop
 }
 
 # See how we were called.

From 3aec413b1db19ba45ef0c5cd3c5a05c76ffeda4c Mon Sep 17 00:00:00 2001
From: "Andrey Jr. Melnikov" <temnota.am at gmail.com>
Date: Mon, 18 Apr 2016 19:16:08 +0300
Subject: [PATCH 020/334] Switch console pty to raw mode. Without this some
 ncurses-based programs behave incorrectly

Signed-off-by: Andrey Jr. Melnikov <temnota.am at gmail.com>
---
 src/lxc/console.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index a346377..c6f6adc 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -262,9 +262,10 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
 
 	/* Remove the echo characters and signal reception, the echo
 	 * will be done with master proxying */
-	newtios.c_iflag &= ~IGNBRK;
+	newtios.c_iflag &= ~(IGNBRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
 	newtios.c_iflag &= BRKINT;
-	newtios.c_lflag &= ~(ECHO|ICANON|ISIG);
+	newtios.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN|ECHOE|ECHOK|ECHONL);
+	newtios.c_oflag &= ~OPOST;
 	newtios.c_cc[VMIN] = 1;
 	newtios.c_cc[VTIME] = 0;
 

From 41d080b9c523087b07db577552d7aa261064eb75 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Tue, 19 Apr 2016 15:17:19 +0200
Subject: [PATCH 021/334] use raw settings of ssh for pty

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index c6f6adc..6d335ca 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -260,16 +260,21 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
 
 	newtios = *oldtios;
 
-	/* Remove the echo characters and signal reception, the echo
-	 * will be done with master proxying */
-	newtios.c_iflag &= ~(IGNBRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
-	newtios.c_iflag &= BRKINT;
-	newtios.c_lflag &= ~(ECHO|ICANON|ISIG|IEXTEN|ECHOE|ECHOK|ECHONL);
+	/* We use the same settings that ssh does. */
+	newtios.c_iflag |= IGNPAR;
+	newtios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
+#ifdef IUCLC
+	newtios.c_iflag &= ~IUCLC;
+#endif
+	newtios.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
+#ifdef IEXTEN
+	newtios.c_lflag &= ~IEXTEN;
+#endif
 	newtios.c_oflag &= ~OPOST;
 	newtios.c_cc[VMIN] = 1;
 	newtios.c_cc[VTIME] = 0;
 
-	/* Set new attributes */
+	/* Set new attributes. */
 	if (tcsetattr(fd, TCSAFLUSH, &newtios)) {
 		ERROR("failed to set new terminal settings");
 		return -1;

From 222306afba0067f99acf422728196b5e8122f760 Mon Sep 17 00:00:00 2001
From: Leonid Isaev <leonid.isaev at jila.colorado.edu>
Date: Thu, 21 Apr 2016 13:20:39 -0600
Subject: [PATCH 022/334] Initialize a pointer in split_init_cmd() to avoid gcc
 warnings

gcc -Wall warns about uninitialized variables (-Wmaybe-uninitialized), and
-Werror makes it fatal. This change allows the build to succeed by NULL'ifying
the pointer passed to strtok_r().

Note that strtok_r(3) anyway ignores a non-NULL arg3 pointer on the 1st call
with non-NULL arg1 string.

Signed-off-by: Leonid Isaev <leonid.isaev at jila.colorado.edu>
Acked-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/lxccontainer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 9f12ca2..50cfc69 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -670,7 +670,7 @@ static char **split_init_cmd(const char *incmd)
 {
 	size_t len;
 	int nargs = 0;
-	char *copy, *p, *saveptr;
+	char *copy, *p, *saveptr = NULL;
 	char **argv;
 
 	if (!incmd)

From 4a060c9eec38c00ab6cf7fe578a820b37bdb2649 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Sun, 24 Apr 2016 18:34:15 -0400
Subject: [PATCH 023/334] Update maintainers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index c5ac900..6e126c1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4,7 +4,7 @@ conforming with the DCO contained in the ./CONTRIBUTING file.
 Maintainer
 ----------
 
-Committers              : Daniel Lezcano (inactive), Serge Hallyn, Stéphane Graber and Dwight Engen
+Committers              : Serge Hallyn, Stéphane Graber, Dwight Engen and Christian Brauner
 Mail patches to         : lxc-devel at lists.linuxcontainers.org
 Send pull requests at   : https://github.com/lxc/lxc
 Mailing lists           : lxc-devel at lists.linuxcontainers.org, lxc-users at lists.linuxcontainers.org

From b1b14a4e3e215e228d09d99911603b25b98049b7 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Mon, 25 Apr 2016 19:30:03 +0900
Subject: [PATCH 024/334] doc: Add logging option to Japanese lxc-attach(1)

Update for commit f43d63b

Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 doc/ja/lxc-attach.sgml.in | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/doc/ja/lxc-attach.sgml.in b/doc/ja/lxc-attach.sgml.in
index 7f28b62..2a8d5b6 100644
--- a/doc/ja/lxc-attach.sgml.in
+++ b/doc/ja/lxc-attach.sgml.in
@@ -63,6 +63,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
+      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -311,6 +312,28 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
 	</listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>
+          <option>-L, --pty-log <replaceable>file</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+            <!--
+            Specify a file where the output of <command>lxc-attach</command> will be
+            logged.
+              -->
+            <command>lxc-attach</command> の出力を記録するファイルを指定します。
+          </para>
+          <para>
+            <!--
+            <emphasis>Important:</emphasis>  When a standard file descriptor
+            does not refer to a pty ouput produced on it will not be logged.
+            -->
+            <emphasis>重要:</emphasis> 標準ファイルディスクリプタが pty を参照していない場合、それらに対する出力は記録されないでしょう。
+          </para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>

From 65fcb7586ee712decd281385224bb328232da35e Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Wed, 27 Apr 2016 14:27:51 +0200
Subject: [PATCH 025/334] lxc-ls: use fewer syscalls when doing ipc

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_ls.c | 178 +++++++++++++++++++++++--------------------------------
 1 file changed, 73 insertions(+), 105 deletions(-)

diff --git a/src/lxc/lxc_ls.c b/src/lxc/lxc_ls.c
index 1a9969a..97c5d46 100644
--- a/src/lxc/lxc_ls.c
+++ b/src/lxc/lxc_ls.c
@@ -103,6 +103,8 @@ static char *ls_get_config_item(struct lxc_container *c, const char *item,
 		bool running);
 static char *ls_get_groups(struct lxc_container *c, bool running);
 static char *ls_get_ips(struct lxc_container *c, const char *inet);
+static int ls_recv_str(int fd, char **buf);
+static int ls_send_str(int fd, const char *buf);
 struct wrapargs {
 	const struct lxc_arguments *args;
 	char **grps_must;
@@ -146,14 +148,9 @@ static void ls_print_table(struct ls *l, struct lengths *lht,
 /*
  * id can only be 79 + \0 chars long.
  */
-static int ls_read_and_grow_buf(const int rpipefd, char **save_buf,
-		const char *id, ssize_t nbytes_id,
-		char **read_buf, ssize_t *read_buf_len);
 static int ls_remove_lock(const char *path, const char *name,
 		char **lockpath, size_t *len_lockpath, bool recalc);
 static int ls_serialize(int wpipefd, struct ls *n);
-static int ls_write(const int wpipefd, const char *id, ssize_t nbytes_id,
-		const char *s);
 static int my_parser(struct lxc_arguments *args, int c, char *arg);
 
 static const struct option my_longopts[] = {
@@ -483,7 +480,7 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
 		if (args->ls_nesting && running) {
 			struct wrapargs wargs = (struct wrapargs){.args = NULL};
 			/* Open a socket so that the child can communicate with us. */
-			check = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, wargs.pipefd);
+			check = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wargs.pipefd);
 			if (check == -1)
 				goto put_and_next;
 
@@ -1004,67 +1001,86 @@ static int ls_remove_lock(const char *path, const char *name,
 	return 0;
 }
 
+static int ls_send_str(int fd, const char *buf)
+{
+	size_t slen = 0;
+	if (buf)
+		slen = strlen(buf);
+	if (lxc_write_nointr(fd, &slen, sizeof(slen)) != sizeof(slen))
+		return -1;
+	if (slen > 0) {
+		if (lxc_write_nointr(fd, buf, slen) != (ssize_t)slen)
+			return -1;
+	}
+	return 0;
+}
+
 static int ls_serialize(int wpipefd, struct ls *n)
 {
 	ssize_t nbytes = sizeof(n->ram);
-	if (lxc_write_nointr(wpipefd, &n->ram, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->ram, (size_t)nbytes) != nbytes)
 		return -1;
 
 	nbytes = sizeof(n->swap);
-	if (lxc_write_nointr(wpipefd, &n->swap, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->swap, (size_t)nbytes) != nbytes)
 		return -1;
 
 	nbytes = sizeof(n->init);
-	if (lxc_write_nointr(wpipefd, &n->init, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->init, (size_t)nbytes) != nbytes)
 		return -1;
 
 	nbytes = sizeof(n->autostart);
-	if (lxc_write_nointr(wpipefd, &n->autostart, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->autostart, (size_t)nbytes) != nbytes)
 		return -1;
 
 	nbytes = sizeof(n->running);
-	if (lxc_write_nointr(wpipefd, &n->running, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->running, (size_t)nbytes) != nbytes)
 		return -1;
 
 	nbytes = sizeof(n->nestlvl);
-	if (lxc_write_nointr(wpipefd, &n->nestlvl, nbytes) != nbytes)
+	if (lxc_write_nointr(wpipefd, &n->nestlvl, (size_t)nbytes) != nbytes)
 		return -1;
 
-	if (ls_write(wpipefd, "NAME:", 5 + 1, n->name) == -1)
+	/* NAME */
+	if (ls_send_str(wpipefd, n->name) < 0)
 		return -1;
 
-	if (ls_write(wpipefd, "STATE:", 6 + 1, n->state) == -1)
+	/* STATE */
+	if (ls_send_str(wpipefd, n->state) < 0)
 		return -1;
 
-	if (ls_write(wpipefd, "GROUPS:", 7 + 1, n->groups) == -1)
+	/* GROUPS */
+	if (ls_send_str(wpipefd, n->groups) < 0)
 		return -1;
 
-	if (ls_write(wpipefd, "INTERFACE:", 10 + 1, n->interface) == -1)
+	/* INTERFACE */
+	if (ls_send_str(wpipefd, n->interface) < 0)
 		return -1;
 
-	if (ls_write(wpipefd, "IPV4:", 5 + 1, n->ipv4) == -1)
+	/* IPV4 */
+	if (ls_send_str(wpipefd, n->ipv4) < 0)
 		return -1;
 
-	if (ls_write(wpipefd, "IPV6:", 5 + 1, n->ipv6) == -1)
+	/* IPV6 */
+	if (ls_send_str(wpipefd, n->ipv6) < 0)
 		return -1;
 
 	return 0;
 }
 
-static int ls_write(const int wpipefd, const char *id, ssize_t nbytes_id,
-		const char *s)
+static int ls_recv_str(int fd, char **buf)
 {
-	if (lxc_write_nointr(wpipefd, id, nbytes_id) != nbytes_id)
+	size_t slen = 0;
+	if (lxc_read_nointr(fd, &slen, sizeof(slen)) != sizeof(slen))
 		return -1;
-	if (s) {
-		nbytes_id = strlen(s) + 1;
-		if (lxc_write_nointr(wpipefd, s, nbytes_id) != nbytes_id)
+	if (slen > 0) {
+		*buf = malloc(sizeof(char) * (slen + 1));
+		if (!*buf)
 			return -1;
-	} else {
-		if (lxc_write_nointr(wpipefd, "\0", 1) != 1)
+		if (lxc_read_nointr(fd, *buf, slen) != (ssize_t)slen)
 			return -1;
+		(*buf)[slen] = '\0';
 	}
-
 	return 0;
 }
 
@@ -1073,111 +1089,63 @@ static int ls_deserialize(int rpipefd, struct ls **m, size_t *len)
 	struct ls *n;
 	size_t sublen = 0;
 	ssize_t nbytes = 0;
-	int ret = -1;
 
 	/* get length */
 	nbytes = sizeof(sublen);
-	if (lxc_read_nointr(rpipefd, &sublen, nbytes) != nbytes)
-		return -1;
-
-	char *serialized = NULL;
-	serialized = malloc(LINELEN * sizeof(char));
-	if (!serialized)
+	if (lxc_read_nointr(rpipefd, &sublen, (size_t)nbytes) != nbytes)
 		return -1;
 
 	while (sublen-- > 0) {
 		n = ls_new(m, len);
 		if (!n)
-			goto out;
+			return -1;
 
 		nbytes = sizeof(n->ram);
-		if (lxc_read_nointr(rpipefd, &n->ram, nbytes) != nbytes)
-			goto out;
+		if (lxc_read_nointr(rpipefd, &n->ram, (size_t)nbytes) != nbytes)
+			return -1;
 
 		nbytes = sizeof(n->swap);
-		if (lxc_read_nointr(rpipefd, &n->swap, nbytes) != nbytes)
-			goto out;
+		if (lxc_read_nointr(rpipefd, &n->swap, (size_t)nbytes) != nbytes)
+			return -1;
 
 		nbytes = sizeof(n->init);
-		if (lxc_read_nointr(rpipefd, &n->init, nbytes) != nbytes)
-			goto out;
+		if (lxc_read_nointr(rpipefd, &n->init, (size_t)nbytes) != nbytes)
+			return -1;
 
 		nbytes = sizeof(n->autostart);
-		if (lxc_read_nointr(rpipefd, &n->autostart, nbytes) != nbytes)
-			goto out;
+		if (lxc_read_nointr(rpipefd, &n->autostart, (size_t)nbytes) != nbytes)
+			return -1;
 
 		nbytes = sizeof(n->running);
-		if (lxc_read_nointr(rpipefd, &n->running, nbytes) != nbytes)
-			goto out;
+		if (lxc_read_nointr(rpipefd, &n->running, (size_t)nbytes) != nbytes)
+			return -1;
 
 		nbytes = sizeof(n->nestlvl);
-		if (lxc_read_nointr(rpipefd, &n->nestlvl, nbytes) != nbytes)
-			goto out;
-
-		ssize_t buf_size = LINELEN;
-		if (ls_read_and_grow_buf(rpipefd, &n->name, "NAME:", 5 + 1, &serialized, &buf_size) == -1)
-			goto out;
-
-		if (ls_read_and_grow_buf(rpipefd, &n->state, "STATE:", 6 + 1, &serialized, &buf_size) == -1)
-			goto out;
-
-		if (ls_read_and_grow_buf(rpipefd, &n->groups, "GROUPS:", 7 + 1, &serialized, &buf_size) == -1)
-			goto out;
-
-		if (ls_read_and_grow_buf(rpipefd, &n->interface, "INTERFACE:", 10 + 1, &serialized, &buf_size) == -1)
-			goto out;
-
-		if (ls_read_and_grow_buf(rpipefd, &n->ipv4, "IPV4:", 5 + 1, &serialized, &buf_size) == -1)
-			goto out;
-
-		if (ls_read_and_grow_buf(rpipefd, &n->ipv6, "IPV6:", 5 + 1, &serialized, &buf_size) == -1)
-			goto out;
-	}
-	ret = 0;
-
-out:
-	free(serialized);
+		if (lxc_read_nointr(rpipefd, &n->nestlvl, (size_t)nbytes) != nbytes)
+			return -1;
 
-	return ret;
-}
+		/* NAME */
+		if (ls_recv_str(rpipefd, &n->name) < 0)
+			return -1;
 
-static int ls_read_and_grow_buf(const int rpipefd, char **save_buf,
-		const char *id, ssize_t nbytes_id,
-		char **read_buf, ssize_t *read_buf_len)
-{
-	char *inc, *tmp;
-	char buf[80]; /* id can only be 79 + \0 long */
+		/* STATE */
+		if (ls_recv_str(rpipefd, &n->state) < 0)
+			return -1;
 
-	if (lxc_read_nointr(rpipefd, buf, nbytes_id) != nbytes_id)
-		return -1;
+		/* GROUPS */
+		if (ls_recv_str(rpipefd, &n->groups) < 0)
+			return -1;
 
-	if (strcmp(id, buf) != 0)
-		return -1;
+		/* INTERFACE */
+		if (ls_recv_str(rpipefd, &n->interface) < 0)
+			return -1;
 
-	inc = *read_buf;
-	nbytes_id = 0;
-	do {
-		/* if the next read would overflow our buffer realloc */
-		if (nbytes_id + 1 >= *read_buf_len) {
-			*read_buf_len += LINELEN;
-			tmp = realloc(*read_buf, *read_buf_len);
-			if (!tmp)
-				return -1;
-			*read_buf = tmp;
-			/* Put inc back to where it was before the realloc so we
-			 * can keep on reading in the string. */
-			inc = *read_buf + nbytes_id;
-		}
-		/* only read one byte at a time */
-		if (lxc_read_nointr(rpipefd, inc, 1) != 1)
+		/* IPV4 */
+		if (ls_recv_str(rpipefd, &n->ipv4) < 0)
 			return -1;
-		nbytes_id++;
-	} while (*inc++ != '\0');
 
-	if (nbytes_id > 1) {
-		/* save it where the caller wants it */
-		*save_buf = strdup(*read_buf);
-		if (!*save_buf)
+		/* IPV6 */
+		if (ls_recv_str(rpipefd, &n->ipv6) < 0)
 			return -1;
 	}
 

From 5a537be50d524394fa0eb5dbd87ff98712cdd32c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Thu, 28 Apr 2016 22:58:14 +0200
Subject: [PATCH 026/334] lxc-ls: non-functional changes

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/lxc_ls.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/lxc/lxc_ls.c b/src/lxc/lxc_ls.c
index 97c5d46..e2a4c34 100644
--- a/src/lxc/lxc_ls.c
+++ b/src/lxc/lxc_ls.c
@@ -16,7 +16,8 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#define _GNU_SOURCE
+#include "config.h"
+
 #include <getopt.h>
 #include <regex.h>
 #include <stdbool.h>
@@ -24,18 +25,17 @@
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
+#include <termios.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <termios.h>
 
 #include <lxc/lxccontainer.h>
 
 #include "arguments.h"
 #include "conf.h"
-#include "config.h"
 #include "confile.h"
 #include "log.h"
 #include "lxc.h"
@@ -105,6 +105,7 @@ static char *ls_get_groups(struct lxc_container *c, bool running);
 static char *ls_get_ips(struct lxc_container *c, const char *inet);
 static int ls_recv_str(int fd, char **buf);
 static int ls_send_str(int fd, const char *buf);
+
 struct wrapargs {
 	const struct lxc_arguments *args;
 	char **grps_must;
@@ -114,10 +115,12 @@ struct wrapargs {
 	const char *parent;
 	unsigned int nestlvl;
 };
+
 /*
  * Takes struct wrapargs as argument.
  */
 static int ls_get_wrapper(void *wrap);
+
 /*
  * To calculate swap usage we should not simply check memory.usage_in_bytes and
  * memory.memsw.usage_in_bytes and then do:
@@ -130,21 +133,25 @@ static unsigned int ls_get_term_width(void);
 static char *ls_get_interface(struct lxc_container *c);
 static bool ls_has_all_grps(const char *has, char **must, size_t must_len);
 static struct ls *ls_new(struct ls **ls, size_t *size);
+
 /*
  * Print user-specified fancy format.
  */
 static void ls_print_fancy_format(struct ls *l, struct lengths *lht,
 		size_t size, const char *fancy_fmt);
+
 /*
  * Only print names of containers.
  */
 static void ls_print_names(struct ls *l, struct lengths *lht,
 		size_t ls_arr, size_t termwidth);
+
 /*
  * Print default fancy format.
  */
 static void ls_print_table(struct ls *l, struct lengths *lht,
 		size_t size);
+
 /*
  * id can only be 79 + \0 chars long.
  */
@@ -309,9 +316,8 @@ static char *ls_get_config_item(struct lxc_container *c, const char *item,
 static void ls_free_arr(char **arr, size_t size)
 {
 	size_t i;
-	for (i = 0; i < size; i++) {
+	for (i = 0; i < size; i++)
 		free(arr[i]);
-	}
 	free(arr);
 }
 

From 2e6f901460f00f8007dcc13725c1ed4568a85a95 Mon Sep 17 00:00:00 2001
From: walkerning <foxdoraame at gmail.com>
Date: Sun, 1 May 2016 01:06:29 +0800
Subject: [PATCH 027/334] Check if stdout is a terminal in lxc-checkconfig

Let lxc-checkconfig write to non-tty stdout without color control
characters
Signed-off-by: walkerning <foxdoraame at gmail.com>
---
 src/lxc/lxc-checkconfig.in | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/lxc/lxc-checkconfig.in b/src/lxc/lxc-checkconfig.in
index 835202b..29586f8 100644
--- a/src/lxc/lxc-checkconfig.in
+++ b/src/lxc/lxc-checkconfig.in
@@ -6,10 +6,17 @@
 
 CAT="cat"
 
-SETCOLOR_SUCCESS="printf \\033[1;32m"
-SETCOLOR_FAILURE="printf \\033[1;31m"
-SETCOLOR_WARNING="printf \\033[1;33m"
-SETCOLOR_NORMAL="printf \\033[0;39m"
+if [ -t 1 ]; then
+    SETCOLOR_SUCCESS="printf \\033[1;32m"
+    SETCOLOR_FAILURE="printf \\033[1;31m"
+    SETCOLOR_WARNING="printf \\033[1;33m"
+    SETCOLOR_NORMAL="printf \\033[0;39m"
+else
+    SETCOLOR_SUCCESS=":"
+    SETCOLOR_FAILURE=":"
+    SETCOLOR_WARNING=":"
+    SETCOLOR_NORMAL=":"
+fi
 
 is_set() {
     $CAT $CONFIG | grep "$1=[y|m]" > /dev/null

From 225ced0f4e32c5c47d7d68793b787b8fc9eb9969 Mon Sep 17 00:00:00 2001
From: Aron Podrigal <aronp at guaranteedplus.com>
Date: Sun, 1 May 2016 11:06:53 -0400
Subject: [PATCH 028/334] Fixed - set PyErr when Container.__init__ fails

When container init failed for whatever reason, previously it resulted
in a `SystemError: NULL result without error in PyObject_Call`
This will now result in a RuntimeError with the error message
previously printed to stderr.

Signed-off-by: Aron Podrigal <aronp at guaranteedplus.com>
---
 src/python-lxc/lxc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/python-lxc/lxc.c b/src/python-lxc/lxc.c
index 151d8fa..4f637d0 100644
--- a/src/python-lxc/lxc.c
+++ b/src/python-lxc/lxc.c
@@ -449,7 +449,9 @@ Container_init(Container *self, PyObject *args, PyObject *kwds)
     self->container = lxc_container_new(name, config_path);
     if (!self->container) {
         Py_XDECREF(fs_config_path);
-        fprintf(stderr, "%d: error creating container %s\n", __LINE__, name);
+
+        PyErr_Format(PyExc_RuntimeError, "%s:%s:%d: error during init for container '%s'.",
+			__FUNCTION__, __FILE__, __LINE__, name);
         return -1;
     }
 

From 2da19674b645f89c5114274afe8266f28ede328e Mon Sep 17 00:00:00 2001
From: Sungbae Yoo <sungbae.yoo at samsung.com>
Date: Mon, 2 May 2016 18:25:29 +0900
Subject: [PATCH 029/334] doc: Add logging option to Korean lxc-attach(1)

Update for commit f43d63b

Signed-off-by: Sungbae Yoo <sungbae.yoo at samsung.com>
---
 doc/ko/lxc-attach.sgml.in | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/doc/ko/lxc-attach.sgml.in b/doc/ko/lxc-attach.sgml.in
index 4f0a22c..3a6e9b1 100644
--- a/doc/ko/lxc-attach.sgml.in
+++ b/doc/ko/lxc-attach.sgml.in
@@ -63,6 +63,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
+      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -300,6 +301,28 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
 	</listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>
+          <option>-L, --pty-log <replaceable>file</replaceable></option>
+        </term>
+        <listitem>
+          <para>
+            <!--
+            Specify a file where the output of <command>lxc-attach</command> will be
+            logged.
+              -->
+            <command>lxc-attach</command>의 출력을 기록할 파일을 지정한다.
+          </para>
+          <para>
+            <!--
+            <emphasis>Important:</emphasis>  When a standard file descriptor
+            does not refer to a pty ouput produced on it will not be logged.
+            -->
+            <emphasis>중요:</emphasis> 표준 입출력 파일 디스크립터가 pty를 참조하지 않으면, 기록되지 않는다.
+          </para>
+        </listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>

From 2a385c0d8ebe9619072a66476cd8624f781178a0 Mon Sep 17 00:00:00 2001
From: Thomas Tanaka <thomas.tanaka at oracle.com>
Date: Mon, 2 May 2016 11:30:30 -0700
Subject: [PATCH 030/334] Improve on the case where default networking config
 is incomplete

Signed-off-by: Thomas Tanaka <thomas.tanaka at oracle.com>
---
 templates/lxc-oracle.in     | 42 +++++++++++++++++++++++++-----------------
 templates/lxc-sparclinux.in | 42 +++++++++++++++++++++++++-----------------
 2 files changed, 50 insertions(+), 34 deletions(-)

diff --git a/templates/lxc-oracle.in b/templates/lxc-oracle.in
index d5a1514..00af55d 100644
--- a/templates/lxc-oracle.in
+++ b/templates/lxc-oracle.in
@@ -40,10 +40,6 @@ done
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
-# use virbr0 that is setup by default by libvirtd
-lxc_network_type=veth
-lxc_network_link=virbr0
-
 die()
 {
     echo "failed: $1"
@@ -484,11 +480,6 @@ container_config_create()
         echo "lxc.include = @LXCTEMPLATECONFIG@/oracle.common.conf" >> $cfg_dir/config
     fi
 
-    # generate a hwaddr for the container with a high mac address
-    # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
-    local hwaddr="fe:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
-                      head -n 1 |awk '{print $2}' | cut -c1-10 |\
-                      sed 's/\(..\)/\1:/g; s/.$//'`"
     cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
 # Container configuration for Oracle Linux $container_release_major.$container_release_minor
 lxc.arch = $arch
@@ -506,20 +497,37 @@ EOF
     fi
 
     echo "# Networking" >>$cfg_dir/config
-    # see if the network settings were already specified
+    # see if the default network settings were already specified
     lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
-    if [ -z "$lxc_network_type" -a			\
-        \( $host_distribution = "OracleServer" -o	\
-           $host_distribution = "Fedora" \) ]; then
-            echo "lxc.network.type = veth" >>$cfg_dir/config
-            echo "lxc.network.flags = up" >>$cfg_dir/config
-            echo "lxc.network.link = virbr0" >>$cfg_dir/config
+    if [ -z "$lxc_network_type" ]; then
+        echo "lxc.network.type = veth" >>$cfg_dir/config
+        lxc_network_type=veth
+    fi
+
+    lxc_network_link=`grep '^lxc.network.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_link" ]; then
+        echo "lxc.network.link = lxcbr0" >>$cfg_dir/config
+        lxc_network_link=lxcbr0
+    fi
+
+    lxc_network_hwaddr=`grep '^lxc.network.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_hwaddr" ]; then
+	# generate a hwaddr for the container
+        # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
+        local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
+                        head -n1 | awk '{print $2}' | cut -c1-6 | \
+                        sed 's/\(..\)/\1:/g; s/.$//'`"
+        echo "lxc.network.hwaddr = $hwaddr" >>$cfg_dir/config
+    fi
+
+    lxc_network_flags=`grep '^lxc.network.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_flags" ]; then
+        echo "lxc.network.flags = up" >>$cfg_dir/config
     fi
 
     cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
 lxc.network.name = eth0
 lxc.network.mtu = 1500
-lxc.network.hwaddr = $hwaddr
 EOF
 }
 
diff --git a/templates/lxc-sparclinux.in b/templates/lxc-sparclinux.in
index cfb893a..70616ba 100644
--- a/templates/lxc-sparclinux.in
+++ b/templates/lxc-sparclinux.in
@@ -44,10 +44,6 @@ done
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
-# use virbr0 that is setup by default by libvirtd
-lxc_network_type=veth
-lxc_network_link=virbr0
-
 die()
 {
     echo "failed: $1"
@@ -319,11 +315,6 @@ container_config_create()
         echo "lxc.include = @LXCTEMPLATECONFIG@/sparclinux.common.conf" >> $cfg_dir/config
     fi
 
-    # generate a hwaddr for the container with a high mac address
-    # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
-    local hwaddr="fe:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
-                      head -n 1 |awk '{print $2}' | cut -c1-10 |\
-                      sed 's/\(..\)/\1:/g; s/.$//'`"
     cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
 # Container configuration for Linux for SPARC $container_release_major.$container_release_minor
 lxc.arch = $arch
@@ -336,20 +327,37 @@ EOF
     echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config
 
     echo "# Networking" >>$cfg_dir/config
-    # see if the network settings were already specified
+    # see if the default network settings were already specified
     lxc_network_type=`grep '^lxc.network.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
-    if [ -z "$lxc_network_type" -a			\
-        \( $host_distribution = "SPARCLinux" -o	\
-           $host_distribution = "Fedora" \) ]; then
-            echo "lxc.network.type = veth" >>$cfg_dir/config
-            echo "lxc.network.flags = up" >>$cfg_dir/config
-            echo "lxc.network.link = virbr0" >>$cfg_dir/config
+    if [ -z "$lxc_network_type" ]; then
+        echo "lxc.network.type = veth" >>$cfg_dir/config
+        lxc_network_type=veth
+    fi
+
+    lxc_network_link=`grep '^lxc.network.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_link" ]; then
+        echo "lxc.network.link = lxcbr0" >>$cfg_dir/config
+        lxc_network_link=lxcbr0
+    fi
+
+    lxc_network_hwaddr=`grep '^lxc.network.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_hwaddr" ]; then
+        # generate a hwaddr for the container
+        # see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
+        local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
+                        head -n1 | awk '{print $2}' | cut -c1-6 | \
+                        sed 's/\(..\)/\1:/g; s/.$//'`"
+        echo "lxc.network.hwaddr = $hwaddr" >>$cfg_dir/config
+    fi
+
+    lxc_network_flags=`grep '^lxc.network.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
+    if [ -z "$lxc_network_flags" ]; then
+        echo "lxc.network.flags = up" >>$cfg_dir/config
     fi
 
     cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
 lxc.network.name = eth0
 lxc.network.mtu = 1500
-lxc.network.hwaddr = $hwaddr
 EOF
 }
 

From 3fb82bafe07df61c6ba8f232568189ec39a5c030 Mon Sep 17 00:00:00 2001
From: Lisio <andrey at kostin.email>
Date: Thu, 5 May 2016 08:35:36 +0400
Subject: [PATCH 031/334] Force DHCP client to send hostname

Required for proper applying dnsmasq config entries.

Signed-off-by: Andrey Kostin <andrey at kostin.email>
---
 templates/lxc-alpine.in | 1 +
 1 file changed, 1 insertion(+)

diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in
index 18feda9..bc4eee4 100644
--- a/templates/lxc-alpine.in
+++ b/templates/lxc-alpine.in
@@ -346,6 +346,7 @@ setup_network() {
 	cat <<-EOF > etc/network/interfaces
 		auto eth0
 		iface eth0 inet dhcp
+		hostname $(hostname)
 	EOF
 }
 

From f55f607dcba8698956ffebcd5df9c63f1da9dca3 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 6 May 2016 11:21:39 -0500
Subject: [PATCH 032/334] sync: fail on unexpected message sizes

I think (?) this may be related to our hanging monitor bug. Let's do this
anyway, as it's probably a good idea.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/sync.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/lxc/sync.c b/src/lxc/sync.c
index f06d302..82f68e3 100644
--- a/src/lxc/sync.c
+++ b/src/lxc/sync.c
@@ -47,6 +47,11 @@ static int __sync_wait(int fd, int sequence)
 	if (!ret)
 		return 0;
 
+	if (ret != sizeof(sync)) {
+		ERROR("unexpected sync size: %d expected %lu", ret, sizeof(sync));
+		return -1;
+	}
+
 	if (sync == LXC_SYNC_ERROR) {
 		ERROR("An error occurred in another process "
 		      "(expected sequence number %d)", sequence);

From 38d122cfbb38b64614f5b8b314e99285d5da03ce Mon Sep 17 00:00:00 2001
From: Karl-Johan Karlsson <creideiki at ferretporn.se>
Date: Sun, 8 May 2016 10:38:31 +0200
Subject: [PATCH 033/334] Change sys_resources to sys_resource.

gentoo.moresecure.conf tries to drop the capability CAP_SYS_RESOURCES.
However, that capability doesn't exist, so the container doesn't start.
Change it to CAP_SYS_RESOURCE, according to capabilities(7).

Also correct the same typo in a comment in slackware.common.conf.

Signed-off-by: Karl-Johan Karlsson <creideiki at ferretporn.se>
---
 config/templates/gentoo.moresecure.conf.in | 4 ++--
 config/templates/slackware.common.conf.in  | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/config/templates/gentoo.moresecure.conf.in b/config/templates/gentoo.moresecure.conf.in
index 6e9aa0d..c08b91c 100644
--- a/config/templates/gentoo.moresecure.conf.in
+++ b/config/templates/gentoo.moresecure.conf.in
@@ -29,8 +29,8 @@ lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
 # lxc.cap.drop = audit_control    # breaks sshd (set_loginuid failed)
 # lxc.cap.drop = audit_write
 # lxc.cap.drop = setpcap          # breaks journald
-# lxc.cap.drop = sys_resources    # breaks systemd
-lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_boot sys_nice sys_pacct sys_ptrace sys_rawio sys_resources sys_tty_config syslog
+# lxc.cap.drop = sys_resource     # breaks systemd
+lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_boot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog
 
 # WARNING: the security vulnerability reported for 'cap_net_admin' at
 # http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html
diff --git a/config/templates/slackware.common.conf.in b/config/templates/slackware.common.conf.in
index 191099f..c932e6d 100644
--- a/config/templates/slackware.common.conf.in
+++ b/config/templates/slackware.common.conf.in
@@ -41,6 +41,6 @@ lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir
 # lxc.cap.drop = audit_control    # breaks sshd (set_loginuid failed)
 # lxc.cap.drop = audit_write
 # lxc.cap.drop = setpcap          # breaks journald
-# lxc.cap.drop = sys_resources    # breaks systemd
+# lxc.cap.drop = sys_resource     # breaks systemd
 #
 lxc.cap.drop = mknod setfcap setpcap

From e1a2c96c0d14a8b83bc141b4116dc87dadb639e6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Sat, 7 May 2016 07:40:33 +0200
Subject: [PATCH 034/334] sync.c: use correct types

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/sync.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/lxc/sync.c b/src/lxc/sync.c
index 82f68e3..c9fbcd9 100644
--- a/src/lxc/sync.c
+++ b/src/lxc/sync.c
@@ -36,7 +36,7 @@ lxc_log_define(lxc_sync, lxc);
 static int __sync_wait(int fd, int sequence)
 {
 	int sync = -1;
-	int ret;
+	ssize_t ret;
 
 	ret = read(fd, &sync, sizeof(sync));
 	if (ret < 0) {
@@ -47,8 +47,8 @@ static int __sync_wait(int fd, int sequence)
 	if (!ret)
 		return 0;
 
-	if (ret != sizeof(sync)) {
-		ERROR("unexpected sync size: %d expected %lu", ret, sizeof(sync));
+	if ((size_t)ret != sizeof(sync)) {
+		ERROR("unexpected sync size: %zu expected %zu", (size_t)ret, sizeof(sync));
 		return -1;
 	}
 

From 563148e2df423ca51c1878cd6f5370a69d58744f Mon Sep 17 00:00:00 2001
From: Hartnell Foster <hartnell.foster at bbc.co.uk>
Date: Mon, 9 May 2016 12:42:56 +0100
Subject: [PATCH 035/334] Added OR statement for cases of ID = rhel in RHEL 7+

Signed-off-by: Hartnell Foster <hartnell.foster at bbc.co.uk>
---
 templates/lxc-centos.in | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in
index ef8061c..051faef 100644
--- a/templates/lxc-centos.in
+++ b/templates/lxc-centos.in
@@ -137,8 +137,9 @@ if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
 then
     centos_host_ver=${VERSION_ID}
     is_centos=true
-elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -a "${VERSION_ID}" != "" ]
+elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -o "${ID}" = "rhel" -a "${VERSION_ID}" != "" ]
 then
+    # RHEL 7+ /etc/os-release ID = 'rhel', which doesn't enter this elif without the added OR statement
     redhat_host_ver=${VERSION_ID}
     is_redhat=true
 elif [ -e /etc/centos-release ]
@@ -394,7 +395,7 @@ configure_centos_init()
 #  power-status-changed - shutdown on SIGPWR
 #
 start on power-status-changed
-    
+
 exec /sbin/shutdown -h now "SIGPWR received"
 EOF
     fi

From 9e0148cfda29169f26b6d578eee3e583ce082813 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn at ubuntu.com>
Date: Mon, 9 May 2016 15:30:46 -0500
Subject: [PATCH 036/334] Unshare netns after setting the userns mappings

so that there is a root uid mapping for the /proc/net files.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/start.c | 48 ++++++++++++++++++++++++++++++++++++------------
 src/lxc/sync.c  |  5 +++++
 src/lxc/sync.h  |  2 ++
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index d9d5814..5437206 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -736,6 +736,20 @@ static int do_start(void *data)
 		close(handler->pinfd);
 	}
 
+	if (lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP))
+		return -1;
+
+	/* Unshare CLONE_NEWNET after CLONE_NEWUSER  - see
+	  https://github.com/lxc/lxd/issues/1978 */
+	if ((handler->clone_flags & (CLONE_NEWNET | CLONE_NEWUSER)) ==
+			(CLONE_NEWNET | CLONE_NEWUSER)) {
+		ret = unshare(CLONE_NEWNET);
+		if (ret < 0) {
+			SYSERROR("Error unsharing network namespace");
+			goto out_warn_father;
+		}
+	}
+
 	/* Tell the parent task it can begin to configure the
 	 * container and wait for it to finish
 	 */
@@ -1027,7 +1041,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 	char *errmsg = NULL;
 	bool cgroups_connected = false;
 	int saved_ns_fd[LXC_NS_MAX];
-	int preserve_mask = 0, i;
+	int preserve_mask = 0, i, flags;
 	int netpipepair[2], nveths;
 
 	netpipe = -1;
@@ -1118,6 +1132,9 @@ static int lxc_spawn(struct lxc_handler *handler)
 	}
 
 	/* Create a process in a new set of namespaces */
+	flags = handler->clone_flags;
+	if (handler->clone_flags & CLONE_NEWUSER)
+		flags &= ~CLONE_NEWNET;
 	handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
 	if (handler->pid < 0) {
 		SYSERROR("failed to fork into a new namespace");
@@ -1135,8 +1152,25 @@ static int lxc_spawn(struct lxc_handler *handler)
 
 	lxc_sync_fini_child(handler);
 
-	if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
+	/* map the container uids - the container became an invalid
+	 * userid the moment it was cloned with CLONE_NEWUSER - this
+	 * call doesn't change anything immediately, but allows the
+	 * container to setuid(0) (0 being mapped to something else on
+	 * the host) later to become a valid uid again */
+	if (lxc_map_ids(&handler->conf->id_map, handler->pid)) {
+		ERROR("failed to set up id mapping");
+		goto out_delete_net;
+	}
+
+	if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) {
 		failed_before_rename = 1;
+		goto out_delete_net;
+	}
+
+	if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) {
+		failed_before_rename = 1;
+		goto out_delete_net;
+	}
 
 	if (!cgroup_create_legacy(handler)) {
 		ERROR("failed to setup the legacy cgroups for %s", name);
@@ -1182,16 +1216,6 @@ static int lxc_spawn(struct lxc_handler *handler)
 		close(netpipepair[1]);
 	}
 
-	/* map the container uids - the container became an invalid
-	 * userid the moment it was cloned with CLONE_NEWUSER - this
-	 * call doesn't change anything immediately, but allows the
-	 * container to setuid(0) (0 being mapped to something else on
-	 * the host) later to become a valid uid again */
-	if (lxc_map_ids(&handler->conf->id_map, handler->pid)) {
-		ERROR("failed to set up id mapping");
-		goto out_delete_net;
-	}
-
 	/* Tell the child to continue its initialization.  we'll get
 	 * LXC_SYNC_CGROUP when it is ready for us to setup cgroups
 	 */
diff --git a/src/lxc/sync.c b/src/lxc/sync.c
index c9fbcd9..7f23622 100644
--- a/src/lxc/sync.c
+++ b/src/lxc/sync.c
@@ -99,6 +99,11 @@ int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
 	return __sync_wake(handler->sv[0], sequence);
 }
 
+int lxc_sync_wait_parent(struct lxc_handler *handler, int sequence)
+{
+	return __sync_wait(handler->sv[0], sequence);
+}
+
 int lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
 {
 	return __sync_wait(handler->sv[1], sequence);
diff --git a/src/lxc/sync.h b/src/lxc/sync.h
index d0aee6f..12a8b95 100644
--- a/src/lxc/sync.h
+++ b/src/lxc/sync.h
@@ -26,6 +26,7 @@
 struct lxc_handler;
 
 enum {
+	LXC_SYNC_STARTUP,
 	LXC_SYNC_CONFIGURE,
 	LXC_SYNC_POST_CONFIGURE,
 	LXC_SYNC_CGROUP,
@@ -42,6 +43,7 @@ void lxc_sync_fini_child(struct lxc_handler *);
 int lxc_sync_wake_child(struct lxc_handler *, int);
 int lxc_sync_wait_child(struct lxc_handler *, int);
 int lxc_sync_wake_parent(struct lxc_handler *, int);
+int lxc_sync_wait_parent(struct lxc_handler *, int);
 int lxc_sync_barrier_parent(struct lxc_handler *, int);
 int lxc_sync_barrier_child(struct lxc_handler *, int);
 

From 015d4e48f342ba67c0c6ab3677fc9671e0be4b77 Mon Sep 17 00:00:00 2001
From: Aron Podrigal <aronp at guaranteedplus.com>
Date: Sun, 1 May 2016 12:13:39 -0400
Subject: [PATCH 037/334] Added `type` to keys in lxc_list_nicconfigs

Signed-off-by: Aron Podrigal <aronp at guaranteedplus.com>
---
 src/lxc/confile.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 8c366c8..2821871 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -521,6 +521,7 @@ extern int lxc_list_nicconfigs(struct lxc_conf *c, const char *key,
 	else
 		memset(retv, 0, inlen);
 
+	strprint(retv, inlen, "type\n");
 	strprint(retv, inlen, "script.up\n");
 	strprint(retv, inlen, "script.down\n");
 	if (netdev->type != LXC_NET_EMPTY) {

From 04503173e5aaf1412dfd09275eafa272b1e0fa3f Mon Sep 17 00:00:00 2001
From: Stewart Brodie <stewart at metahusky.net>
Date: Tue, 10 May 2016 13:57:00 +0100
Subject: [PATCH 038/334] Allow configuration file values to be quoted

If the value starts and ends with matching quote characters, those
characters are stripped automatically.   Quote characters are the
single quote (') or double quote (").  The quote removal is done after
the whitespace trimming.

This is needed particularly in order that lxc.environment values may
have trailing spaces.  However, the quote removal is done for all values
in the parse_line function, as it has non-const access to the value.

Signed-off-by: Stewart Brodie <stewart at metahusky.net>
---
 src/lxc/confile.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 2821871..14a76b2 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1964,6 +1964,14 @@ static int parse_line(char *buffer, void *data)
 	value += lxc_char_left_gc(value, strlen(value));
 	value[lxc_char_right_gc(value, strlen(value))] = '\0';
 
+	if (*value == '\'' || *value == '\"') {
+		size_t len = strlen(value);
+		if (len > 1 && value[len-1] == *value) {
+			value[len-1] = '\0';
+			value++;
+		}
+	}
+
 	config = lxc_getconfig(key);
 	if (!config) {
 		ERROR("unknown key %s", key);

From 28e42b622a53a382151b500a8342645b49136cd1 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 9 May 2016 21:37:26 +0000
Subject: [PATCH 039/334] log: remove duplicate definitons and bump buffer size

When writing out the CRIU exec command, we're bumping up against the buffer
size limit. Let's increase it so we can avoid:

lxc 20160509213229.921 WARN     lxc_log - log.c:log_append_logfile:111 - truncated next event from 523 to 512 bytes

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/log.c | 2 --
 src/lxc/log.h | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 55fa7f5..11d4bbf 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -40,8 +40,6 @@
 #include "caps.h"
 #include "utils.h"
 
-#define LXC_LOG_PREFIX_SIZE	32
-#define LXC_LOG_BUFFER_SIZE	512
 #define LXC_LOG_DATEFOMAT_SIZE  15
 
 int lxc_log_fd = -1;
diff --git a/src/lxc/log.h b/src/lxc/log.h
index 76bd4df..eb330d0 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -44,7 +44,7 @@
 #endif
 
 #define LXC_LOG_PREFIX_SIZE	32
-#define LXC_LOG_BUFFER_SIZE	512
+#define LXC_LOG_BUFFER_SIZE	1024
 
 /* This attribute is required to silence clang warnings */
 #if defined(__GNUC__)

From 9d928ec50fd75f7f392c7978395ec755650587f3 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 6 May 2016 18:19:16 +0000
Subject: [PATCH 040/334] c/r: rearrange things to pass struct migrate_opts all
 the way down

If we don't do this, we'll end up changing the function signatures for the
internal __criu_* functions each time we add a new parameter, which will
get very annoying very quickly. Since we already have the user's arguments
struct, let's just pass that all the way down.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c         | 77 +++++++++++++++++++-------------------------------
 src/lxc/criu.h         |  6 ++--
 src/lxc/lxccontainer.c |  6 ++--
 3 files changed, 35 insertions(+), 54 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 3645bab..18cca3c 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -56,20 +56,13 @@ struct criu_opts {
 	/* The type of criu invocation, one of "dump" or "restore" */
 	char *action;
 
-	/* The directory to pass to criu */
-	char *directory;
+	/* the user-provided migrate options relevant to this action */
+	struct migrate_opts *user;
 
 	/* The container to dump */
 	struct lxc_container *c;
 
-	/* Enable criu verbose mode? */
-	bool verbose;
-
-	/* (pre-)dump: a directory for the previous dump's images */
-	char *predump_dir;
-
 	/* dump: stop the container or not after dumping? */
-	bool stop;
 	char tty_id[32]; /* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
 
 	/* restore: the file to write the init process' pid into */
@@ -82,10 +75,6 @@ struct criu_opts {
 	 * different) on the target host. NULL if lxc.console = "none".
 	 */
 	char *console_name;
-
-	/* Address and port where a criu pageserver is listening */
-	char *pageserver_address;
-	char *pageserver_port;
 };
 
 static int load_tty_major_minor(char *directory, char *output, int len)
@@ -157,15 +146,15 @@ static void exec_criu(struct criu_opts *opts)
 		static_args += 4;
 
 		/* --prev-images-dir <path-to-directory-A-relative-to-B> */
-		if (opts->predump_dir)
+		if (opts->user->predump_dir)
 			static_args += 2;
 
 		/* --page-server --address <address> --port <port> */
-		if (opts->pageserver_address && opts->pageserver_port)
+		if (opts->user->pageserver_address && opts->user->pageserver_port)
 			static_args += 5;
 
 		/* --leave-running (only for final dump) */
-		if (strcmp(opts->action, "dump") == 0 && !opts->stop)
+		if (strcmp(opts->action, "dump") == 0 && !opts->user->stop)
 			static_args++;
 
 		/* --external tty[88,4] */
@@ -179,7 +168,7 @@ static void exec_criu(struct criu_opts *opts)
 		static_args += 10;
 
 		tty_info[0] = 0;
-		if (load_tty_major_minor(opts->directory, tty_info, sizeof(tty_info)))
+		if (load_tty_major_minor(opts->user->directory, tty_info, sizeof(tty_info)))
 			return;
 
 		/* --inherit-fd fd[%d]:tty[%s] */
@@ -189,10 +178,10 @@ static void exec_criu(struct criu_opts *opts)
 		return;
 	}
 
-	if (opts->verbose)
+	if (opts->user->verbose)
 		static_args++;
 
-	ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->directory, opts->action);
+	ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action);
 	if (ret < 0 || ret >= PATH_MAX) {
 		ERROR("logfile name too long\n");
 		return;
@@ -236,11 +225,11 @@ static void exec_criu(struct criu_opts *opts)
 	DECLARE_ARG("--enable-fs");
 	DECLARE_ARG("tracefs");
 	DECLARE_ARG("-D");
-	DECLARE_ARG(opts->directory);
+	DECLARE_ARG(opts->user->directory);
 	DECLARE_ARG("-o");
 	DECLARE_ARG(log);
 
-	if (opts->verbose)
+	if (opts->user->verbose)
 		DECLARE_ARG("-vvvvvv");
 
 	if (strcmp(opts->action, "dump") == 0 || strcmp(opts->action, "pre-dump") == 0) {
@@ -275,21 +264,21 @@ static void exec_criu(struct criu_opts *opts)
 			DECLARE_ARG(opts->tty_id);
 		}
 
-		if (opts->predump_dir) {
+		if (opts->user->predump_dir) {
 			DECLARE_ARG("--prev-images-dir");
-			DECLARE_ARG(opts->predump_dir);
+			DECLARE_ARG(opts->user->predump_dir);
 		}
 
-		if (opts->pageserver_address && opts->pageserver_port) {
+		if (opts->user->pageserver_address && opts->user->pageserver_port) {
 			DECLARE_ARG("--page-server");
 			DECLARE_ARG("--address");
-			DECLARE_ARG(opts->pageserver_address);
+			DECLARE_ARG(opts->user->pageserver_address);
 			DECLARE_ARG("--port");
-			DECLARE_ARG(opts->pageserver_port);
+			DECLARE_ARG(opts->user->pageserver_port);
 		}
 
 		/* only for final dump */
-		if (strcmp(opts->action, "dump") == 0 && !opts->stop)
+		if (strcmp(opts->action, "dump") == 0 && !opts->user->stop)
 			DECLARE_ARG("--leave-running");
 	} else if (strcmp(opts->action, "restore") == 0) {
 		void *m;
@@ -556,7 +545,7 @@ static bool restore_net_info(struct lxc_container *c)
 
 // do_restore never returns, the calling process is used as the
 // monitor process. do_restore calls exit() if it fails.
-void do_restore(struct lxc_container *c, int status_pipe, char *directory, bool verbose)
+void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts)
 {
 	pid_t pid;
 	char pidfile[L_tmpnam];
@@ -642,10 +631,9 @@ void do_restore(struct lxc_container *c, int status_pipe, char *directory, bool
 		}
 
 		os.action = "restore";
-		os.directory = directory;
+		os.user = opts;
 		os.c = c;
 		os.pidfile = pidfile;
-		os.verbose = verbose;
 		os.cgroup_path = cgroup_canonical_path(handler);
 		os.console_fd = c->lxc_conf->console.slave;
 
@@ -829,16 +817,14 @@ static int save_tty_major_minor(char *directory, struct lxc_container *c, char *
 }
 
 /* do one of either predump or a regular dump */
-static bool do_dump(struct lxc_container *c, char *mode, char *directory,
-		    bool stop, bool verbose, char *predump_dir,
-		    char *pageserver_address, char *pageserver_port)
+static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *opts)
 {
 	pid_t pid;
 
 	if (!criu_ok(c))
 		return false;
 
-	if (mkdir_p(directory, 0700) < 0)
+	if (mkdir_p(opts->directory, 0700) < 0)
 		return false;
 
 	pid = fork();
@@ -851,16 +837,11 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory,
 		struct criu_opts os;
 
 		os.action = mode;
-		os.directory = directory;
+		os.user = opts;
 		os.c = c;
-		os.stop = stop;
-		os.verbose = verbose;
-		os.predump_dir = predump_dir;
 		os.console_name = c->lxc_conf->console.path;
-		os.pageserver_address = pageserver_address;
-		os.pageserver_port = pageserver_port;
 
-		if (save_tty_major_minor(directory, c, os.tty_id, sizeof(os.tty_id)) < 0)
+		if (save_tty_major_minor(opts->directory, c, os.tty_id, sizeof(os.tty_id)) < 0)
 			exit(1);
 
 		/* exec_criu() returning is an error */
@@ -891,17 +872,17 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory,
 	}
 }
 
-bool __criu_pre_dump(struct lxc_container *c, char *directory, bool verbose, char *predump_dir, char *pageserver_address, char *pageserver_port)
+bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts)
 {
-	return do_dump(c, "pre-dump", directory, false, verbose, predump_dir, pageserver_address, pageserver_port);
+	return do_dump(c, "pre-dump", opts);
 }
 
-bool __criu_dump(struct lxc_container *c, char *directory, bool stop, bool verbose, char *predump_dir, char *pageserver_address, char *pageserver_port)
+bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts)
 {
 	char path[PATH_MAX];
 	int ret;
 
-	ret = snprintf(path, sizeof(path), "%s/inventory.img", directory);
+	ret = snprintf(path, sizeof(path), "%s/inventory.img", opts->directory);
 	if (ret < 0 || ret >= sizeof(path))
 		return false;
 
@@ -910,10 +891,10 @@ bool __criu_dump(struct lxc_container *c, char *directory, bool stop, bool verbo
 		return false;
 	}
 
-	return do_dump(c, "dump", directory, stop, verbose, predump_dir, pageserver_address, pageserver_port);
+	return do_dump(c, "dump", opts);
 }
 
-bool __criu_restore(struct lxc_container *c, char *directory, bool verbose)
+bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
 {
 	pid_t pid;
 	int status, nread;
@@ -942,7 +923,7 @@ bool __criu_restore(struct lxc_container *c, char *directory, bool verbose)
 	if (pid == 0) {
 		close(pipefd[0]);
 		// this never returns
-		do_restore(c, pipefd[1], directory, verbose);
+		do_restore(c, pipefd[1], opts);
 	}
 
 	close(pipefd[1]);
diff --git a/src/lxc/criu.h b/src/lxc/criu.h
index db2ab11..ce94b31 100644
--- a/src/lxc/criu.h
+++ b/src/lxc/criu.h
@@ -27,8 +27,8 @@
 
 #include <lxc/lxccontainer.h>
 
-bool __criu_pre_dump(struct lxc_container *c, char *directory, bool verbose, char *predump_dir, char *pageserver_address, char *pageserver_port);
-bool __criu_dump(struct lxc_container *c, char *directory, bool stop, bool verbose, char *predump_dir, char *pageserver_address, char *pageserver_port);
-bool __criu_restore(struct lxc_container *c, char *directory, bool verbose);
+bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts);
+bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts);
+bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts);
 
 #endif
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 50cfc69..8bd9b8e 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -3968,13 +3968,13 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
 
 	switch (cmd) {
 	case MIGRATE_PRE_DUMP:
-		ret = !__criu_pre_dump(c, opts->directory, opts->verbose, opts->predump_dir, opts->pageserver_address, opts->pageserver_port);
+		ret = !__criu_pre_dump(c, opts);
 		break;
 	case MIGRATE_DUMP:
-		ret = !__criu_dump(c, opts->directory, opts->stop, opts->verbose, opts->predump_dir, opts->pageserver_address, opts->pageserver_port);
+		ret = !__criu_dump(c, opts);
 		break;
 	case MIGRATE_RESTORE:
-		ret = !__criu_restore(c, opts->directory, opts->verbose);
+		ret = !__criu_restore(c, opts);
 		break;
 	default:
 		ERROR("invalid migrate command %u", cmd);

From c6c37c20326c7fcd8a2f072263188cc84c403955 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 11 May 2016 07:51:11 -0600
Subject: [PATCH 041/334] c/r: add an option to use faster inotify support in
 CRIU

The idea here is that criu can use open_by_handle on a configuration which
will preserve inodes on moves across hosts, but shouldn't do that on
configurations which won't preserve inodes. Before, we forced it to always
be slow, but we don't have to do this.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c         | 12 +++++++++---
 src/lxc/lxccontainer.h |  7 +++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 18cca3c..ce8ada6 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -115,7 +115,7 @@ static int load_tty_major_minor(char *directory, char *output, int len)
 static void exec_criu(struct criu_opts *opts)
 {
 	char **argv, log[PATH_MAX];
-	int static_args = 24, argc = 0, i, ret;
+	int static_args = 23, argc = 0, i, ret;
 	int netnr = 0;
 	struct lxc_list *it;
 
@@ -134,7 +134,7 @@ static void exec_criu(struct criu_opts *opts)
 	}
 
 	/* The command line always looks like:
-	 * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \
+	 * criu $(action) --tcp-established --file-locks --link-remap \
 	 * --manage-cgroups action-script foo.sh -D $(directory) \
 	 * -o $(directory)/$(action).log --ext-mount-map auto
 	 * --enable-external-sharing --enable-external-masters
@@ -160,6 +160,10 @@ static void exec_criu(struct criu_opts *opts)
 		/* --external tty[88,4] */
 		if (opts->tty_id[0])
 			static_args += 2;
+
+		/* --force-irmap */
+		if (!opts->user->preserves_inodes)
+			static_args++;
 	} else if (strcmp(opts->action, "restore") == 0) {
 		/* --root $(lxc_mount_point) --restore-detached
 		 * --restore-sibling --pidfile $foo --cgroup-root $foo
@@ -214,7 +218,6 @@ static void exec_criu(struct criu_opts *opts)
 	DECLARE_ARG("--tcp-established");
 	DECLARE_ARG("--file-locks");
 	DECLARE_ARG("--link-remap");
-	DECLARE_ARG("--force-irmap");
 	DECLARE_ARG("--manage-cgroups");
 	DECLARE_ARG("--ext-mount-map");
 	DECLARE_ARG("auto");
@@ -277,6 +280,9 @@ static void exec_criu(struct criu_opts *opts)
 			DECLARE_ARG(opts->user->pageserver_port);
 		}
 
+		if (!opts->user->preserves_inodes)
+			DECLARE_ARG("--force-irmap");
+
 		/* only for final dump */
 		if (strcmp(opts->action, "dump") == 0 && !opts->user->stop)
 			DECLARE_ARG("--leave-running");
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 0e014bc..ecc66e2 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -884,6 +884,13 @@ struct migrate_opts {
 	char *predump_dir; /* relative to directory above */
 	char *pageserver_address; /* where should memory pages be send? */
 	char *pageserver_port;
+
+	/* This flag indicates whether or not the container's rootfs will have
+	 * the same inodes on checkpoint and restore. In the case of e.g. zfs
+	 * send or btrfs send, or an LVM snapshot, this will be true, but it
+	 * won't if e.g. you rsync the filesystems between two machines.
+	 */
+	bool preserves_inodes;
 };
 
 /*!

From b03f1f4ac3666abd032ddc617823213568ad577b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 11 May 2016 12:59:23 -0400
Subject: [PATCH 042/334] Also allow fstype=fuse for fuse filesystems
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/apparmor/abstractions/container-base    | 1 +
 config/apparmor/abstractions/container-base.in | 1 +
 2 files changed, 2 insertions(+)

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index c9f5947..fe24ff3 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -57,6 +57,7 @@
   mount fstype=mqueue,
 
   # allow fuse mounts everywhere
+  mount fstype=fuse,
   mount fstype=fuse.*,
 
   # allow bind mount of /lib/init/fstab for lxcguest
diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
index 4cd409d..550625c 100644
--- a/config/apparmor/abstractions/container-base.in
+++ b/config/apparmor/abstractions/container-base.in
@@ -57,6 +57,7 @@
   mount fstype=mqueue,
 
   # allow fuse mounts everywhere
+  mount fstype=fuse,
   mount fstype=fuse.*,
 
   # allow bind mount of /lib/init/fstab for lxcguest

From 6897137846ebeb1a0b1ee1b1d76fddf8b71024cc Mon Sep 17 00:00:00 2001
From: Jesse Pretorius <jesse.pretorius at rackspace.co.uk>
Date: Wed, 11 May 2016 18:17:58 +0100
Subject: [PATCH 043/334] Add apt-transport-https to minbase variant
 packages_template

In many environments the preference is to configure containers with
apt mirrors that are SSL-secured.

When building containers using the download template this can't be
done unless an insecure mirror is first used to install the
apt-transport-https package, then the sources reconfigured to
use the https URL.

When building containers without using the download template this
can't be done unless the container creator specifically includes
this package in the package list at build time.

It seems more intuitive to me to have the package installed by
default. This patch includes the required package for the minbase
variant only as this is the default.

Signed-off-by: Jesse Pretorius <jesse.pretorius at rackspace.co.uk>
---
 templates/lxc-ubuntu.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-ubuntu.in b/templates/lxc-ubuntu.in
index 06ce8ce..022acf4 100644
--- a/templates/lxc-ubuntu.in
+++ b/templates/lxc-ubuntu.in
@@ -359,7 +359,7 @@ download_ubuntu()
         debootstrap_parameters="$debootstrap_parameters --variant=$variant"
     fi
     if [ "$variant" = 'minbase' ]; then
-        packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client"
+        packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client,apt-transport-https"
     fi
 
     echo "Installing packages in template: ${packages_template}"

From 08a204373170880ac46bc3bb578f399bfacb174a Mon Sep 17 00:00:00 2001
From: Andrey Kostin <andrey at kostin.email>
Date: Wed, 11 May 2016 23:32:40 +0300
Subject: [PATCH 044/334] Fix hostname in interface config for apline template

Signed-off-by: Andrey Kostin <andrey at kostin.email>
---
 templates/lxc-alpine.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in
index bc4eee4..c78795c 100644
--- a/templates/lxc-alpine.in
+++ b/templates/lxc-alpine.in
@@ -346,7 +346,7 @@ setup_network() {
 	cat <<-EOF > etc/network/interfaces
 		auto eth0
 		iface eth0 inet dhcp
-		hostname $(hostname)
+		hostname \$(hostname)
 	EOF
 }
 

From b58725c65b472bb129c610829e2bf4faaf438dbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 16 May 2016 16:25:28 -0400
Subject: [PATCH 045/334] change version to 2.0.1 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 9475b0e..586a0f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 0)
+m4_define([lxc_version_micro], 1)
 m4_define([lxc_version_beta], [])
 m4_define([lxc_version_abi], 1.2.0)
 

From 340f3a48eba4174baa0bd8c6cc1ac989b420808a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Krause?= <joerg.krause at embedded.rocks>
Date: Thu, 19 May 2016 21:51:27 +0200
Subject: [PATCH 046/334] Fix redefinition of struct in6_addr
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

struct in6_addr is both defined in the C library header <netinet/in.h>
and the Linux kernel header <linux/in6.h>.

lxc_user_nic.c includes both <netinet/in.h> and <linux/if_bridge.h>. The
later one includes <linux/in6.h>.

This breaks build with the musl libc:
  error: redefinition of ‘struct in6_addr’

As lxc_user_nic.c does not use any references from <linux/if_bridge.h> it
is safe to remove this header.

Signed-off-by: Jörg Krause <joerg.krause at embedded.rocks>
---
 src/lxc/lxc_user_nic.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
index 87780ca..0cb38ba 100644
--- a/src/lxc/lxc_user_nic.c
+++ b/src/lxc/lxc_user_nic.c
@@ -41,7 +41,6 @@
 #include <net/if.h>
 #include <net/if_arp.h>
 #include <netinet/in.h>
-#include <linux/if_bridge.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <linux/sockios.h>

From dafca21383c0c1df1da70c11a6501c153bec4c1b Mon Sep 17 00:00:00 2001
From: Aleksandr Mezin <mezin.alexander at gmail.com>
Date: Fri, 27 May 2016 18:47:23 +0600
Subject: [PATCH 047/334] travis: test VPATH builds

It looks like VPATH (split source and build directories) builds
are frequently broken. So let's test them on travis-ci.

Personally I use VPATH build in my deployment scripts.

Signed-off-by: Aleksandr Mezin <mezin.alexander at gmail.com>
---
 .travis.yml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 974130d..9f6a7e6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,12 @@ before_install:
  - sudo add-apt-repository ppa:ubuntu-lxc/daily -y
  - sudo apt-get update -qq
  - sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev python3-dev docbook2x libgnutls-dev liblua5.2-dev libselinux1-dev libcgmanager-dev
-script: ./autogen.sh && ./configure --enable-tests && make -j4
+script:
+ - ./autogen.sh
+ - mkdir build
+ - cd build
+ - ../configure --enable-tests
+ - make -j4
 notifications:
   email:
     recipients:

From 934506f59c7322477cc9cdb2a787736f177010ba Mon Sep 17 00:00:00 2001
From: Aleksandr Mezin <mezin.alexander at gmail.com>
Date: Fri, 27 May 2016 21:40:13 +0600
Subject: [PATCH 048/334] travis: ensure 'make install' doesn't fail

Signed-off-by: Aleksandr Mezin <mezin.alexander at gmail.com>
---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index 9f6a7e6..fe5f3eb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,7 @@ script:
  - cd build
  - ../configure --enable-tests
  - make -j4
+ - make DESTDIR=$TRAVIS_BUILD_DIR/install install
 notifications:
   email:
     recipients:

From 2991a7d0e1537bf7910c269f23448e3486ff242c Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at golov.de>
Date: Thu, 2 Jun 2016 15:38:47 +0200
Subject: [PATCH 049/334] start containers in foreground when using the
 lxc at .service

lxc-start started to default to daemonize the container when starting
this conflicts with type=simple of the systemd unit

call lxc-start with -F and thus force execution in foreground
that way we can feed the log to journald properly and keep type=simple

Debian-Bug: https://bugs.debian.org/826100
Signed-off-by: Evgeni Golov <evgeni at golov.de>
---
 config/init/systemd/lxc at .service.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/init/systemd/lxc at .service.in b/config/init/systemd/lxc at .service.in
index 190280e..ba8cc1b 100644
--- a/config/init/systemd/lxc at .service.in
+++ b/config/init/systemd/lxc at .service.in
@@ -9,7 +9,7 @@ Type=simple
 KillMode=mixed
 KillSignal=SIGPWR
 TimeoutStopSec=120s
-ExecStart=@BINDIR@/lxc-start -n %i
+ExecStart=@BINDIR@/lxc-start -F -n %i
 # Environment=BOOTUP=serial
 # Environment=CONSOLETYPE=serial
 Delegate=yes

From b27223f1b9d1afa5703131c72cf0c35b0c27f997 Mon Sep 17 00:00:00 2001
From: Jesse Pretorius <jesse.pretorius at rackspace.co.uk>
Date: Fri, 3 Jun 2016 16:33:25 +0100
Subject: [PATCH 050/334] Move apt-transport-https to global packages_template

In many environments the preference is to configure containers with
apt mirrors that are SSL-secured.

When building containers using the download template this can't be
done unless an insecure mirror is first used to install the
apt-transport-https package, then the sources reconfigured to
use the https URL.

When building containers without using the download template this
can't be done unless the container creator specifically includes
this package in the package list at build time. It seems more
intuitive to me to have the package installed by default.

Commit 396f75abb3d319adc7d871b94b08bc6bb9c49585 added the package
to the minbase variant, but this variant is not used by the download
template build process. The build process instead specifies no
variant, so this patch moves the package from the packages_template
package list in the minbase variant to the global packages_template
package list, ensuring that this package is included in all Ubuntu
build images that use the lxc-ubuntu template.

Signed-off-by: Jesse Pretorius <jesse.pretorius at rackspace.co.uk>
---
 templates/lxc-ubuntu.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-ubuntu.in b/templates/lxc-ubuntu.in
index 022acf4..92be563 100644
--- a/templates/lxc-ubuntu.in
+++ b/templates/lxc-ubuntu.in
@@ -342,7 +342,7 @@ download_ubuntu()
             ;;
     esac
 
-    packages_template=${packages_template:-"ssh,vim"}
+    packages_template=${packages_template:-"apt-transport-https,ssh,vim"}
     debootstrap_parameters=
 
     # Try to guess a list of langpacks to install
@@ -359,7 +359,7 @@ download_ubuntu()
         debootstrap_parameters="$debootstrap_parameters --variant=$variant"
     fi
     if [ "$variant" = 'minbase' ]; then
-        packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client,apt-transport-https"
+        packages_template="${packages_template},sudo,ifupdown,isc-dhcp-client"
     fi
 
     echo "Installing packages in template: ${packages_template}"

From 38788e4878f23a1be3479b3dde45c774340c82f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 7 Jun 2016 15:10:24 -0400
Subject: [PATCH 051/334] Drop lxc-devsetup as unneeded by current autodev
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/init/common/Makefile.am         |  4 ++--
 config/init/common/lxc-devsetup        | 25 -------------------------
 config/init/systemd/lxc.service.in     |  1 -
 config/init/sysvinit/lxc-containers.in |  1 -
 config/init/upstart/lxc.conf.in        |  3 ---
 lxc.spec.in                            |  1 -
 6 files changed, 2 insertions(+), 33 deletions(-)
 delete mode 100755 config/init/common/lxc-devsetup

diff --git a/config/init/common/Makefile.am b/config/init/common/Makefile.am
index 123e800..8c0134c 100644
--- a/config/init/common/Makefile.am
+++ b/config/init/common/Makefile.am
@@ -1,2 +1,2 @@
-EXTRA_DIST = lxc-containers.in lxc-net.in lxc-devsetup
-pkglibexec_SCRIPTS = lxc-containers lxc-net lxc-devsetup
+EXTRA_DIST = lxc-containers.in lxc-net.in
+pkglibexec_SCRIPTS = lxc-containers lxc-net
diff --git a/config/init/common/lxc-devsetup b/config/init/common/lxc-devsetup
deleted file mode 100755
index e765daf..0000000
--- a/config/init/common/lxc-devsetup
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh -
-
-# lxc.devsetup - Setup host /dev for container /dev subdirectories.
-
-if [ ! -d /dev/.lxc ]
-then
-    echo "Creating /dev/.lxc"
-    mkdir /dev/.lxc
-    chmod 755 /dev/.lxc
-fi
-
-if grep -q "/dev devtmpfs " /proc/self/mounts
-then
-    echo "/dev is devtmpfs"
-else
-    echo "/dev is not devtmpfs - mounting tmpfs on .lxc"
-    mount -t tmpfs tmpfs /dev/.lxc
-fi
-
-if [ ! -d /dev/.lxc/user ]
-then
-    echo "Creating /dev/.lxc/user"
-    mkdir /dev/.lxc/user
-    chmod 1777 /dev/.lxc/user
-fi
diff --git a/config/init/systemd/lxc.service.in b/config/init/systemd/lxc.service.in
index fd26e83..9876155 100644
--- a/config/init/systemd/lxc.service.in
+++ b/config/init/systemd/lxc.service.in
@@ -6,7 +6,6 @@ Wants=lxc-net.service
 [Service]
 Type=oneshot
 RemainAfterExit=yes
-ExecStartPre=@LIBEXECDIR@/lxc/lxc-devsetup
 ExecStartPre=@LIBEXECDIR@/lxc/lxc-apparmor-load
 ExecStart=@LIBEXECDIR@/lxc/lxc-containers start
 ExecStop=@LIBEXECDIR@/lxc/lxc-containers stop
diff --git a/config/init/sysvinit/lxc-containers.in b/config/init/sysvinit/lxc-containers.in
index 3b38393..a7502a8 100644
--- a/config/init/sysvinit/lxc-containers.in
+++ b/config/init/sysvinit/lxc-containers.in
@@ -29,7 +29,6 @@ test ! -r /lib/lsb/init-functions ||
 
 start() {
     # Setup host /dev for autodev containers.
-    @LIBEXECDIR@/lxc/lxc-devsetup
     log_daemon_msg "Starting LXC autoboot containers: "
     @LIBEXECDIR@/lxc/lxc-containers start
 }
diff --git a/config/init/upstart/lxc.conf.in b/config/init/upstart/lxc.conf.in
index 899fe11..437db3c 100644
--- a/config/init/upstart/lxc.conf.in
+++ b/config/init/upstart/lxc.conf.in
@@ -45,9 +45,6 @@ pre-start script
 		fi
 	fi
 
-	# Setup host /dev for autodev containers.
-	@LIBEXECDIR@/lxc/lxc-devsetup
-
 	[ "x$LXC_AUTO" = "xtrue" ] || exit 0
 
 	if [ -n "$BOOTGROUPS" ]
diff --git a/lxc.spec.in b/lxc.spec.in
index 9cc8dc5..099b595 100644
--- a/lxc.spec.in
+++ b/lxc.spec.in
@@ -275,7 +275,6 @@ fi
 %{_libexecdir}/%{name}
 %attr(4111,root,root) %{_libexecdir}/%{name}/lxc-user-nic
 %if %{with_systemd}
-%attr(555,root,root) %{_libexecdir}/%{name}/lxc-devsetup
 %attr(555,root,root) %{_libexecdir}/%{name}/lxc-net
 %attr(555,root,root) %{_libexecdir}/%{name}/lxc-containers
 %endif

From 0cd7f6f94ed70c3f19329cfbd0bc659e331c21cb Mon Sep 17 00:00:00 2001
From: Thomas Tanaka <thomas.tanaka at oracle.com>
Date: Thu, 9 Jun 2016 13:41:02 -0700
Subject: [PATCH 052/334] Unable to login via console in OL7.2

There is container-getty.service with OL7.2 systemd, it
is also used for managing the getty service, use that
instead and not manually create it.

Signed-off-by: Thomas Tanaka <thomas.tanaka at oracle.com>
---
 templates/lxc-oracle.in | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/templates/lxc-oracle.in b/templates/lxc-oracle.in
index 00af55d..eb01ecb 100644
--- a/templates/lxc-oracle.in
+++ b/templates/lxc-oracle.in
@@ -145,21 +145,25 @@ EOF
 
     # OL7 has systemd, no rc.sysinit
     if [ $container_release_major = "7" ]; then
-        # from mhw in the fedora template: We do need to disable the
-        # "ConditionalPathExists=/dev/tty0" line or no gettys are started on
-        # the ttys in the container. Lets do it in an override copy of the
-        # service so it can still pass rpm verifies and not be automatically
-        # updated by a new systemd version.
-        sed -e 's/^ConditionPathExists=/#LXC ConditionPathExists=/' \
-            < $container_rootfs/usr/lib/systemd/system/getty\@.service \
-            > $container_rootfs/etc/systemd/system/getty\@.service
-        # Setup getty service on the 4 ttys we are going to allow in the
-        # default config.  Number should match lxc.tty
-        ( cd $container_rootfs/etc/systemd/system/getty.target.wants
-            for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty at tty${i}.service; done )
-        # We only want to spawn a getty on /dev/console in lxc, libvirt-lxc
-        # symlinks /dev/console to /dev/tty1
-        sed -i '/Before=getty.target/a ConditionVirtualization=lxc' $container_rootfs/usr/lib/systemd/system/console-getty.service
+        # with newer systemd (OL7.2), getty service include container-getty.service
+        # let that be the one who manage the getty service instead
+        if [ ! -f $container_rootfs/usr/lib/systemd/system/container-getty at .service ]; then
+        	# from mhw in the fedora template: We do need to disable the
+        	# "ConditionalPathExists=/dev/tty0" line or no gettys are started on
+        	# the ttys in the container. Lets do it in an override copy of the
+        	# service so it can still pass rpm verifies and not be automatically
+        	# updated by a new systemd version.
+        	sed -e 's/^ConditionPathExists=/#LXC ConditionPathExists=/' \
+            		< $container_rootfs/usr/lib/systemd/system/getty\@.service \
+            		> $container_rootfs/etc/systemd/system/getty\@.service
+        	# Setup getty service on the 4 ttys we are going to allow in the
+        	# default config.  Number should match lxc.tty
+        	( cd $container_rootfs/etc/systemd/system/getty.target.wants
+            		for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty at tty${i}.service; done )
+        	# We only want to spawn a getty on /dev/console in lxc, libvirt-lxc
+        	# symlinks /dev/console to /dev/tty1
+        	sed -i '/Before=getty.target/a ConditionVirtualization=lxc' $container_rootfs/usr/lib/systemd/system/console-getty.service
+        fi
 
         # disable some systemd services, set default boot, sigpwr target
         rm -f $container_rootfs/usr/lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service

From 7f5a16e41bb87f88725a3577d2a91ed5dc2db73e Mon Sep 17 00:00:00 2001
From: Antonio Terceiro <terceiro at softwarelivre.org>
Date: Fri, 17 Jun 2016 19:00:56 -0300
Subject: [PATCH 053/334] lxc-debian: make sure init is installed

init 1.34 is not "Essential" anymore, in order to make it not required
on minimal chroots, docker containers, etc. Because of that we now need
to manually include it on systems that are expected to boot.

Signed-off-by: Antonio Terceiro <terceiro at debian.org>
---
 templates/lxc-debian.in | 1 +
 1 file changed, 1 insertion(+)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 1ed6f20..60025d3 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -242,6 +242,7 @@ cleanup()
 download_debian()
 {
     packages=\
+init,\
 ifupdown,\
 locales,\
 libui-dialog-perl,\

From f2b17b4309e6a0bf2a319340576b8c4e3141ae91 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Tue, 21 Jun 2016 11:06:25 +0900
Subject: [PATCH 054/334] plamo: Improve Plamo template

* configure to start only the minimum of service
* add ntp, kmod to ignore packages

Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 templates/lxc-plamo.in | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/templates/lxc-plamo.in b/templates/lxc-plamo.in
index 48cde46..009fa4f 100644
--- a/templates/lxc-plamo.in
+++ b/templates/lxc-plamo.in
@@ -49,7 +49,7 @@ MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"}
 CATEGORIES=${CATEGORIES-"00_base 01_minimum"}
 EXTRACTGRS=${EXTRACTGRS-""}
 IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl
-    cpufreqd cpufrequtils gpm"}
+    cpufreqd cpufrequtils gpm ntp kmod"}
 ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"}
 
 download_plamo() {
@@ -222,6 +222,14 @@ configure_plamo() {
   sh /tmp/netconfig.rconly
   rm -f /tmp/netconfig.rconly
   sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet
+  # /etc/rc.d/rc.inet2
+  sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2
+  sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2
+  # configure to start only the minimum of service
+  chmod 644 $rootfs/etc/rc.d/init.d/saslauthd
+  chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi
+  rm -f $rootfs/etc/rc.d/init.d/postfix
+  rm -f $rootfs/var/log/initpkg/shadow
   return 0
 }
 

From 9a1d96120f578d35227895aff3852ef10a9e1b1d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 23 Jun 2016 16:01:29 -0400
Subject: [PATCH 055/334] apparmor: Allow bind-mounts and {r}shared/{r}private
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bind-mounts aren't harmful in containers, so long as they're not used to
bypass MAC policies.

This change allows bind-mounting of any path which isn't a dangerous
filesystem that's otherwise blocked by apparmor.

This also allows switching paths {r}shared or {r}private.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/apparmor/abstractions/container-base    | 38 +++++++++++++++++++++-----
 config/apparmor/abstractions/container-base.in | 38 +++++++++++++++++++++-----
 2 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index fe24ff3..9452f66 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -60,13 +60,6 @@
   mount fstype=fuse,
   mount fstype=fuse.*,
 
-  # allow bind mount of /lib/init/fstab for lxcguest
-  mount options=(rw, bind) /lib/init/fstab.lxc/ -> /lib/init/fstab/,
-
-  # allow bind mounts of /run/{,lock} to /var/run/{,lock}
-  mount options=(rw, bind) /run/ -> /var/run/,
-  mount options=(rw, bind) /run/lock/ -> /var/lock/,
-
   # deny access under /proc/bus to avoid e.g. messing with pci devices directly
   deny @{PROC}/bus/** wklx,
 
@@ -100,6 +93,37 @@
   # deny reads from debugfs
   deny /sys/kernel/debug/{,**} rwklx,
 
+  # allow paths to be made shared, rshared, private or rprivate
+  mount options=(rw,shared) -> /,
+  mount options=(rw,shared) -> /**,
+
+  mount options=(rw,rshared) -> /,
+  mount options=(rw,rshared) -> /**,
+
+  mount options=(rw,private) -> /,
+  mount options=(rw,private) -> /**,
+
+  mount options=(rw,rprivate) -> /,
+  mount options=(rw,rprivate) -> /**,
+
+  # allow bind-mounts of anything except /proc, /sys and /dev
+  mount options=(rw,bind) /[^spd]*{,/**},
+  mount options=(rw,bind) /d[^e]*{,/**},
+  mount options=(rw,bind) /de[^v]*{,/**},
+  mount options=(rw,bind) /dev/.[^l]*{,/**},
+  mount options=(rw,bind) /dev/.l[^x]*{,/**},
+  mount options=(rw,bind) /dev/.lx[^c]*{,/**},
+  mount options=(rw,bind) /dev/.lxc?*{,/**},
+  mount options=(rw,bind) /dev/[^.]*{,/**},
+  mount options=(rw,bind) /dev?*{,/**},
+  mount options=(rw,bind) /p[^r]*{,/**},
+  mount options=(rw,bind) /pr[^o]*{,/**},
+  mount options=(rw,bind) /pro[^c]*{,/**},
+  mount options=(rw,bind) /proc?*{,/**},
+  mount options=(rw,bind) /s[^y]*{,/**},
+  mount options=(rw,bind) /sy[^s]*{,/**},
+  mount options=(rw,bind) /sys?*{,/**},
+
   # generated by: lxc-generate-aa-rules.py container-rules.base
   deny /proc/sys/[^kn]*{,/**} wklx,
   deny /proc/sys/k[^e]*{,/**} wklx,
diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
index 550625c..68db43d 100644
--- a/config/apparmor/abstractions/container-base.in
+++ b/config/apparmor/abstractions/container-base.in
@@ -60,13 +60,6 @@
   mount fstype=fuse,
   mount fstype=fuse.*,
 
-  # allow bind mount of /lib/init/fstab for lxcguest
-  mount options=(rw, bind) /lib/init/fstab.lxc/ -> /lib/init/fstab/,
-
-  # allow bind mounts of /run/{,lock} to /var/run/{,lock}
-  mount options=(rw, bind) /run/ -> /var/run/,
-  mount options=(rw, bind) /run/lock/ -> /var/lock/,
-
   # deny access under /proc/bus to avoid e.g. messing with pci devices directly
   deny @{PROC}/bus/** wklx,
 
@@ -100,3 +93,34 @@
   # deny reads from debugfs
   deny /sys/kernel/debug/{,**} rwklx,
 
+  # allow paths to be made shared, rshared, private or rprivate
+  mount options=(rw,shared) -> /,
+  mount options=(rw,shared) -> /**,
+
+  mount options=(rw,rshared) -> /,
+  mount options=(rw,rshared) -> /**,
+
+  mount options=(rw,private) -> /,
+  mount options=(rw,private) -> /**,
+
+  mount options=(rw,rprivate) -> /,
+  mount options=(rw,rprivate) -> /**,
+
+  # allow bind-mounts of anything except /proc, /sys and /dev
+  mount options=(rw,bind) /[^spd]*{,/**},
+  mount options=(rw,bind) /d[^e]*{,/**},
+  mount options=(rw,bind) /de[^v]*{,/**},
+  mount options=(rw,bind) /dev/.[^l]*{,/**},
+  mount options=(rw,bind) /dev/.l[^x]*{,/**},
+  mount options=(rw,bind) /dev/.lx[^c]*{,/**},
+  mount options=(rw,bind) /dev/.lxc?*{,/**},
+  mount options=(rw,bind) /dev/[^.]*{,/**},
+  mount options=(rw,bind) /dev?*{,/**},
+  mount options=(rw,bind) /p[^r]*{,/**},
+  mount options=(rw,bind) /pr[^o]*{,/**},
+  mount options=(rw,bind) /pro[^c]*{,/**},
+  mount options=(rw,bind) /proc?*{,/**},
+  mount options=(rw,bind) /s[^y]*{,/**},
+  mount options=(rw,bind) /sy[^s]*{,/**},
+  mount options=(rw,bind) /sys?*{,/**},
+

From 5b0e4923bc39cf34215e44fccc425b1f3e42674b Mon Sep 17 00:00:00 2001
From: AnrDaemon <anrdaemon at freemail.ru>
Date: Fri, 24 Jun 2016 06:19:51 +0300
Subject: [PATCH 056/334] Force lxc-instance to behave like a good Upstart
 client

Remove unnecessary shell wrap around job start.
Force foreground execution to allow job monitoring and control.

Signed-off-by Andrey Repin <anrdaemon at yandex.ru>
---
 config/init/upstart/lxc-instance.conf | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/config/init/upstart/lxc-instance.conf b/config/init/upstart/lxc-instance.conf
index 58d045d..1c9c3e6 100644
--- a/config/init/upstart/lxc-instance.conf
+++ b/config/init/upstart/lxc-instance.conf
@@ -17,6 +17,4 @@ pre-start script
 	lxc-wait -s RUNNING -n $NAME -t 0 && { stop; exit 0; } || true
 end script
 
-script
-	exec lxc-start -n $NAME
-end script
+exec lxc-start -F -n $NAME

From 7e4c9a30feb3905902a158cde099f4510a54d5ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 27 Jun 2016 15:11:16 -0400
Subject: [PATCH 057/334] apparmor: allow mount move
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/apparmor/abstractions/container-base    | 18 ++++++++++++++++++
 config/apparmor/abstractions/container-base.in | 18 ++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index 9452f66..7533fdb 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -124,6 +124,24 @@
   mount options=(rw,bind) /sy[^s]*{,/**},
   mount options=(rw,bind) /sys?*{,/**},
 
+  # allow moving mounts except for /proc, /sys and /dev
+  mount options=(rw,move) /[^spd]*{,/**},
+  mount options=(rw,move) /d[^e]*{,/**},
+  mount options=(rw,move) /de[^v]*{,/**},
+  mount options=(rw,move) /dev/.[^l]*{,/**},
+  mount options=(rw,move) /dev/.l[^x]*{,/**},
+  mount options=(rw,move) /dev/.lx[^c]*{,/**},
+  mount options=(rw,move) /dev/.lxc?*{,/**},
+  mount options=(rw,move) /dev/[^.]*{,/**},
+  mount options=(rw,move) /dev?*{,/**},
+  mount options=(rw,move) /p[^r]*{,/**},
+  mount options=(rw,move) /pr[^o]*{,/**},
+  mount options=(rw,move) /pro[^c]*{,/**},
+  mount options=(rw,move) /proc?*{,/**},
+  mount options=(rw,move) /s[^y]*{,/**},
+  mount options=(rw,move) /sy[^s]*{,/**},
+  mount options=(rw,move) /sys?*{,/**},
+
   # generated by: lxc-generate-aa-rules.py container-rules.base
   deny /proc/sys/[^kn]*{,/**} wklx,
   deny /proc/sys/k[^e]*{,/**} wklx,
diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
index 68db43d..022d04d 100644
--- a/config/apparmor/abstractions/container-base.in
+++ b/config/apparmor/abstractions/container-base.in
@@ -124,3 +124,21 @@
   mount options=(rw,bind) /sy[^s]*{,/**},
   mount options=(rw,bind) /sys?*{,/**},
 
+  # allow moving mounts except for /proc, /sys and /dev
+  mount options=(rw,move) /[^spd]*{,/**},
+  mount options=(rw,move) /d[^e]*{,/**},
+  mount options=(rw,move) /de[^v]*{,/**},
+  mount options=(rw,move) /dev/.[^l]*{,/**},
+  mount options=(rw,move) /dev/.l[^x]*{,/**},
+  mount options=(rw,move) /dev/.lx[^c]*{,/**},
+  mount options=(rw,move) /dev/.lxc?*{,/**},
+  mount options=(rw,move) /dev/[^.]*{,/**},
+  mount options=(rw,move) /dev?*{,/**},
+  mount options=(rw,move) /p[^r]*{,/**},
+  mount options=(rw,move) /pr[^o]*{,/**},
+  mount options=(rw,move) /pro[^c]*{,/**},
+  mount options=(rw,move) /proc?*{,/**},
+  mount options=(rw,move) /s[^y]*{,/**},
+  mount options=(rw,move) /sy[^s]*{,/**},
+  mount options=(rw,move) /sys?*{,/**},
+

From 549a40b6128892112895299e445e0564c3faaea2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 27 Jun 2016 15:15:15 -0400
Subject: [PATCH 058/334] apparmor: Update mount states handling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Properly list all of the states and the right apparmor stanza for them,
then comment them all as actually enabling this would currently let the
user bypass apparmor entirely.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/apparmor/abstractions/container-base    | 21 +++++++++------------
 config/apparmor/abstractions/container-base.in | 22 ++++++++++------------
 2 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index 7533fdb..0aacb6a 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -93,18 +93,15 @@
   # deny reads from debugfs
   deny /sys/kernel/debug/{,**} rwklx,
 
-  # allow paths to be made shared, rshared, private or rprivate
-  mount options=(rw,shared) -> /,
-  mount options=(rw,shared) -> /**,
-
-  mount options=(rw,rshared) -> /,
-  mount options=(rw,rshared) -> /**,
-
-  mount options=(rw,private) -> /,
-  mount options=(rw,private) -> /**,
-
-  mount options=(rw,rprivate) -> /,
-  mount options=(rw,rprivate) -> /**,
+  # allow paths to be made slave, shared, private or unbindable
+  mount options=(rw,make-slave) -> **,
+  mount options=(rw,make-rslave) -> **,
+  mount options=(rw,make-shared) -> **,
+  mount options=(rw,make-rshared) -> **,
+  mount options=(rw,make-private) -> **,
+  mount options=(rw,make-rprivate) -> **,
+  mount options=(rw,make-unbindable) -> **,
+  mount options=(rw,make-runbindable) -> **,
 
   # allow bind-mounts of anything except /proc, /sys and /dev
   mount options=(rw,bind) /[^spd]*{,/**},
diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
index 022d04d..5bc9b28 100644
--- a/config/apparmor/abstractions/container-base.in
+++ b/config/apparmor/abstractions/container-base.in
@@ -93,18 +93,16 @@
   # deny reads from debugfs
   deny /sys/kernel/debug/{,**} rwklx,
 
-  # allow paths to be made shared, rshared, private or rprivate
-  mount options=(rw,shared) -> /,
-  mount options=(rw,shared) -> /**,
-
-  mount options=(rw,rshared) -> /,
-  mount options=(rw,rshared) -> /**,
-
-  mount options=(rw,private) -> /,
-  mount options=(rw,private) -> /**,
-
-  mount options=(rw,rprivate) -> /,
-  mount options=(rw,rprivate) -> /**,
+  # allow paths to be made slave, shared, private or unbindable
+  # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
+#  mount options=(rw,make-slave) -> **,
+#  mount options=(rw,make-rslave) -> **,
+#  mount options=(rw,make-shared) -> **,
+#  mount options=(rw,make-rshared) -> **,
+#  mount options=(rw,make-private) -> **,
+#  mount options=(rw,make-rprivate) -> **,
+#  mount options=(rw,make-unbindable) -> **,
+#  mount options=(rw,make-runbindable) -> **,
 
   # allow bind-mounts of anything except /proc, /sys and /dev
   mount options=(rw,bind) /[^spd]*{,/**},

From 05352fc9304f465b9322e22d19f62641d82dc6ad Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Mon, 27 Jun 2016 16:20:00 -0400
Subject: [PATCH 059/334] AppArmor: add make-rslave to usr.bin.lxc-start

The profile already contains
  mount options=(rw, make-slave) -> **,

Which allows going through all mountpoints with make-slave,
so it seems to make sense to also allow the directly
recursive variant with "make-rslave".

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
---
 config/apparmor/abstractions/start-container | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config/apparmor/abstractions/start-container b/config/apparmor/abstractions/start-container
index b06a84d..eee0c2f 100644
--- a/config/apparmor/abstractions/start-container
+++ b/config/apparmor/abstractions/start-container
@@ -15,6 +15,7 @@
   mount options=bind /dev/pts/ptmx/ -> /dev/ptmx/,
   mount options=bind /dev/pts/** -> /dev/**,
   mount options=(rw, make-slave) -> **,
+  mount options=(rw, make-rslave) -> **,
   mount fstype=debugfs,
   # allow pre-mount hooks to stage mounts under /var/lib/lxc/<container>/
   mount -> /var/lib/lxc/{**,},

From 9179d21a5df6d41770df2aa67653722596ab079e Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 27 Jun 2016 22:24:09 +0000
Subject: [PATCH 060/334] c/r: use criu's "full" mode for cgroups

A while ago cgroup modes were introduced to CRIU, which slightly changed
the behavior w.r.t. cgroups under the hood. What we're really after is
criu's --full mode, i.e. even if a particular cgroup directory exists
(in particular /lxc/$container[-$number] will, since we create it), we
should restore perms on that cgroup.

Things worked just fine for actual properties (except "special" properties
as criu refers to them, which I've just sent a patch for) because liblxc
creates no subdirectories, just the TLD.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index ce8ada6..a1b7d40 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -135,7 +135,7 @@ static void exec_criu(struct criu_opts *opts)
 
 	/* The command line always looks like:
 	 * criu $(action) --tcp-established --file-locks --link-remap \
-	 * --manage-cgroups action-script foo.sh -D $(directory) \
+	 * --manage-cgroups=full action-script foo.sh -D $(directory) \
 	 * -o $(directory)/$(action).log --ext-mount-map auto
 	 * --enable-external-sharing --enable-external-masters
 	 * --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n
@@ -218,7 +218,7 @@ static void exec_criu(struct criu_opts *opts)
 	DECLARE_ARG("--tcp-established");
 	DECLARE_ARG("--file-locks");
 	DECLARE_ARG("--link-remap");
-	DECLARE_ARG("--manage-cgroups");
+	DECLARE_ARG("--manage-cgroups=full");
 	DECLARE_ARG("--ext-mount-map");
 	DECLARE_ARG("auto");
 	DECLARE_ARG("--enable-external-sharing");

From 155543d95101b6176fbe2553b766faf55a499890 Mon Sep 17 00:00:00 2001
From: Preetam D'Souza <preetamjdsouza at gmail.com>
Date: Mon, 27 Jun 2016 23:12:12 -0400
Subject: [PATCH 061/334] Include all lxcmntent.h function declarations on
 Bionic

Newer versions of Android (5.0+, aka API Level 21+) include mntent.h,
which declares setmntent and endmntent. This hits an edge
case with the preprocessor checks in lxcmntent.h because HAVE_SETMNTENT
and HAVE_ENDMNTENT are both defined (in Bionic's mntent.h), but conf.c
always includes lxcmntent.h on Bionic! As a result, we get compiler
warnings of implicit function declarations for setmntent endmntent.

This patch always includes setmntent/endmntent/hasmntopt function
declarations on Bionic, which gets rid of these warnings.

Signed-off-by: Preetam D'Souza <preetamjdsouza at gmail.com>
---
 src/include/lxcmntent.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/include/lxcmntent.h b/src/include/lxcmntent.h
index bf731a0..25df5b9 100644
--- a/src/include/lxcmntent.h
+++ b/src/include/lxcmntent.h
@@ -36,15 +36,15 @@ extern struct mntent *getmntent (FILE *stream);
 extern struct mntent *getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz);
 #endif
 
-#ifndef HAVE_SETMNTENT
+#if !defined(HAVE_SETMNTENT) || IS_BIONIC
 FILE *setmntent (const char *file, const char *mode);
 #endif
 
-#ifndef HAVE_ENDMNTENT
+#if !defined(HAVE_ENDMNTENT) || IS_BIONIC
 int endmntent (FILE *stream);
 #endif
 
-#ifndef HAVE_HASMNTOPT
+#if !defined(HAVE_HASMNTOPT) || IS_BIONIC
 extern char *hasmntopt (const struct mntent *mnt, const char *opt);
 #endif
 

From bde3d22a044fa95e71fa7f62a02ccd163a893b3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 28 Jun 2016 14:17:55 -0400
Subject: [PATCH 062/334] change version to 2.0.2 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 586a0f1..ad7f7c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 1)
+m4_define([lxc_version_micro], 2)
 m4_define([lxc_version_beta], [])
 m4_define([lxc_version_abi], 1.2.0)
 

From 564ad051ce487e5f684feb4ace09545ef9e1b9d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 28 Jun 2016 15:35:58 -0400
Subject: [PATCH 063/334] apparmor: Refresh generated file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 config/apparmor/abstractions/container-base | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index 0aacb6a..06290de 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -94,14 +94,15 @@
   deny /sys/kernel/debug/{,**} rwklx,
 
   # allow paths to be made slave, shared, private or unbindable
-  mount options=(rw,make-slave) -> **,
-  mount options=(rw,make-rslave) -> **,
-  mount options=(rw,make-shared) -> **,
-  mount options=(rw,make-rshared) -> **,
-  mount options=(rw,make-private) -> **,
-  mount options=(rw,make-rprivate) -> **,
-  mount options=(rw,make-unbindable) -> **,
-  mount options=(rw,make-runbindable) -> **,
+  # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
+#  mount options=(rw,make-slave) -> **,
+#  mount options=(rw,make-rslave) -> **,
+#  mount options=(rw,make-shared) -> **,
+#  mount options=(rw,make-rshared) -> **,
+#  mount options=(rw,make-private) -> **,
+#  mount options=(rw,make-rprivate) -> **,
+#  mount options=(rw,make-unbindable) -> **,
+#  mount options=(rw,make-runbindable) -> **,
 
   # allow bind-mounts of anything except /proc, /sys and /dev
   mount options=(rw,bind) /[^spd]*{,/**},

From 5c27394ee7a2795a5c3eb125579ed5999034c82d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 28 Jun 2016 15:38:30 -0400
Subject: [PATCH 064/334] change version to 2.0.3 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index ad7f7c0..cb7f641 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 2)
+m4_define([lxc_version_micro], 3)
 m4_define([lxc_version_beta], [])
 m4_define([lxc_version_abi], 1.2.0)
 

From ca53937eb9b555631cadf693176e92a0c7fb9506 Mon Sep 17 00:00:00 2001
From: Antonio Terceiro <terceiro at debian.org>
Date: Wed, 29 Jun 2016 14:58:35 -0300
Subject: [PATCH 065/334] lxc-debian: fix regression when creating wheezy
 containers

The regression was introduced by commit
3c39b0b7a2b445e08d2e2aecb05566075f4f3423 which makes it possible to
create working stretch containers by forcinig `init` to be in the
included package list.

However, `init` didn't exit before jessie, so now for wheezy we
explicitly include `sysvinit`; sysvinit on wheezy is essential,
so it would already be included anyway.

Signed-off-by: Antonio Terceiro <terceiro at debian.org>
---
 templates/lxc-debian.in | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 60025d3..ccce6da 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -241,8 +241,16 @@ cleanup()
 
 download_debian()
 {
+    case "$release" in
+      wheezy)
+        init=sysvinit
+        ;;
+      *)
+        init=init
+        ;;
+    esac
     packages=\
-init,\
+$init,\
 ifupdown,\
 locales,\
 libui-dialog-perl,\

From 659ce93a2e405f928cd4e1a457270572571a8db8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 29 Jun 2016 16:56:41 -0400
Subject: [PATCH 066/334] Fix typo found by lintian
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 doc/ja/lxc-attach.sgml.in | 2 +-
 doc/ko/lxc-attach.sgml.in | 2 +-
 doc/lxc-attach.sgml.in    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/ja/lxc-attach.sgml.in b/doc/ja/lxc-attach.sgml.in
index 2a8d5b6..25322da 100644
--- a/doc/ja/lxc-attach.sgml.in
+++ b/doc/ja/lxc-attach.sgml.in
@@ -327,7 +327,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
           <para>
             <!--
             <emphasis>Important:</emphasis>  When a standard file descriptor
-            does not refer to a pty ouput produced on it will not be logged.
+            does not refer to a pty output produced on it will not be logged.
             -->
             <emphasis>重要:</emphasis> 標準ファイルディスクリプタが pty を参照していない場合、それらに対する出力は記録されないでしょう。
           </para>
diff --git a/doc/ko/lxc-attach.sgml.in b/doc/ko/lxc-attach.sgml.in
index 3a6e9b1..eb7baf0 100644
--- a/doc/ko/lxc-attach.sgml.in
+++ b/doc/ko/lxc-attach.sgml.in
@@ -316,7 +316,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
           <para>
             <!--
             <emphasis>Important:</emphasis>  When a standard file descriptor
-            does not refer to a pty ouput produced on it will not be logged.
+            does not refer to a pty output produced on it will not be logged.
             -->
             <emphasis>중요:</emphasis> 표준 입출력 파일 디스크립터가 pty를 참조하지 않으면, 기록되지 않는다.
           </para>
diff --git a/doc/lxc-attach.sgml.in b/doc/lxc-attach.sgml.in
index 2b7203f..3b103f9 100644
--- a/doc/lxc-attach.sgml.in
+++ b/doc/lxc-attach.sgml.in
@@ -247,7 +247,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 	  </para>
 	  <para>
 	    <emphasis>Important:</emphasis>  When a standard file descriptor
-	    does not refer to a pty ouput produced on it will not be logged.
+	    does not refer to a pty output produced on it will not be logged.
 	  </para>
 	</listitem>
       </varlistentry>

From ea986a874775a0800194822aed9359e73297970d Mon Sep 17 00:00:00 2001
From: Rodrigo Vaz <rodrigo.vaz at gmail.com>
Date: Fri, 1 Jul 2016 18:34:11 -0700
Subject: [PATCH 067/334] Add flag in mount_entry to skip NODEV in case of a
 persistent dev entry

Signed-off-by: Rodrigo Vaz <rodrigo at heroku.com>
---
 src/lxc/conf.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index e8dfaae..009aac8 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1634,7 +1634,7 @@ static char *get_field(char *src, int nfields)
 
 static int mount_entry(const char *fsname, const char *target,
 		       const char *fstype, unsigned long mountflags,
-		       const char *data, int optional, const char *rootfs)
+		       const char *data, int optional, int dev, const char *rootfs)
 {
 #ifdef HAVE_STATVFS
 	struct statvfs sb;
@@ -1663,7 +1663,7 @@ static int mount_entry(const char *fsname, const char *target,
 			unsigned long required_flags = rqd_flags;
 			if (sb.f_flag & MS_NOSUID)
 				required_flags |= MS_NOSUID;
-			if (sb.f_flag & MS_NODEV)
+			if (sb.f_flag & MS_NODEV && !dev)
 				required_flags |= MS_NODEV;
 			if (sb.f_flag & MS_RDONLY)
 				required_flags |= MS_RDONLY;
@@ -1785,6 +1785,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
 	char *mntdata;
 	int ret;
 	bool optional = hasmntopt(mntent, "optional") != NULL;
+	bool dev = hasmntopt(mntent, "dev") != NULL;
 
 	char *rootfs_path = NULL;
 	if (rootfs && rootfs->path)
@@ -1803,7 +1804,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
 	}
 
 	ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags,
-			  mntdata, optional, rootfs_path);
+			  mntdata, optional, dev, rootfs_path);
 
 	free(mntdata);
 	return ret;

From 5dc180dd2a87f69c912118dc78ae0ad9b3d1e206 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge at hallyn.com>
Date: Fri, 1 Jul 2016 21:18:38 -0500
Subject: [PATCH 068/334] cgfsng: don't pre-calculate path

First, we're doing this so long a there is any cgroup config item -
even if no devices ones.  Then if devices is not available we fail.
This was leading to Rob E's mysterious startup failures.

Secondly, we're not even using this info.  The user was removed
awhile back.

Signed-off-by: Serge Hallyn <serge at hallyn.com>
---
 src/lxc/cgfsng.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/src/lxc/cgfsng.c b/src/lxc/cgfsng.c
index 1e72347..0ea7b39 100644
--- a/src/lxc/cgfsng.c
+++ b/src/lxc/cgfsng.c
@@ -1627,8 +1627,6 @@ static bool cgfsng_setup_limits(void *hdata, struct lxc_list *cgroup_settings,
 	struct cgfsng_handler_data *d = hdata;
 	struct lxc_list *iterator, *sorted_cgroup_settings, *next;
 	struct lxc_cgroup *cg;
-	struct hierarchy *h;
-	char *listpath = NULL;
 	bool ret = false;
 
 	if (lxc_list_empty(cgroup_settings))
@@ -1639,15 +1637,6 @@ static bool cgfsng_setup_limits(void *hdata, struct lxc_list *cgroup_settings,
 		return false;
 	}
 
-	if (do_devices) {
-		h = get_hierarchy("devices");
-		if (!h) {
-			ERROR("No devices cgroup setup for %s", d->name);
-			return false;
-		}
-		listpath = must_make_path(h->fullcgpath, "devices.list", NULL);
-	}
-
 	lxc_list_for_each(iterator, sorted_cgroup_settings) {
 		cg = iterator->elem;
 
@@ -1670,7 +1659,6 @@ static bool cgfsng_setup_limits(void *hdata, struct lxc_list *cgroup_settings,
 	ret = true;
 	INFO("cgroup has been setup");
 out:
-	free(listpath);
 	lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
 		lxc_list_del(iterator);
 		free(iterator);

From 606cd0e7d053a69166af998a2c636844e7fdb502 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Tue, 5 Jul 2016 16:52:21 +0200
Subject: [PATCH 069/334] store criu version

- If version != NULL criu_version_ok() stores the detected criu version in
  version. Allocates memory for version which must be freed by caller.
- If version == NULL criu_version_ok() will return true when the version
  matches, false in all other cases.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/criu.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index a1b7d40..838432f 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -402,8 +402,11 @@ static void exec_criu(struct criu_opts *opts)
  *
  * The intent is that when criu development slows down, we can drop this, but
  * for now we shouldn't attempt to c/r with versions that we know won't work.
+ *
+ * Note: If version != NULL criu_version() stores the detected criu version in
+ * version. Allocates memory for version which must be freed by caller.
  */
-static bool criu_version_ok()
+static bool criu_version_ok(char **version)
 {
 	int pipes[2];
 	pid_t pid;
@@ -436,7 +439,7 @@ static bool criu_version_ok()
 		exit(1);
 	} else {
 		FILE *f;
-		char version[1024];
+		char *tmp;
 		int patch;
 
 		close(pipes[1]);
@@ -452,16 +455,22 @@ static bool criu_version_ok()
 			return false;
 		}
 
-		if (fscanf(f, "Version: %1023[^\n]s", version) != 1)
+		tmp = malloc(1024);
+		if (!tmp) {
+			fclose(f);
+			return false;
+		}
+
+		if (fscanf(f, "Version: %1023[^\n]s", tmp) != 1)
 			goto version_error;
 
 		if (fgetc(f) != '\n')
 			goto version_error;
 
-		if (strcmp(version, CRIU_VERSION) >= 0)
+		if (strcmp(tmp, CRIU_VERSION) >= 0)
 			goto version_match;
 
-		if (fscanf(f, "GitID: v%1023[^-]s", version) != 1)
+		if (fscanf(f, "GitID: v%1023[^-]s", tmp) != 1)
 			goto version_error;
 
 		if (fgetc(f) != '-')
@@ -470,7 +479,7 @@ static bool criu_version_ok()
 		if (fscanf(f, "%d", &patch) != 1)
 			goto version_error;
 
-		if (strcmp(version, CRIU_GITID_VERSION) < 0)
+		if (strcmp(tmp, CRIU_GITID_VERSION) < 0)
 			goto version_error;
 
 		if (patch < CRIU_GITID_PATCHLEVEL)
@@ -478,10 +487,15 @@ static bool criu_version_ok()
 
 version_match:
 		fclose(f);
+		if (!version)
+			free(tmp);
+		else
+			*version = tmp;
 		return true;
 
 version_error:
 		fclose(f);
+		free(tmp);
 		ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore\n");
 		return false;
 	}
@@ -493,7 +507,7 @@ static bool criu_ok(struct lxc_container *c)
 {
 	struct lxc_list *it;
 
-	if (!criu_version_ok())
+	if (!criu_version_ok(NULL))
 		return false;
 
 	if (geteuid()) {

From fc51f291c5ae414911cc2fbb5fa40e02cfe5385a Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 6 Jul 2016 23:45:15 +0000
Subject: [PATCH 070/334] c/r: add support for CRIU's --action-script

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c         | 8 ++++++++
 src/lxc/lxccontainer.h | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 838432f..6bf0606 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -185,6 +185,9 @@ static void exec_criu(struct criu_opts *opts)
 	if (opts->user->verbose)
 		static_args++;
 
+	if (opts->user->action_script)
+		static_args += 2;
+
 	ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action);
 	if (ret < 0 || ret >= PATH_MAX) {
 		ERROR("logfile name too long\n");
@@ -235,6 +238,11 @@ static void exec_criu(struct criu_opts *opts)
 	if (opts->user->verbose)
 		DECLARE_ARG("-vvvvvv");
 
+	if (opts->user->action_script) {
+		DECLARE_ARG("--action-script");
+		DECLARE_ARG(opts->user->action_script);
+	}
+
 	if (strcmp(opts->action, "dump") == 0 || strcmp(opts->action, "pre-dump") == 0) {
 		char pid[32], *freezer_relative;
 
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index ecc66e2..bde4912 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -891,6 +891,11 @@ struct migrate_opts {
 	 * won't if e.g. you rsync the filesystems between two machines.
 	 */
 	bool preserves_inodes;
+
+	/* Path to an executable script that will be registered as a criu
+	 * "action script"
+	 */
+	char *action_script;
 };
 
 /*!

From 6ce2eaee989818a577a5fbd6ce1187b2e8460ea6 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber at redhat.com>
Date: Mon, 11 Jul 2016 21:55:43 +0200
Subject: [PATCH 071/334] c/r: initialize migrate_opts properly

The commit "c/r: add support for CRIU's --action-script" breaks
lxc-checkpoint on the command-line. It produces errors like:

 sh: $'\260\366\b\001': command not found

and then it fails. src/lxc/criu.c expects migrate_opts->action_script to
be either NULL, then it is ignored, or to actually contain the name of
an action scripts.

As the struct migrate_opts has not static storage is has to be explicitly
initialized or the value of the structure's members is indeterminate.

Signed-off-by: Adrian Reber <areber at redhat.com>
---
 src/lxc/lxccontainer.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 8bd9b8e..4a4dc42 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -3988,11 +3988,13 @@ WRAP_API_3(int, lxcapi_migrate, unsigned int, struct migrate_opts *, unsigned in
 
 static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool stop, bool verbose)
 {
-	struct migrate_opts opts = {
-		.directory = directory,
-		.stop = stop,
-		.verbose = verbose,
-	};
+	struct migrate_opts opts;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.directory = directory;
+	opts.stop = stop;
+	opts.verbose = verbose;
 
 	return !do_lxcapi_migrate(c, MIGRATE_DUMP, &opts, sizeof(opts));
 }
@@ -4001,10 +4003,12 @@ WRAP_API_3(bool, lxcapi_checkpoint, char *, bool, bool)
 
 static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool verbose)
 {
-	struct migrate_opts opts = {
-		.directory = directory,
-		.verbose = verbose,
-	};
+	struct migrate_opts opts;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.directory = directory;
+	opts.verbose = verbose;
 
 	return !do_lxcapi_migrate(c, MIGRATE_RESTORE, &opts, sizeof(opts));
 }

From 3c6054ecdda3fe510d411576e4e827bd26591cd1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Mon, 11 Jul 2016 22:48:48 +0200
Subject: [PATCH 072/334] add missing cgroup namespace to ns_info struct

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/start.c | 3 ++-
 src/lxc/start.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 5437206..b3f75b8 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -82,7 +82,8 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
 	[LXC_NS_UTS] = {"uts", CLONE_NEWUTS},
 	[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC},
 	[LXC_NS_USER] = {"user", CLONE_NEWUSER},
-	[LXC_NS_NET] = {"net", CLONE_NEWNET}
+	[LXC_NS_NET] = {"net", CLONE_NEWNET},
+	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP}
 };
 
 extern void mod_all_rdeps(struct lxc_container *c, bool inc);
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 86b19a2..fe47ab9 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -49,6 +49,7 @@ enum {
 	LXC_NS_IPC,
 	LXC_NS_USER,
 	LXC_NS_NET,
+	LXC_NS_CGROUP,
 	LXC_NS_MAX
 };
 

From 2fdca63d45448ffaa602e696865e456744fc0752 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber at redhat.com>
Date: Mon, 4 Jul 2016 16:58:09 +0200
Subject: [PATCH 073/334] c/r: drop in-flight connections during CRIU dump

Shortly after CRIU 2.3 has been released a patch has been added to skip
in-flight TCP connections. In-flight connections are not completely
established connections (SYN, SYN-ACK). Skipping in-flight TCP
connections means that the client has to re-initiate the connection
establishment.

This patch stores the CRIU version detected during version check, so
that during dump/checkpoint options can be dynamically enabled depending
on the available CRIU version.

v2:
   * use the newly introduced criu version interface
   * add an option to disable skipping in-flight connections

Signed-off-by: Adrian Reber <areber at redhat.com>
---
 src/lxc/criu.c         | 25 +++++++++++++++++++------
 src/lxc/lxccontainer.h |  6 ++++++
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 6bf0606..630e67b 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -50,6 +50,8 @@
 #define CRIU_GITID_VERSION	"2.0"
 #define CRIU_GITID_PATCHLEVEL	0
 
+#define CRIU_IN_FLIGHT_SUPPORT	"2.4"
+
 lxc_log_define(lxc_criu, lxc);
 
 struct criu_opts {
@@ -75,6 +77,9 @@ struct criu_opts {
 	 * different) on the target host. NULL if lxc.console = "none".
 	 */
 	char *console_name;
+
+	/* The detected version of criu */
+	char *criu_version;
 };
 
 static int load_tty_major_minor(char *directory, char *output, int len)
@@ -264,6 +269,10 @@ static void exec_criu(struct criu_opts *opts)
 		if (ret < 0 || ret >= sizeof(log))
 			goto err;
 
+		if (!opts->user->disable_skip_in_flight &&
+				strcmp(opts->criu_version, CRIU_IN_FLIGHT_SUPPORT) >= 0)
+			DECLARE_ARG("--skip-in-flight");
+
 		DECLARE_ARG("--freeze-cgroup");
 		DECLARE_ARG(log);
 
@@ -511,11 +520,11 @@ static bool criu_version_ok(char **version)
 
 /* Check and make sure the container has a configuration that we know CRIU can
  * dump. */
-static bool criu_ok(struct lxc_container *c)
+static bool criu_ok(struct lxc_container *c, char **criu_version)
 {
 	struct lxc_list *it;
 
-	if (!criu_version_ok(NULL))
+	if (!criu_version_ok(criu_version))
 		return false;
 
 	if (geteuid()) {
@@ -573,7 +582,7 @@ static bool restore_net_info(struct lxc_container *c)
 
 // do_restore never returns, the calling process is used as the
 // monitor process. do_restore calls exit() if it fails.
-void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts)
+void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version)
 {
 	pid_t pid;
 	char pidfile[L_tmpnam];
@@ -664,6 +673,7 @@ void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *o
 		os.pidfile = pidfile;
 		os.cgroup_path = cgroup_canonical_path(handler);
 		os.console_fd = c->lxc_conf->console.slave;
+		os.criu_version = criu_version;
 
 		if (os.console_fd >= 0) {
 			/* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu
@@ -848,8 +858,9 @@ static int save_tty_major_minor(char *directory, struct lxc_container *c, char *
 static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *opts)
 {
 	pid_t pid;
+	char *criu_version = NULL;
 
-	if (!criu_ok(c))
+	if (!criu_ok(c, &criu_version))
 		return false;
 
 	if (mkdir_p(opts->directory, 0700) < 0)
@@ -868,6 +879,7 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 		os.user = opts;
 		os.c = c;
 		os.console_name = c->lxc_conf->console.path;
+		os.criu_version = criu_version;
 
 		if (save_tty_major_minor(opts->directory, c, os.tty_id, sizeof(os.tty_id)) < 0)
 			exit(1);
@@ -927,8 +939,9 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
 	pid_t pid;
 	int status, nread;
 	int pipefd[2];
+	char *criu_version = NULL;
 
-	if (!criu_ok(c))
+	if (!criu_ok(c, &criu_version))
 		return false;
 
 	if (geteuid()) {
@@ -951,7 +964,7 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
 	if (pid == 0) {
 		close(pipefd[0]);
 		// this never returns
-		do_restore(c, pipefd[1], opts);
+		do_restore(c, pipefd[1], opts, criu_version);
 	}
 
 	close(pipefd[1]);
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index bde4912..e4915d2 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -896,6 +896,12 @@ struct migrate_opts {
 	 * "action script"
 	 */
 	char *action_script;
+
+	/* If CRIU >= 2.4 is detected the option to skip in-flight connections
+	 * will be enabled by default. The flag 'disable_skip_in_flight' will
+	 * unconditionally disable this feature. In-flight connections are
+	 * not fully established TCP connections: SYN, SYN-ACK */
+	bool disable_skip_in_flight;
 };
 
 /*!

From 3e4b0221c4a5f4e815fe2fed6ccef90d8df507f0 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber at redhat.com>
Date: Fri, 15 Jul 2016 10:54:30 +0200
Subject: [PATCH 074/334] c/r: make local function static

This is a minimal commit which makes the function 'do_restore()' static
as it is not used anywhere else in the code. This also removes a
trailing space my editor complained about.

Signed-off-by: Adrian Reber <areber at redhat.com>
---
 src/lxc/criu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 630e67b..804fd41 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -45,7 +45,7 @@
 #include "network.h"
 #include "utils.h"
 
-#define CRIU_VERSION 		"2.0"
+#define CRIU_VERSION		"2.0"
 
 #define CRIU_GITID_VERSION	"2.0"
 #define CRIU_GITID_PATCHLEVEL	0
@@ -582,7 +582,7 @@ static bool restore_net_info(struct lxc_container *c)
 
 // do_restore never returns, the calling process is used as the
 // monitor process. do_restore calls exit() if it fails.
-void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version)
+static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version)
 {
 	pid_t pid;
 	char pidfile[L_tmpnam];

From ceb3af7985ef3621607fb1416064722c93f37692 Mon Sep 17 00:00:00 2001
From: Vitaly Lavrov <vel21ripn at gmail.com>
Date: Thu, 30 Jun 2016 20:04:49 +0300
Subject: [PATCH 075/334] Set up MTU for vlan-type interfaces.

Signed-off-by: Vitaly Lavrov <vel21ripn at gmail.com>
---
 src/lxc/conf.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 009aac8..48a2978 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2742,6 +2742,15 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
 
 	DEBUG("instantiated vlan '%s', ifindex is '%d'", " vlan1000",
 	      netdev->ifindex);
+	if (netdev->mtu) {
+		err = lxc_netdev_set_mtu(peer, atoi(netdev->mtu));
+		if (err) {
+			ERROR("failed to set mtu '%s' for %s : %s",
+			      netdev->mtu, peer, strerror(-err));
+			lxc_netdev_delete_by_name(peer);
+			return -1;
+		}
+	}
 
 	return 0;
 }

From 9b867606336ef91bb1528683f1ef7730c627bf1e Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Mon, 18 Jul 2016 22:21:56 +0200
Subject: [PATCH 076/334] lxccontainer: detect if we should send SIGRTMIN+3

This is required by systemd to cleanly shutdown. Other init systems should not
have SIGRTMIN+3 in the blocked signals set.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/lxccontainer.c |  8 ++++++++
 src/lxc/utils.c        | 38 ++++++++++++++++++++++++++++++++++++++
 src/lxc/utils.h        |  3 +++
 3 files changed, 49 insertions(+)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 4a4dc42..8ea0005 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1604,8 +1604,16 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 	pid = do_lxcapi_init_pid(c);
 	if (pid <= 0)
 		return true;
+
+	/* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
+	if (task_blocking_signal(pid, (SIGRTMIN + 3)))
+		haltsignal = (SIGRTMIN + 3);
+
 	if (c->lxc_conf && c->lxc_conf->haltsignal)
 		haltsignal = c->lxc_conf->haltsignal;
+
+	INFO("Using signal number '%d' as halt signal.", haltsignal);
+
 	kill(pid, haltsignal);
 	retv = do_lxcapi_wait(c, "STOPPED", timeout);
 	return retv;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 5c35ae8..614add5 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1838,3 +1838,41 @@ int lxc_strmunmap(void *addr, size_t length)
 {
 	return munmap(addr, length + 1);
 }
+
+/* Check whether a signal is blocked by a process. */
+bool task_blocking_signal(pid_t pid, int signal)
+{
+	bool bret = false;
+	char *line = NULL;
+	long unsigned int sigblk = 0;
+	size_t n = 0;
+	int ret;
+	FILE *f;
+
+	/* The largest integer that can fit into long int is 2^64. This is a
+	 * 20-digit number. */
+	size_t len = /* /proc */ 5 + /* /pid-to-str */ 21 + /* /status */ 7 + /* \0 */ 1;
+	char status[len];
+
+	ret = snprintf(status, len, "/proc/%d/status", pid);
+	if (ret < 0 || ret >= len)
+		return bret;
+
+	f = fopen(status, "r");
+	if (!f)
+		return bret;
+
+	while (getline(&line, &n, f) != -1) {
+		if (!strncmp(line, "SigBlk:\t", 8))
+			if (sscanf(line + 8, "%lx", &sigblk) != 1)
+				goto out;
+	}
+
+	if (sigblk & signal)
+		bret = true;
+
+out:
+	free(line);
+	fclose(f);
+	return bret;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 22161cb..b541e07 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -296,4 +296,7 @@ int open_devnull(void);
 int set_stdfds(int fd);
 int null_stdfds(void);
 int lxc_count_file_lines(const char *fn);
+
+/* Check whether a signal is blocked by a process. */
+bool task_blocking_signal(pid_t pid, int signal);
 #endif /* __LXC_UTILS_H */

From a3f4eb755e69de91d7a8f8a01dee96cb68608026 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Tue, 19 Jul 2016 14:27:26 -0600
Subject: [PATCH 077/334] c/r: add support for ghost-limit in CRIU

This is an old option that we probably should have exposed long ago :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c         | 17 +++++++++++++++++
 src/lxc/lxccontainer.h |  6 ++++++
 2 files changed, 23 insertions(+)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 804fd41..d330d72 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -169,6 +169,10 @@ static void exec_criu(struct criu_opts *opts)
 		/* --force-irmap */
 		if (!opts->user->preserves_inodes)
 			static_args++;
+
+		/* --ghost-limit 1024 */
+		if (opts->user->ghost_limit)
+			static_args += 2;
 	} else if (strcmp(opts->action, "restore") == 0) {
 		/* --root $(lxc_mount_point) --restore-detached
 		 * --restore-sibling --pidfile $foo --cgroup-root $foo
@@ -300,6 +304,19 @@ static void exec_criu(struct criu_opts *opts)
 		if (!opts->user->preserves_inodes)
 			DECLARE_ARG("--force-irmap");
 
+		if (opts->user->ghost_limit) {
+			char ghost_limit[32];
+
+			ret = sprintf(ghost_limit, "%lu", opts->user->ghost_limit);
+			if (ret < 0 || ret >= sizeof(ghost_limit)) {
+				ERROR("failed to print ghost limit %lu", opts->user->ghost_limit);
+				goto err;
+			}
+
+			DECLARE_ARG("--ghost-limit");
+			DECLARE_ARG(ghost_limit);
+		}
+
 		/* only for final dump */
 		if (strcmp(opts->action, "dump") == 0 && !opts->user->stop)
 			DECLARE_ARG("--leave-running");
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index e4915d2..06bec58 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -902,6 +902,12 @@ struct migrate_opts {
 	 * unconditionally disable this feature. In-flight connections are
 	 * not fully established TCP connections: SYN, SYN-ACK */
 	bool disable_skip_in_flight;
+
+	/* This is the maximum file size for deleted files (which CRIU calls
+	 * "ghost" files) that will be handled. 0 indicates the CRIU default,
+	 * which at this time is 1MB.
+	 */
+	uint64_t ghost_limit;
 };
 
 /*!

From 66d0074a92cefb9a894590330dea6f6ac80b465b Mon Sep 17 00:00:00 2001
From: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
Date: Tue, 12 Jul 2016 17:51:06 +0200
Subject: [PATCH 078/334] templates: avoid noisy perl warnings caused by
 missing locales

Signed-off-by: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
---
 templates/lxc-debian.in | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index ccce6da..d1cd6f2 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -98,6 +98,24 @@ EOF
 
     # reconfigure some services
 
+    # but first reconfigure locales - so we get no noisy perl-warnings
+    if [ -z "$LANG" ]; then
+        cat >> $rootfs/etc/locale.gen << EOF
+en_US.UTF-8 UTF-8
+EOF
+        chroot $rootfs locale-gen en_US.UTF-8 UTF-8
+        chroot $rootfs update-locale LANG=en_US.UTF-8
+    else
+        encoding=$(echo $LANG | cut -d. -f2)
+        chroot $rootfs sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
+            -i /etc/locale.gen 2> /dev/null
+        cat >> $rootfs/etc/locale.gen << EOF
+$LANG $encoding
+EOF
+        chroot $rootfs locale-gen $LANG $encoding
+        chroot $rootfs update-locale LANG=$LANG
+    fi
+
     # remove pointless services in a container
     chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh disable
     chroot $rootfs /usr/sbin/update-rc.d -f umountfs disable
@@ -451,23 +469,6 @@ EOF
     # Re-enable service startup
     rm ${rootfs}/usr/sbin/policy-rc.d
     
-    # reconfigure locales
-    if [ -z "$LANG" ]; then
-        cat >> $rootfs/etc/locale.gen << EOF
-en_US.UTF-8 UTF-8
-EOF
-        chroot $rootfs locale-gen en_US.UTF-8 UTF-8
-        chroot $rootfs update-locale LANG=en_US.UTF-8
-    else
-        encoding=$(echo $LANG | cut -d. -f2)
-        chroot $rootfs sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
-            -i /etc/locale.gen 2> /dev/null
-        cat >> $rootfs/etc/locale.gen << EOF
-$LANG $encoding
-EOF
-        chroot $rootfs locale-gen $LANG $encoding
-        chroot $rootfs update-locale LANG=$LANG
-    fi
     # end
 }
 

From 01af742a7b77d85c8f52da16e281b72415f46f9d Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 22 Jul 2016 11:14:24 +0200
Subject: [PATCH 079/334] c/r: use PRIu64 format specifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes build failures on arm:

criu.c: In function ‘exec_criu’:
criu.c:310:4: error: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘uint64_t’ [-Werror=format=]
    ret = sprintf(ghost_limit, "%lu", opts->user->ghost_limit);
    ^
In file included from criu.c:42:0:
log.h:285:9: error: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 3 has type ‘uint64_t’ [-Werror=format=]
  struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT;  \
         ^
criu.c:312:5: note: in expansion of macro ‘ERROR’
     ERROR("failed to print ghost limit %lu", opts->user->ghost_limit);
     ^

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/criu.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index d330d72..69d25cf 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -22,6 +22,7 @@
  */
 #define _GNU_SOURCE
 #include <assert.h>
+#include <inttypes.h>
 #include <linux/limits.h>
 #include <sched.h>
 #include <stdio.h>
@@ -307,9 +308,9 @@ static void exec_criu(struct criu_opts *opts)
 		if (opts->user->ghost_limit) {
 			char ghost_limit[32];
 
-			ret = sprintf(ghost_limit, "%lu", opts->user->ghost_limit);
+			ret = sprintf(ghost_limit, "%"PRIu64, opts->user->ghost_limit);
 			if (ret < 0 || ret >= sizeof(ghost_limit)) {
-				ERROR("failed to print ghost limit %lu", opts->user->ghost_limit);
+				ERROR("failed to print ghost limit %"PRIu64, opts->user->ghost_limit);
 				goto err;
 			}
 

From 166f25a5d5574393fa492c049f8397f207c89b46 Mon Sep 17 00:00:00 2001
From: Jakub Jirutka <jakub at jirutka.cz>
Date: Sat, 23 Jul 2016 19:57:36 +0200
Subject: [PATCH 080/334] lxc-alpine: mount tmpfs under /run

When running under grsecurity kernel or userns, it can't be mounted from inside.

Signed-off-by: Jakub Jirutka <jakub at jirutka.cz>
---
 config/templates/alpine.common.conf.in | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/config/templates/alpine.common.conf.in b/config/templates/alpine.common.conf.in
index 034a33b..55ea3d2 100644
--- a/config/templates/alpine.common.conf.in
+++ b/config/templates/alpine.common.conf.in
@@ -18,3 +18,6 @@ lxc.cap.drop = sys_resource
 lxc.cap.drop = sys_tty_config
 lxc.cap.drop = syslog
 lxc.cap.drop = wake_alarm
+
+# Mount tmpfs under /run.
+lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0

From c05143a121a285a24143a20974e1be2d2a3cd298 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Mon, 25 Jul 2016 17:10:47 +0200
Subject: [PATCH 081/334] cgfsng: fix is_lxcfs() and is_cgroupfs()

Both functions advertise that they return true when strncmp() == 0 and false
when strncmp() != 0 but so far they returned the exact opposite.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/cgfsng.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/lxc/cgfsng.c b/src/lxc/cgfsng.c
index 0ea7b39..16a9457 100644
--- a/src/lxc/cgfsng.c
+++ b/src/lxc/cgfsng.c
@@ -438,7 +438,7 @@ static bool is_lxcfs(const char *line)
 	char *p = strstr(line, " - ");
 	if (!p)
 		return false;
-	return strncmp(p, " - fuse.lxcfs ", 14);
+	return strncmp(p, " - fuse.lxcfs ", 14) == 0;
 }
 
 /*
@@ -488,7 +488,7 @@ static bool is_cgroupfs(char *line)
 	char *p = strstr(line, " - ");
 	if (!p)
 		return false;
-	return strncmp(p, " - cgroup ", 10);
+	return strncmp(p, " - cgroup ", 10) == 0;
 }
 
 /* Add a controller to our list of hierarchies */
@@ -1350,7 +1350,7 @@ static bool cgfsng_mount(void *hdata, const char *root, int type)
 			free(controllerpath);
 			goto bad;
 		}
-		
+
 		r = do_secondstage_mounts_if_needed(type, h, controllerpath, path2,
 						    d->container_cgroup);
 		free(controllerpath);

From 11178e280df0aa182e0e27f5a8f7aa0696ba9e6a Mon Sep 17 00:00:00 2001
From: Sergio Schvezov <sergio.schvezov at ubuntu.com>
Date: Tue, 26 Jul 2016 09:41:47 +0200
Subject: [PATCH 082/334] Add a prefix to the lxc.pc

This allows installing to different locations and using
the lxc.pc to build using the generated includedir and
libdir.

Signed-off-by: Sergio Schvezov <sergio.schvezov at ubuntu.com>
---
 lxc.pc.in | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lxc.pc.in b/lxc.pc.in
index 380dd25..d019154 100644
--- a/lxc.pc.in
+++ b/lxc.pc.in
@@ -1,7 +1,8 @@
+prefix=@prefix@
 bindir=@BINDIR@
-libdir=@LIBDIR@
+libdir=${prefix}/@LIBDIR@
 localstatedir=@LOCALSTATEDIR@
-includedir=@INCLUDEDIR@
+includedir=${prefix}/@INCLUDEDIR@
 rootfsmountdir=@LXCROOTFSMOUNT@
 
 Name: lxc

From d27a62b1276c929f757ed563200f66444965d5ca Mon Sep 17 00:00:00 2001
From: oc <chenhaiq at yunify.com>
Date: Wed, 27 Jul 2016 22:43:58 +0800
Subject: [PATCH 083/334] attach: setns instead of unshare in lxc-attach

lxc-checkpoint will fail because process createdy by lxc-attach has
incorrect cgroup ns. It needs to use "setns" instead of "unshare"
to set cgroup ns.

Signed-off-by: Chen Haiquan <oc at yunify.com>
---
 src/lxc/attach.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index da5a557..0d9e3d0 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -217,10 +217,10 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 	 * the file for user namepsaces in /proc/$pid/ns will be called
 	 * 'user' once the kernel supports it
 	 */
-	static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net" };
+	static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup" };
 	static int flags[] = {
 		CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
-		CLONE_NEWNET
+		CLONE_NEWNET, CLONE_NEWCGROUP
 	};
 	static const int size = sizeof(ns) / sizeof(char *);
 	int fd[size];
@@ -720,7 +720,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	int ipc_sockets[2];
 	int procfd;
 	signed long personality;
-	bool unshare_cgns = false;
 
 	if (!options)
 		options = &attach_static_default_options;
@@ -931,8 +930,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		rexit(-1);
 	}
 
-	if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP && cgns_supported())
-		unshare_cgns = true;
+	if ((options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) && cgns_supported())
+		options->namespaces |= CLONE_NEWCGROUP;
 
 	procfd = open("/proc", O_DIRECTORY | O_RDONLY);
 	if (procfd < 0) {
@@ -961,14 +960,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		WARN("could not change directory to '%s'", new_cwd);
 	free(cwd);
 
-	if (unshare_cgns) {
-		if (unshare(CLONE_NEWCGROUP) != 0) {
-			SYSERROR("cgroupns unshare: permission denied");
-			rexit(-1);
-		}
-		INFO("Unshared cgroup namespace");
-	}
-
 	/* now create the real child process */
 	{
 		struct attach_clone_payload payload = {

From d2a1437f28ef4f70330b57bc529b67be9df23cc6 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Thu, 28 Jul 2016 11:52:18 +0200
Subject: [PATCH 084/334] conf: set pty_info to NULL after free

This fixes a double free corruption on container-requested
reboots when lxc_spawn() fails before receiving the ttys, as
lxc_fini() (part of __lxc_start()'s cleanup) calls
lxc_delete_tty().

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/conf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 48a2978..1e330ac 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3327,6 +3327,7 @@ void lxc_delete_tty(struct lxc_tty_info *tty_info)
 	}
 
 	free(tty_info->pty_info);
+	tty_info->pty_info = NULL;
 	tty_info->nbtty = 0;
 }
 

From 8e3ce6b09e2817883bfc7d5497843e212f3ad5ed Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 29 Jul 2016 00:53:53 +0200
Subject: [PATCH 085/334] criu: replace tmpnam() with mkstemp()

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/criu.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 69d25cf..bf9a87a 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -603,11 +603,13 @@ static bool restore_net_info(struct lxc_container *c)
 static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version)
 {
 	pid_t pid;
-	char pidfile[L_tmpnam];
 	struct lxc_handler *handler;
-	int status, pipes[2] = {-1, -1};
+	int fd, status;
+	int pipes[2] = {-1, -1};
+	char pidfile[] = "criu_restore_XXXXXX";
 
-	if (!tmpnam(pidfile))
+	fd = mkstemp(pidfile);
+	if (fd < 0)
 		goto out;
 
 	handler = lxc_init(c->name, c->lxc_conf, c->config_path);
@@ -756,11 +758,12 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 				goto out_fini_handler;
 			} else {
 				int ret;
-				FILE *f = fopen(pidfile, "r");
+				FILE *f = fdopen(fd, "r");
 				if (!f) {
 					SYSERROR("couldn't read restore's init pidfile %s\n", pidfile);
 					goto out_fini_handler;
 				}
+				fd = -1;
 
 				ret = fscanf(f, "%d", (int*) &handler->pid);
 				fclose(f);
@@ -818,6 +821,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		close(status_pipe);
 	}
 
+	if (fd > 0)
+		close(fd);
+
 	exit(1);
 }
 

From b5e153dee105e6890c4336db72b986d6d4004e78 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sun, 31 Jul 2016 12:04:28 +0200
Subject: [PATCH 086/334] bdev: add subdirectories to search path

This allows us to avoid using relative includes which is cleaner in the long
run when we create subdirectories for other components of liblxc.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/Makefile.am    | 8 +++++---
 src/lxc/cgfs.c         | 2 +-
 src/lxc/cgfsng.c       | 2 +-
 src/lxc/cgmanager.c    | 2 +-
 src/lxc/conf.c         | 6 +++---
 src/lxc/confile.c      | 2 +-
 src/lxc/criu.c         | 2 +-
 src/lxc/lxc_copy.c     | 2 +-
 src/lxc/lxc_create.c   | 2 +-
 src/lxc/lxc_snapshot.c | 2 +-
 src/lxc/lxccontainer.c | 6 +++---
 src/lxc/start.c        | 2 +-
 12 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index f361c3f..5078b5c 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -138,8 +138,7 @@ liblxc_so_SOURCES += ../include/getline.c ../include/getline.h
 endif
 endif
 
-AM_CFLAGS=-I$(top_srcdir)/src \
-	-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
+AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
 	-DLXCPATH=\"$(LXCPATH)\" \
 	-DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \
 	-DLXCINITDIR=\"$(LXCINITDIR)\" \
@@ -152,7 +151,10 @@ AM_CFLAGS=-I$(top_srcdir)/src \
 	-DLXC_USERNIC_CONF=\"$(LXC_USERNIC_CONF)\" \
 	-DDEFAULT_CGROUP_PATTERN=\"$(DEFAULT_CGROUP_PATTERN)\" \
 	-DRUNTIME_PATH=\"$(RUNTIME_PATH)\" \
-	-DSBINDIR=\"$(SBINDIR)\"
+	-DSBINDIR=\"$(SBINDIR)\" \
+	-I $(top_srcdir)/src \
+	-I $(top_srcdir)/src/lxc \
+	-I $(top_srcdir)/src/lxc/bdev
 
 if ENABLE_APPARMOR
 AM_CFLAGS += -DHAVE_APPARMOR
diff --git a/src/lxc/cgfs.c b/src/lxc/cgfs.c
index c493d58..6b2ac7e 100644
--- a/src/lxc/cgfs.c
+++ b/src/lxc/cgfs.c
@@ -39,12 +39,12 @@
 #include <netinet/in.h>
 #include <net/if.h>
 
+#include "bdev.h"
 #include "error.h"
 #include "commands.h"
 #include "list.h"
 #include "conf.h"
 #include "utils.h"
-#include "bdev/bdev.h"
 #include "log.h"
 #include "cgroup.h"
 #include "start.h"
diff --git a/src/lxc/cgfsng.c b/src/lxc/cgfsng.c
index 16a9457..27c2721 100644
--- a/src/lxc/cgfsng.c
+++ b/src/lxc/cgfsng.c
@@ -43,11 +43,11 @@
 #include <dirent.h>
 #include <grp.h>
 
+#include "bdev.h"
 #include "log.h"
 #include "cgroup.h"
 #include "utils.h"
 #include "commands.h"
-#include "bdev/bdev.h"
 
 lxc_log_define(lxc_cgfsng, lxc);
 
diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
index c387b00..4da891d 100644
--- a/src/lxc/cgmanager.c
+++ b/src/lxc/cgmanager.c
@@ -41,12 +41,12 @@
 #include <net/if.h>
 #include <poll.h>
 
+#include "bdev.h"
 #include "error.h"
 #include "commands.h"
 #include "list.h"
 #include "conf.h"
 #include "utils.h"
-#include "bdev/bdev.h"
 #include "log.h"
 #include "cgroup.h"
 #include "start.h"
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 1e330ac..9fea993 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -66,6 +66,7 @@
 #include <net/if.h>
 #include <libgen.h>
 
+#include "bdev.h"
 #include "network.h"
 #include "error.h"
 #include "af_unix.h"
@@ -74,9 +75,8 @@
 #include "conf.h"
 #include "log.h"
 #include "caps.h"       /* for lxc_caps_last_cap() */
-#include "bdev/bdev.h"
-#include "bdev/lxcaufs.h"
-#include "bdev/lxcoverlay.h"
+#include "lxcaufs.h"
+#include "lxcoverlay.h"
 #include "cgroup.h"
 #include "lxclock.h"
 #include "namespace.h"
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 14a76b2..fbd9255 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -39,10 +39,10 @@
 #include <time.h>
 #include <dirent.h>
 
+#include "bdev.h"
 #include "parse.h"
 #include "config.h"
 #include "confile.h"
-#include "bdev/bdev.h"
 #include "utils.h"
 #include "log.h"
 #include "conf.h"
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index bf9a87a..65998ed 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -35,7 +35,7 @@
 
 #include "config.h"
 
-#include "bdev/bdev.h"
+#include "bdev.h"
 #include "cgroup.h"
 #include "conf.h"
 #include "commands.h"
diff --git a/src/lxc/lxc_copy.c b/src/lxc/lxc_copy.c
index e424e65..db63a6c 100644
--- a/src/lxc/lxc_copy.c
+++ b/src/lxc/lxc_copy.c
@@ -37,6 +37,7 @@
 #include <lxc/lxccontainer.h>
 
 #include "attach.h"
+#include "bdev.h"
 #include "log.h"
 #include "confile.h"
 #include "arguments.h"
@@ -44,7 +45,6 @@
 #include "conf.h"
 #include "state.h"
 #include "utils.h"
-#include "bdev/bdev.h"
 
 #ifndef HAVE_GETSUBOPT
 #include <../include/getsubopt.h>
diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
index 5fd5a29..4b0e9d7 100644
--- a/src/lxc/lxc_create.c
+++ b/src/lxc/lxc_create.c
@@ -27,10 +27,10 @@
 #include <sys/types.h>
 
 #include "arguments.h"
+#include "bdev.h"
 #include "log.h"
 #include "lxc.h"
 #include "utils.h"
-#include "bdev/bdev.h"
 
 lxc_log_define(lxc_create_ui, lxc);
 
diff --git a/src/lxc/lxc_snapshot.c b/src/lxc/lxc_snapshot.c
index 147101e..8f44891 100644
--- a/src/lxc/lxc_snapshot.c
+++ b/src/lxc/lxc_snapshot.c
@@ -27,9 +27,9 @@
 
 #include <lxc/lxccontainer.h>
 
+#include "bdev.h"
 #include "lxc.h"
 #include "log.h"
-#include "bdev/bdev.h"
 #include "arguments.h"
 #include "utils.h"
 
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 8ea0005..24ded6f 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -39,9 +39,9 @@
 #include <sys/wait.h>
 
 #include "attach.h"
-#include "bdev/bdev.h"
-#include "bdev/lxcoverlay.h"
-#include "bdev/lxcbtrfs.h"
+#include "bdev.h"
+#include "lxcoverlay.h"
+#include "lxcbtrfs.h"
 #include "cgroup.h"
 #include "conf.h"
 #include "config.h"
diff --git a/src/lxc/start.c b/src/lxc/start.c
index b3f75b8..06e7522 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -55,6 +55,7 @@
 #endif
 
 #include "af_unix.h"
+#include "bdev.h"
 #include "caps.h"
 #include "cgroup.h"
 #include "commands.h"
@@ -71,7 +72,6 @@
 #include "start.h"
 #include "sync.h"
 #include "utils.h"
-#include "bdev/bdev.h"
 #include "lsm/lsm.h"
 
 lxc_log_define(lxc_start, lxc);

From b815882690ed3a52d69ca5144b087ffa9c53acb9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sun, 31 Jul 2016 12:21:58 +0200
Subject: [PATCH 087/334] cgroups: move cgroup files to common subfolder

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/Makefile.am               | 13 +++++++------
 src/lxc/{ => cgroups}/cgfs.c      |  0
 src/lxc/{ => cgroups}/cgfsng.c    |  0
 src/lxc/{ => cgroups}/cgmanager.c |  0
 src/lxc/{ => cgroups}/cgroup.c    |  0
 src/lxc/{ => cgroups}/cgroup.h    |  0
 6 files changed, 7 insertions(+), 6 deletions(-)
 rename src/lxc/{ => cgroups}/cgfs.c (100%)
 rename src/lxc/{ => cgroups}/cgfsng.c (100%)
 rename src/lxc/{ => cgroups}/cgmanager.c (100%)
 rename src/lxc/{ => cgroups}/cgroup.c (100%)
 rename src/lxc/{ => cgroups}/cgroup.h (100%)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 5078b5c..9a87c15 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -17,8 +17,8 @@ noinst_HEADERS = \
 	bdev/lxcrbd.h \
 	bdev/lxcrsync.h \
 	bdev/lxczfs.h \
+	cgroups/cgroup.h \
 	caps.h \
-	cgroup.h \
 	conf.h \
 	console.h \
 	error.h \
@@ -80,6 +80,9 @@ liblxc_so_SOURCES = \
 	bdev/lxcrbd.c bdev/lxcrbd.h \
 	bdev/lxcrsync.c bdev/lxcrsync.h \
 	bdev/lxczfs.c bdev/lxczfs.h \
+	cgroups/cgfs.c \
+	cgroups/cgfsng.c \
+	cgroups/cgroup.c cgroups/cgroup.h \
 	commands.c commands.h \
 	start.c start.h \
 	execute.c \
@@ -88,9 +91,6 @@ liblxc_so_SOURCES = \
 	freezer.c \
 	error.h error.c \
 	parse.c parse.h \
-	cgfs.c \
-	cgfsng.c \
-	cgroup.c cgroup.h \
 	lxc.h \
 	initutils.c initutils.h \
 	utils.c utils.h \
@@ -122,7 +122,7 @@ liblxc_so_SOURCES = \
 	$(LSM_SOURCES)
 
 if ENABLE_CGMANAGER
-liblxc_so_SOURCES += cgmanager.c
+liblxc_so_SOURCES += cgroups/cgmanager.c
 endif
 
 if IS_BIONIC
@@ -154,7 +154,8 @@ AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
 	-DSBINDIR=\"$(SBINDIR)\" \
 	-I $(top_srcdir)/src \
 	-I $(top_srcdir)/src/lxc \
-	-I $(top_srcdir)/src/lxc/bdev
+	-I $(top_srcdir)/src/lxc/bdev \
+	-I $(top_srcdir)/src/lxc/cgroups
 
 if ENABLE_APPARMOR
 AM_CFLAGS += -DHAVE_APPARMOR
diff --git a/src/lxc/cgfs.c b/src/lxc/cgroups/cgfs.c
similarity index 100%
rename from src/lxc/cgfs.c
rename to src/lxc/cgroups/cgfs.c
diff --git a/src/lxc/cgfsng.c b/src/lxc/cgroups/cgfsng.c
similarity index 100%
rename from src/lxc/cgfsng.c
rename to src/lxc/cgroups/cgfsng.c
diff --git a/src/lxc/cgmanager.c b/src/lxc/cgroups/cgmanager.c
similarity index 100%
rename from src/lxc/cgmanager.c
rename to src/lxc/cgroups/cgmanager.c
diff --git a/src/lxc/cgroup.c b/src/lxc/cgroups/cgroup.c
similarity index 100%
rename from src/lxc/cgroup.c
rename to src/lxc/cgroups/cgroup.c
diff --git a/src/lxc/cgroup.h b/src/lxc/cgroups/cgroup.h
similarity index 100%
rename from src/lxc/cgroup.h
rename to src/lxc/cgroups/cgroup.h

From 5a21336025eec5b4228994d0efece129257411bd Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sun, 31 Jul 2016 12:40:49 +0200
Subject: [PATCH 088/334] tools, tests: reorganize repo

- tools: move lxc commands to common subfolder
- tests: adapt include search path

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 configure.ac                               |  4 +-
 src/lxc/Makefile.am                        | 60 +++++++++++++++---------------
 src/lxc/{ => tools}/lxc-checkconfig.in     |  0
 src/lxc/{ => tools}/lxc-start-ephemeral.in |  0
 src/lxc/{ => tools}/lxc-top.lua            |  0
 src/lxc/{ => tools}/lxc_attach.c           |  0
 src/lxc/{ => tools}/lxc_autostart.c        |  0
 src/lxc/{ => tools}/lxc_cgroup.c           |  0
 src/lxc/{ => tools}/lxc_checkpoint.c       |  0
 src/lxc/{ => tools}/lxc_clone.c            |  0
 src/lxc/{ => tools}/lxc_config.c           |  0
 src/lxc/{ => tools}/lxc_console.c          |  0
 src/lxc/{ => tools}/lxc_copy.c             |  0
 src/lxc/{ => tools}/lxc_create.c           |  0
 src/lxc/{ => tools}/lxc_destroy.c          |  0
 src/lxc/{ => tools}/lxc_device.c           |  0
 src/lxc/{ => tools}/lxc_execute.c          |  0
 src/lxc/{ => tools}/lxc_freeze.c           |  0
 src/lxc/{ => tools}/lxc_info.c             |  0
 src/lxc/{ => tools}/lxc_init.c             |  0
 src/lxc/{ => tools}/lxc_ls.c               |  0
 src/lxc/{ => tools}/lxc_monitor.c          |  0
 src/lxc/{ => tools}/lxc_snapshot.c         |  0
 src/lxc/{ => tools}/lxc_start.c            |  0
 src/lxc/{ => tools}/lxc_stop.c             |  0
 src/lxc/{ => tools}/lxc_top.c              |  0
 src/lxc/{ => tools}/lxc_unfreeze.c         |  0
 src/lxc/{ => tools}/lxc_unshare.c          |  0
 src/lxc/{ => tools}/lxc_usernsexec.c       |  0
 src/lxc/{ => tools}/lxc_wait.c             |  0
 src/tests/Makefile.am                      | 10 +++--
 src/tests/cgpath.c                         |  7 ++--
 32 files changed, 43 insertions(+), 38 deletions(-)
 rename src/lxc/{ => tools}/lxc-checkconfig.in (100%)
 rename src/lxc/{ => tools}/lxc-start-ephemeral.in (100%)
 rename src/lxc/{ => tools}/lxc-top.lua (100%)
 rename src/lxc/{ => tools}/lxc_attach.c (100%)
 rename src/lxc/{ => tools}/lxc_autostart.c (100%)
 rename src/lxc/{ => tools}/lxc_cgroup.c (100%)
 rename src/lxc/{ => tools}/lxc_checkpoint.c (100%)
 rename src/lxc/{ => tools}/lxc_clone.c (100%)
 rename src/lxc/{ => tools}/lxc_config.c (100%)
 rename src/lxc/{ => tools}/lxc_console.c (100%)
 rename src/lxc/{ => tools}/lxc_copy.c (100%)
 rename src/lxc/{ => tools}/lxc_create.c (100%)
 rename src/lxc/{ => tools}/lxc_destroy.c (100%)
 rename src/lxc/{ => tools}/lxc_device.c (100%)
 rename src/lxc/{ => tools}/lxc_execute.c (100%)
 rename src/lxc/{ => tools}/lxc_freeze.c (100%)
 rename src/lxc/{ => tools}/lxc_info.c (100%)
 rename src/lxc/{ => tools}/lxc_init.c (100%)
 rename src/lxc/{ => tools}/lxc_ls.c (100%)
 rename src/lxc/{ => tools}/lxc_monitor.c (100%)
 rename src/lxc/{ => tools}/lxc_snapshot.c (100%)
 rename src/lxc/{ => tools}/lxc_start.c (100%)
 rename src/lxc/{ => tools}/lxc_stop.c (100%)
 rename src/lxc/{ => tools}/lxc_top.c (100%)
 rename src/lxc/{ => tools}/lxc_unfreeze.c (100%)
 rename src/lxc/{ => tools}/lxc_unshare.c (100%)
 rename src/lxc/{ => tools}/lxc_usernsexec.c (100%)
 rename src/lxc/{ => tools}/lxc_wait.c (100%)

diff --git a/configure.ac b/configure.ac
index cb7f641..54c987b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -842,9 +842,9 @@ AC_CONFIG_FILES([
 
 	src/Makefile
 	src/lxc/Makefile
-	src/lxc/lxc-checkconfig
-	src/lxc/lxc-start-ephemeral
 	src/lxc/lxc.functions
+	src/lxc/tools/lxc-checkconfig
+	src/lxc/tools/lxc-start-ephemeral
 	src/lxc/version.h
 	src/python-lxc/Makefile
 	src/python-lxc/setup.py
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 9a87c15..73a0971 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -192,14 +192,14 @@ liblxc_so_LDADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
 liblxc_so_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS)
 endif
 
-bin_SCRIPTS = lxc-checkconfig
+bin_SCRIPTS = tools/lxc-checkconfig
 
 EXTRA_DIST = \
-	lxc-top.lua
+	tools/lxc-top.lua
 
 if ENABLE_DEPRECATED
 if ENABLE_PYTHON
-bin_SCRIPTS += lxc-start-ephemeral
+bin_SCRIPTS += tools/lxc-start-ephemeral
 endif
 endif
 
@@ -243,35 +243,35 @@ AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
 endif
 LDADD=liblxc.so @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
 
-lxc_attach_SOURCES = lxc_attach.c
-lxc_autostart_SOURCES = lxc_autostart.c
-lxc_cgroup_SOURCES = lxc_cgroup.c
-lxc_config_SOURCES = lxc_config.c
-lxc_console_SOURCES = lxc_console.c
-lxc_destroy_SOURCES = lxc_destroy.c
-lxc_device_SOURCES = lxc_device.c
-lxc_execute_SOURCES = lxc_execute.c
-lxc_freeze_SOURCES = lxc_freeze.c
-lxc_info_SOURCES = lxc_info.c
-init_lxc_SOURCES = lxc_init.c
-lxc_monitor_SOURCES = lxc_monitor.c
-lxc_monitord_SOURCES = lxc_monitord.c
-lxc_ls_SOURCES = lxc_ls.c
-lxc_copy_SOURCES = lxc_copy.c
-lxc_start_SOURCES = lxc_start.c
-lxc_stop_SOURCES = lxc_stop.c
-lxc_top_SOURCES = lxc_top.c
-lxc_unfreeze_SOURCES = lxc_unfreeze.c
-lxc_unshare_SOURCES = lxc_unshare.c
-lxc_wait_SOURCES = lxc_wait.c
-lxc_create_SOURCES = lxc_create.c
-lxc_snapshot_SOURCES = lxc_snapshot.c
-lxc_usernsexec_SOURCES = lxc_usernsexec.c
+lxc_attach_SOURCES = tools/lxc_attach.c
+lxc_autostart_SOURCES = tools/lxc_autostart.c
+lxc_cgroup_SOURCES = tools/lxc_cgroup.c
+lxc_config_SOURCES = tools/lxc_config.c
+lxc_console_SOURCES = tools/lxc_console.c
+lxc_destroy_SOURCES = tools/lxc_destroy.c
+lxc_device_SOURCES = tools/lxc_device.c
+lxc_execute_SOURCES = tools/lxc_execute.c
+lxc_freeze_SOURCES = tools/lxc_freeze.c
+lxc_info_SOURCES = tools/lxc_info.c
+init_lxc_SOURCES = tools/lxc_init.c
+lxc_monitor_SOURCES = tools/lxc_monitor.c
+lxc_ls_SOURCES = tools/lxc_ls.c
+lxc_copy_SOURCES = tools/lxc_copy.c
+lxc_start_SOURCES = tools/lxc_start.c
+lxc_stop_SOURCES = tools/lxc_stop.c
+lxc_top_SOURCES = tools/lxc_top.c
+lxc_unfreeze_SOURCES = tools/lxc_unfreeze.c
+lxc_unshare_SOURCES = tools/lxc_unshare.c
+lxc_wait_SOURCES = tools/lxc_wait.c
+lxc_create_SOURCES = tools/lxc_create.c
+lxc_snapshot_SOURCES = tools/lxc_snapshot.c
+lxc_usernsexec_SOURCES = tools/lxc_usernsexec.c
+lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c
 lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h
-lxc_checkpoint_SOURCES = lxc_checkpoint.c
+lxc_monitord_SOURCES = lxc_monitord.c
 
 if ENABLE_DEPRECATED
-lxc_clone_SOURCES = lxc_clone.c
+lxc_clone_SOURCES = tools/lxc_clone.c
 endif
 
 if !HAVE_GETSUBOPT
@@ -281,7 +281,7 @@ endif
 if HAVE_STATIC_LIBCAP
 sbin_PROGRAMS += init.lxc.static
 
-init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c
+init_lxc_static_SOURCES = tools/lxc_init.c error.c log.c initutils.c caps.c
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
diff --git a/src/lxc/lxc-checkconfig.in b/src/lxc/tools/lxc-checkconfig.in
similarity index 100%
rename from src/lxc/lxc-checkconfig.in
rename to src/lxc/tools/lxc-checkconfig.in
diff --git a/src/lxc/lxc-start-ephemeral.in b/src/lxc/tools/lxc-start-ephemeral.in
similarity index 100%
rename from src/lxc/lxc-start-ephemeral.in
rename to src/lxc/tools/lxc-start-ephemeral.in
diff --git a/src/lxc/lxc-top.lua b/src/lxc/tools/lxc-top.lua
similarity index 100%
rename from src/lxc/lxc-top.lua
rename to src/lxc/tools/lxc-top.lua
diff --git a/src/lxc/lxc_attach.c b/src/lxc/tools/lxc_attach.c
similarity index 100%
rename from src/lxc/lxc_attach.c
rename to src/lxc/tools/lxc_attach.c
diff --git a/src/lxc/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
similarity index 100%
rename from src/lxc/lxc_autostart.c
rename to src/lxc/tools/lxc_autostart.c
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
similarity index 100%
rename from src/lxc/lxc_cgroup.c
rename to src/lxc/tools/lxc_cgroup.c
diff --git a/src/lxc/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
similarity index 100%
rename from src/lxc/lxc_checkpoint.c
rename to src/lxc/tools/lxc_checkpoint.c
diff --git a/src/lxc/lxc_clone.c b/src/lxc/tools/lxc_clone.c
similarity index 100%
rename from src/lxc/lxc_clone.c
rename to src/lxc/tools/lxc_clone.c
diff --git a/src/lxc/lxc_config.c b/src/lxc/tools/lxc_config.c
similarity index 100%
rename from src/lxc/lxc_config.c
rename to src/lxc/tools/lxc_config.c
diff --git a/src/lxc/lxc_console.c b/src/lxc/tools/lxc_console.c
similarity index 100%
rename from src/lxc/lxc_console.c
rename to src/lxc/tools/lxc_console.c
diff --git a/src/lxc/lxc_copy.c b/src/lxc/tools/lxc_copy.c
similarity index 100%
rename from src/lxc/lxc_copy.c
rename to src/lxc/tools/lxc_copy.c
diff --git a/src/lxc/lxc_create.c b/src/lxc/tools/lxc_create.c
similarity index 100%
rename from src/lxc/lxc_create.c
rename to src/lxc/tools/lxc_create.c
diff --git a/src/lxc/lxc_destroy.c b/src/lxc/tools/lxc_destroy.c
similarity index 100%
rename from src/lxc/lxc_destroy.c
rename to src/lxc/tools/lxc_destroy.c
diff --git a/src/lxc/lxc_device.c b/src/lxc/tools/lxc_device.c
similarity index 100%
rename from src/lxc/lxc_device.c
rename to src/lxc/tools/lxc_device.c
diff --git a/src/lxc/lxc_execute.c b/src/lxc/tools/lxc_execute.c
similarity index 100%
rename from src/lxc/lxc_execute.c
rename to src/lxc/tools/lxc_execute.c
diff --git a/src/lxc/lxc_freeze.c b/src/lxc/tools/lxc_freeze.c
similarity index 100%
rename from src/lxc/lxc_freeze.c
rename to src/lxc/tools/lxc_freeze.c
diff --git a/src/lxc/lxc_info.c b/src/lxc/tools/lxc_info.c
similarity index 100%
rename from src/lxc/lxc_info.c
rename to src/lxc/tools/lxc_info.c
diff --git a/src/lxc/lxc_init.c b/src/lxc/tools/lxc_init.c
similarity index 100%
rename from src/lxc/lxc_init.c
rename to src/lxc/tools/lxc_init.c
diff --git a/src/lxc/lxc_ls.c b/src/lxc/tools/lxc_ls.c
similarity index 100%
rename from src/lxc/lxc_ls.c
rename to src/lxc/tools/lxc_ls.c
diff --git a/src/lxc/lxc_monitor.c b/src/lxc/tools/lxc_monitor.c
similarity index 100%
rename from src/lxc/lxc_monitor.c
rename to src/lxc/tools/lxc_monitor.c
diff --git a/src/lxc/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
similarity index 100%
rename from src/lxc/lxc_snapshot.c
rename to src/lxc/tools/lxc_snapshot.c
diff --git a/src/lxc/lxc_start.c b/src/lxc/tools/lxc_start.c
similarity index 100%
rename from src/lxc/lxc_start.c
rename to src/lxc/tools/lxc_start.c
diff --git a/src/lxc/lxc_stop.c b/src/lxc/tools/lxc_stop.c
similarity index 100%
rename from src/lxc/lxc_stop.c
rename to src/lxc/tools/lxc_stop.c
diff --git a/src/lxc/lxc_top.c b/src/lxc/tools/lxc_top.c
similarity index 100%
rename from src/lxc/lxc_top.c
rename to src/lxc/tools/lxc_top.c
diff --git a/src/lxc/lxc_unfreeze.c b/src/lxc/tools/lxc_unfreeze.c
similarity index 100%
rename from src/lxc/lxc_unfreeze.c
rename to src/lxc/tools/lxc_unfreeze.c
diff --git a/src/lxc/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
similarity index 100%
rename from src/lxc/lxc_unshare.c
rename to src/lxc/tools/lxc_unshare.c
diff --git a/src/lxc/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c
similarity index 100%
rename from src/lxc/lxc_usernsexec.c
rename to src/lxc/tools/lxc_usernsexec.c
diff --git a/src/lxc/lxc_wait.c b/src/lxc/tools/lxc_wait.c
similarity index 100%
rename from src/lxc/lxc_wait.c
rename to src/lxc/tools/lxc_wait.c
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 68141f9..26beeda 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -24,13 +24,17 @@ lxc_test_attach_SOURCES = attach.c
 lxc_test_device_add_remove_SOURCES = device_add_remove.c
 lxc_test_apparmor_SOURCES = aa.c
 
-AM_CFLAGS=-I$(top_srcdir)/src \
-	-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
+AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
 	-DLXCPATH=\"$(LXCPATH)\" \
 	-DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \
 	-DLXCINITDIR=\"$(LXCINITDIR)\" \
 	-DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \
-	-DRUNTIME_PATH=\"$(RUNTIME_PATH)\"
+	-DRUNTIME_PATH=\"$(RUNTIME_PATH)\" \
+	-I $(top_srcdir)/src \
+	-I $(top_srcdir)/src/lxc \
+	-I $(top_srcdir)/src/lxc/bdev \
+	-I $(top_srcdir)/src/lxc/cgroups \
+	-I $(top_srcdir)/src/lxc/tools
 
 if ENABLE_APPARMOR
 AM_CFLAGS += -DHAVE_APPARMOR
diff --git a/src/tests/cgpath.c b/src/tests/cgpath.c
index c8a09e8..fb755cd 100644
--- a/src/tests/cgpath.c
+++ b/src/tests/cgpath.c
@@ -28,9 +28,10 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
-#include "lxc/cgroup.h"
-#include "lxc/lxc.h"
-#include "lxc/commands.h"
+
+#include "cgroup.h"
+#include "lxc.h"
+#include "commands.h"
 
 #define MYNAME "lxctest1"
 

From a7104b0b68e29ea29386359bb08577d026072fc1 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Thu, 4 Aug 2016 11:23:54 +0200
Subject: [PATCH 089/334] add -f option to lxc-attach

Otherwise a container with a non-standard configuration file
can be started but not attached to.
Fixes the following case:
 # lxc-start -n ct -f /different/path/my.config
 # lxc-attach -n ct
 Error: container ct is not defined

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_attach.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 58f658b..7116885 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -65,6 +65,7 @@ static const struct option my_longopts[] = {
 	{"keep-var", required_argument, 0, 502},
 	{"set-var", required_argument, 0, 'v'},
 	{"pty-log", required_argument, 0, 'L'},
+	{"rcfile", required_argument, 0, 'f'},
 	LXC_COMMON_OPTIONS
 };
 
@@ -153,6 +154,7 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
 	case 'L':
 		args->console_log = arg;
 		break;
+	case 'f': args->rcfile = arg; break;
 	}
 
 	return 0;
@@ -202,7 +204,10 @@ Options :\n\
                     multiple times.\n\
       --keep-var    Keep an additional environment variable. Only\n\
                     applicable if --clear-env is specified. May be used\n\
-                    multiple times.\n",
+                    multiple times.\n\
+  -f, --rcfile=FILE\n\
+                    Load configuration file FILE\n\
+",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = NULL,
@@ -373,6 +378,15 @@ int main(int argc, char *argv[])
 	if (!c)
 		exit(EXIT_FAILURE);
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			ERROR("Failed to load rcfile");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
 		lxc_container_put(c);

From 5caa1713c6d4b41d98f3189f42aeb7f3e9080c06 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Thu, 4 Aug 2016 11:28:37 +0200
Subject: [PATCH 090/334] whitespace cleanup

The rest of this block uses spaces instead of tabs already.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_attach.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 7116885..281f97a 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -198,7 +198,7 @@ Options :\n\
                     is the current default behaviour, but is likely to\n\
                     change in the future.\n\
   -L, --pty-log=FILE\n\
-		    Log pty output to FILE\n\
+                    Log pty output to FILE\n\
   -v, --set-var     Set an additional variable that is seen by the\n\
                     attached program in the container. May be specified\n\
                     multiple times.\n\

From ff48886e1d46d86ee8b16ef38672bd4368474706 Mon Sep 17 00:00:00 2001
From: Carlo Landmeter <clandmeter at gmail.com>
Date: Sun, 7 Aug 2016 09:21:05 +0000
Subject: [PATCH 091/334] templates: add support for new arch on Alpine Linux

Signed-off-by: Carlo Landmeter <clandmeter at gmail.com>
---
 templates/lxc-alpine.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in
index c78795c..988f109 100644
--- a/templates/lxc-alpine.in
+++ b/templates/lxc-alpine.in
@@ -123,6 +123,8 @@ parse_arch() {
 	case "$1" in
 		x86 | i[3-6]86) echo 'x86';;
 		x86_64 | amd64) echo 'x86_64';;
+		aarch64 | arm64) echo 'aarch64';;
+		armv7) echo 'armv7';;
 		arm*) echo 'armhf';;
 		*) return 1;;
 	esac

From e75ec2bbb93154055cbd0f80fdd8f5976196da32 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Tue, 9 Aug 2016 21:05:19 +0200
Subject: [PATCH 092/334] tree-wide: replace readdir_r() with readdir()

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/bdev/lxcloop.c   |  4 ++--
 src/lxc/cgroups/cgfs.c   | 23 ++++-------------------
 src/lxc/cgroups/cgfsng.c |  8 ++++----
 src/lxc/conf.c           |  4 ++--
 src/lxc/confile.c        |  4 ++--
 src/lxc/lxccontainer.c   | 20 ++++++++++----------
 src/lxc/start.c          |  4 ++--
 src/lxc/utils.c          |  4 ++--
 8 files changed, 28 insertions(+), 43 deletions(-)

diff --git a/src/lxc/bdev/lxcloop.c b/src/lxc/bdev/lxcloop.c
index c17483f..b322002 100644
--- a/src/lxc/bdev/lxcloop.c
+++ b/src/lxc/bdev/lxcloop.c
@@ -269,7 +269,7 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype)
 
 static int find_free_loopdev_no_control(int *retfd, char *namep)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	struct loop_info64 lo;
 	DIR *dir;
 	int fd = -1;
@@ -279,7 +279,7 @@ static int find_free_loopdev_no_control(int *retfd, char *namep)
 		SYSERROR("Error opening /dev");
 		return -1;
 	}
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 
 		if (!direntp)
 			break;
diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 6b2ac7e..2d0de0c 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -157,7 +157,7 @@ static struct cgroup_ops cgfs_ops;
 
 static int cgroup_rmdir(char *dirname)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	int saved_errno = 0;
 	DIR *dir;
 	int ret, failed=0;
@@ -169,7 +169,7 @@ static int cgroup_rmdir(char *dirname)
 		return -1;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		struct stat mystat;
 		int rc;
 
@@ -2067,26 +2067,14 @@ static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d,
 static int cgroup_recursive_task_count(const char *cgroup_path)
 {
 	DIR *d;
-	struct dirent *dent_buf;
 	struct dirent *dent;
-	ssize_t name_max;
 	int n = 0, r;
 
-	/* see man readdir_r(3) */
-	name_max = pathconf(cgroup_path, _PC_NAME_MAX);
-	if (name_max <= 0)
-		name_max = 255;
-	dent_buf = malloc(offsetof(struct dirent, d_name) + name_max + 1);
-	if (!dent_buf)
-		return -1;
-
 	d = opendir(cgroup_path);
-	if (!d) {
-		free(dent_buf);
+	if (!d)
 		return 0;
-	}
 
-	while (readdir_r(d, dent_buf, &dent) == 0 && dent) {
+	while ((dent = readdir(d))) {
 		const char *parts[3] = {
 			cgroup_path,
 			dent->d_name,
@@ -2100,13 +2088,11 @@ static int cgroup_recursive_task_count(const char *cgroup_path)
 		sub_path = lxc_string_join("/", parts, false);
 		if (!sub_path) {
 			closedir(d);
-			free(dent_buf);
 			return -1;
 		}
 		r = stat(sub_path, &st);
 		if (r < 0) {
 			closedir(d);
-			free(dent_buf);
 			free(sub_path);
 			return -1;
 		}
@@ -2122,7 +2108,6 @@ static int cgroup_recursive_task_count(const char *cgroup_path)
 		free(sub_path);
 	}
 	closedir(d);
-	free(dent_buf);
 
 	return n;
 }
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 27c2721..95f29ca 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -907,7 +907,7 @@ static char *must_make_path(const char *first, ...)
 
 static int cgroup_rmdir(char *dirname)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	DIR *dir;
 	int r = 0;
 
@@ -915,7 +915,7 @@ static int cgroup_rmdir(char *dirname)
 	if (!dir)
 		return -1;
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		struct stat mystat;
 		char *pathname;
 
@@ -1367,7 +1367,7 @@ static bool cgfsng_mount(void *hdata, const char *root, int type)
 
 static int recursive_count_nrtasks(char *dirname)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	DIR *dir;
 	int count = 0, ret;
 	char *path;
@@ -1376,7 +1376,7 @@ static int recursive_count_nrtasks(char *dirname)
 	if (!dir)
 		return 0;
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		struct stat mystat;
 
 		if (!direntp)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 9fea993..4ece410 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -510,7 +510,7 @@ static int setup_lodev(const char *rootfs, int fd, struct loop_info64 *loinfo)
 static int mount_rootfs_file(const char *rootfs, const char *target,
 				             const char *options)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	struct loop_info64 loinfo;
 	int ret = -1, fd = -1, rc;
 	DIR *dir;
@@ -522,7 +522,7 @@ static int mount_rootfs_file(const char *rootfs, const char *target,
 		return -1;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 
 		if (!direntp)
 			break;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index fbd9255..2cbf375 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1785,7 +1785,7 @@ int append_unexp_config_line(const char *line, struct lxc_conf *conf)
 
 static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	DIR *dir;
 	char path[MAXPATHLEN];
 	int ret = -1, len;
@@ -1796,7 +1796,7 @@ static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
 		return -1;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		const char *fnam;
 		if (!direntp)
 			break;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 24ded6f..ae0286f 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -623,7 +623,7 @@ WRAP_API_1(bool, wait_on_daemonized_start, int)
 
 static bool am_single_threaded(void)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	DIR *dir;
 	int count=0;
 
@@ -633,7 +633,7 @@ static bool am_single_threaded(void)
 		return false;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 
@@ -2284,7 +2284,7 @@ static bool has_fs_snapshots(struct lxc_container *c)
 static bool has_snapshots(struct lxc_container *c)
 {
 	char path[MAXPATHLEN];
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	int count=0;
 	DIR *dir;
 
@@ -2293,7 +2293,7 @@ static bool has_snapshots(struct lxc_container *c)
 	dir = opendir(path);
 	if (!dir)
 		return false;
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 
@@ -3503,7 +3503,7 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
 {
 	char snappath[MAXPATHLEN], path2[MAXPATHLEN];
 	int count = 0, ret;
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	struct lxc_snapshot *snaps =NULL, *nsnaps;
 	DIR *dir;
 
@@ -3520,7 +3520,7 @@ static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot
 		return 0;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 
@@ -3666,7 +3666,7 @@ static bool do_snapshot_destroy(const char *snapname, const char *clonelxcpath)
 static bool remove_all_snapshots(const char *path)
 {
 	DIR *dir;
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	bool bret = true;
 
 	dir = opendir(path);
@@ -3674,7 +3674,7 @@ static bool remove_all_snapshots(const char *path)
 		SYSERROR("opendir on snapshot path %s", path);
 		return false;
 	}
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 		if (!strcmp(direntp->d_name, "."))
@@ -4191,7 +4191,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
 {
 	DIR *dir;
 	int i, cfound = 0, nfound = 0;
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	struct lxc_container *c;
 
 	if (!lxcpath)
@@ -4208,7 +4208,7 @@ int list_defined_containers(const char *lxcpath, char ***names, struct lxc_conta
 	if (names)
 		*names = NULL;
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 06e7522..78c9ed0 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -209,7 +209,7 @@ static int match_fd(int fd)
  */
 int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	int fd, fddir;
 	DIR *dir;
 
@@ -225,7 +225,7 @@ int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 
 	fddir = dirfd(dir);
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		if (!direntp)
 			break;
 
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 614add5..27362da 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -90,7 +90,7 @@ extern bool btrfs_try_remove_subvol(const char *path);
 static int _recursive_rmdir(char *dirname, dev_t pdev,
 			    const char *exclude, int level, bool onedev)
 {
-	struct dirent dirent, *direntp;
+	struct dirent *direntp;
 	DIR *dir;
 	int ret, failed=0;
 	char pathname[MAXPATHLEN];
@@ -102,7 +102,7 @@ static int _recursive_rmdir(char *dirname, dev_t pdev,
 		return -1;
 	}
 
-	while (!readdir_r(dir, &dirent, &direntp)) {
+	while ((direntp = readdir(dir))) {
 		struct stat mystat;
 		int rc;
 

From d7538219961a4cb12b0f7132be4c3bad713b4dd7 Mon Sep 17 00:00:00 2001
From: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
Date: Tue, 12 Jul 2016 17:53:08 +0200
Subject: [PATCH 093/334] templates: add more quotes to variables (at least
 $rootfs should now be covered)

Signed-off-by: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
---
 templates/lxc-debian.in | 176 ++++++++++++++++++++++++------------------------
 1 file changed, 88 insertions(+), 88 deletions(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index d1cd6f2..509ea3a 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -49,9 +49,9 @@ configure_debian()
 
     # squeeze only has /dev/tty and /dev/tty0 by default,
     # therefore creating missing device nodes for tty1-4.
-    for tty in $(seq 1 $num_tty); do
-        if [ ! -e $rootfs/dev/tty$tty ]; then
-            mknod $rootfs/dev/tty$tty c 4 $tty
+    for tty in $(seq 1 "$num_tty"); do
+        if [ ! -e "$rootfs/dev/tty$tty" ]; then
+            mknod "$rootfs/dev/tty$tty" c 4 "$tty"
         fi
     done
 
@@ -69,18 +69,18 @@ l6:6:wait:/etc/init.d/rc 6
 # Normally not reached, but fallthrough in case of emergency.
 z6:6:respawn:/sbin/sulogin
 1:2345:respawn:/sbin/getty 38400 console
-$(for tty in $(seq 1 $num_tty); do echo "c${tty}:12345:respawn:/sbin/getty 38400 tty${tty} linux" ; done;)
+$(for tty in $(seq 1 "$num_tty"); do echo "c${tty}:12345:respawn:/sbin/getty 38400 tty${tty} linux" ; done;)
 p6::ctrlaltdel:/sbin/init 6
 p0::powerfail:/sbin/init 0
 EOF
 
     # symlink mtab
-    [ -e "$rootfs/etc/mtab" ] && rm $rootfs/etc/mtab
-    ln -s /proc/self/mounts $rootfs/etc/mtab
+    [ -e "$rootfs/etc/mtab" ] && rm "$rootfs/etc/mtab"
+    ln -s /proc/self/mounts "$rootfs/etc/mtab"
 
     # disable selinux in debian
-    mkdir -p $rootfs/selinux
-    echo 0 > $rootfs/selinux/enforce
+    mkdir -p "$rootfs/selinux"
+    echo 0 > "$rootfs/selinux/enforce"
 
     # configure the network using the dhcp
     cat <<EOF > $rootfs/etc/network/interfaces
@@ -100,60 +100,60 @@ EOF
 
     # but first reconfigure locales - so we get no noisy perl-warnings
     if [ -z "$LANG" ]; then
-        cat >> $rootfs/etc/locale.gen << EOF
+        cat >> "$rootfs/etc/locale.gen" << EOF
 en_US.UTF-8 UTF-8
 EOF
-        chroot $rootfs locale-gen en_US.UTF-8 UTF-8
-        chroot $rootfs update-locale LANG=en_US.UTF-8
+        chroot "$rootfs" locale-gen en_US.UTF-8 UTF-8
+        chroot "$rootfs" update-locale LANG=en_US.UTF-8
     else
-        encoding=$(echo $LANG | cut -d. -f2)
-        chroot $rootfs sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
+        encoding=$(echo "$LANG" | cut -d. -f2)
+        chroot "$rootfs" sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
             -i /etc/locale.gen 2> /dev/null
-        cat >> $rootfs/etc/locale.gen << EOF
+        cat >> "$rootfs/etc/locale.gen" << EOF
 $LANG $encoding
 EOF
-        chroot $rootfs locale-gen $LANG $encoding
-        chroot $rootfs update-locale LANG=$LANG
+        chroot "$rootfs" locale-gen "$LANG" "$encoding"
+        chroot "$rootfs" update-locale LANG="$LANG"
     fi
 
     # remove pointless services in a container
-    chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh disable
-    chroot $rootfs /usr/sbin/update-rc.d -f umountfs disable
-    chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh disable
-    chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh disable
+    chroot "$rootfs" /usr/sbin/update-rc.d -f checkroot.sh disable
+    chroot "$rootfs" /usr/sbin/update-rc.d -f umountfs disable
+    chroot "$rootfs" /usr/sbin/update-rc.d -f hwclock.sh disable
+    chroot "$rootfs" /usr/sbin/update-rc.d -f hwclockfirst.sh disable
 
     # generate new SSH keys
-    if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then
-        cat > $rootfs/usr/sbin/policy-rc.d << EOF
+    if [ -x "$rootfs/var/lib/dpkg/info/openssh-server.postinst" ]; then
+        cat > "$rootfs/usr/sbin/policy-rc.d" << EOF
 #!/bin/sh
 exit 101
 EOF
-        chmod +x $rootfs/usr/sbin/policy-rc.d
+        chmod +x "$rootfs/usr/sbin/policy-rc.d"
 
-        if [ -f $rootfs/etc/init/ssh.conf ]; then
-            mv $rootfs/etc/init/ssh.conf $rootfs/etc/init/ssh.conf.disabled
+        if [ -f "$rootfs/etc/init/ssh.conf" ]; then
+            mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled"
         fi
 
-        rm -f $rootfs/etc/ssh/ssh_host_*key*
+        rm -f "$rootfs/etc/ssh/"ssh_host_*key*
 
-        DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs /var/lib/dpkg/info/openssh-server.postinst configure
-        sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub
+        DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot "$rootfs" /var/lib/dpkg/info/openssh-server.postinst configure
+        sed -i "s/root@$(hostname)/root@$hostname/g" "$rootfs/etc/ssh/"ssh_host_*.pub
 
         if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then
-            mv $rootfs/etc/init/ssh.conf.disabled $rootfs/etc/init/ssh.conf
+            mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf"
         fi
 
-        rm -f $rootfs/usr/sbin/policy-rc.d
+        rm -f "$rootfs/usr/sbin/policy-rc.d"
     fi
 
     # set initial timezone as on host
     if [ -f /etc/timezone ]; then
-        cat /etc/timezone > $rootfs/etc/timezone
-        chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
+        cat /etc/timezone > "$rootfs/etc/timezone"
+        chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata
     elif [ -f /etc/sysconfig/clock ]; then
         . /etc/sysconfig/clock
-        echo $ZONE > $rootfs/etc/timezone
-        chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
+        echo "$ZONE" > "$rootfs/etc/timezone"
+        chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata
     else
         echo "Timezone in container is not configured. Adjust it manually."
     fi
@@ -197,9 +197,9 @@ install_packages()
     local rootfs="$1"; shift
     local packages="$*"
 
-    chroot ${rootfs} apt-get update
+    chroot "${rootfs}" apt-get update
     if [ -n "${packages}" ]; then
-        chroot ${rootfs} apt-get install --force-yes -y --no-install-recommends ${packages}
+        chroot "${rootfs}" apt-get install --force-yes -y --no-install-recommends ${packages}
     fi
 }
 
@@ -211,42 +211,42 @@ configure_debian_systemd()
     num_tty=$4
 
     # this only works if we have getty at .service to manipulate
-    if [ -f ${rootfs}/lib/systemd/system/getty\@.service ]; then
+    if [ -f "${rootfs}/lib/systemd/system/getty\@.service" ]; then
        sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
            -e 's/After=dev-%i.device/After=/' \
-           < ${rootfs}/lib/systemd/system/getty\@.service \
-           > ${rootfs}/etc/systemd/system/getty\@.service
+           < "${rootfs}/lib/systemd/system/getty\@.service" \
+           > "${rootfs}/etc/systemd/system/getty\@.service"
     fi
 
     # just in case systemd is not installed
-    mkdir -p ${rootfs}/{lib,etc}/systemd/system
-    mkdir -p ${rootfs}/etc/systemd/system/getty.target.wants
+    mkdir -p "${rootfs}/{lib,etc}/systemd/system"
+    mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants"
 
     # Fix getty-static-service as debootstrap does not install dbus
-    if [ -e $rootfs//lib/systemd/system/getty-static.service ] ; then
-        local tty_services=$(for i in $(seq 2 $num_tty); do echo -n "getty at tty${i}.service "; done; )
+    if [ -e "$rootfs//lib/systemd/system/getty-static.service" ] ; then
+        local tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty at tty${i}.service "; done; )
         sed 's/ getty at tty.*/'" $tty_services "'/g' \
-                $rootfs/lib/systemd/system/getty-static.service |  \
-                sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > $rootfs/etc/systemd/system/getty-static.service
+                "$rootfs/lib/systemd/system/getty-static.service" |  \
+                sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > "$rootfs/etc/systemd/system/getty-static.service"
     fi
 
     # This function has been copied and adapted from lxc-fedora
-    rm -f ${rootfs}/etc/systemd/system/default.target
-    chroot ${rootfs} ln -s /dev/null /etc/systemd/system/udev.service
-    chroot ${rootfs} ln -s /dev/null /etc/systemd/system/systemd-udevd.service
-    chroot ${rootfs} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
+    rm -f "${rootfs}/etc/systemd/system/default.target"
+    chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/udev.service
+    chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/systemd-udevd.service
+    chroot "${rootfs}" ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
     # Make systemd honor SIGPWR
-    chroot ${rootfs} ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
+    chroot "${rootfs}" ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
     # Setup getty service on the ttys we are going to allow in the
     # default config.  Number should match lxc.tty
-    ( cd ${rootfs}/etc/systemd/system/getty.target.wants
-        for i in $(seq 1 $num_tty) ; do ln -sf ../getty\@.service getty at tty${i}.service; done )
+    ( cd "${rootfs}/etc/systemd/system/getty.target.wants"
+        for i in $(seq 1 "$num_tty") ; do ln -sf ../getty\@.service getty at tty"${i}".service; done )
 
     # Since we use static-getty.target; we need to mask container-getty at .service generated by
     # container-getty-generator, so we don't get multiple instances of agetty running.
     # See https://github.com/lxc/lxc/issues/520 and https://github.com/lxc/lxc/issues/484
-    ( cd ${rootfs}/etc/systemd/system/getty.target.wants
-        for i in $(seq 0 $num_tty); do ln -sf /dev/null container-getty\@${i}.service; done )
+    ( cd "${rootfs}/etc/systemd/system/getty.target.wants"
+        for i in $(seq 0 "$num_tty"); do ln -sf /dev/null container-getty\@"${i}".service; done )
 
     return 0
 }
@@ -304,7 +304,7 @@ openssh-server
                 ;;
         esac
         wget https://ftp-master.debian.org/keys/${gpgkeyname}.asc -O - --quiet \
-            | gpg --import --no-default-keyring --keyring=${releasekeyring}
+            | gpg --import --no-default-keyring --keyring="${releasekeyring}"
     fi
     # check the mini debian was not already downloaded
     mkdir -p "$cache/partial-$release-$arch"
@@ -370,7 +370,7 @@ install_debian()
             fi
         fi
 
-        copy_debian $cache $arch $rootfs $release
+        copy_debian "$cache" "$arch" "$rootfs" "$release"
         if [ $? -ne 0 ]; then
             echo "Failed to copy rootfs"
             return 1
@@ -394,25 +394,25 @@ copy_configuration()
     # Generate the configuration file
     # if there is exactly one veth network entry, make sure it has an
     # associated hwaddr.
-    nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
-    if [ $nics -eq 1 ]; then
-        grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
+    nics=$(grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' "$path/config" | wc -l)
+    if [ "$nics" -eq 1 ]; then
+        grep -q "^lxc.network.hwaddr" "$path/config" || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" "$path/config"
     fi
 
     ## Add all the includes
-    echo "" >> $path/config
-    echo "# Common configuration" >> $path/config
+    echo "" >> "$path/config"
+    echo "# Common configuration" >> "$path/config"
     if [ -e "${LXC_TEMPLATE_CONFIG}/debian.common.conf" ]; then
-        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.common.conf" >> $path/config
+        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.common.conf" >> "$path/config"
     fi
     if [ -e "${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" ]; then
-        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" >> $path/config
+        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" >> "$path/config"
     fi
 
     ## Add the container-specific config
-    echo "" >> $path/config
-    echo "# Container specific configuration" >> $path/config
-    grep -q "^lxc.rootfs" $path/config 2> /dev/null || echo "lxc.rootfs = $rootfs" >> $path/config
+    echo "" >> "$path/config"
+    echo "# Container specific configuration" >> "$path/config"
+    grep -q "^lxc.rootfs" "$path/config" 2> /dev/null || echo "lxc.rootfs = $rootfs" >> "$path/config"
 
     cat <<EOF >> $path/config
 lxc.tty = $num_tty
@@ -437,17 +437,17 @@ post_process()
     local packages="$*"
 
     # Disable service startup
-    cat > ${rootfs}/usr/sbin/policy-rc.d << EOF
+    cat > "${rootfs}/usr/sbin/policy-rc.d" << EOF
 #!/bin/sh
 exit 101
 EOF
-    chmod +x ${rootfs}/usr/sbin/policy-rc.d
+    chmod +x "${rootfs}/usr/sbin/policy-rc.d"
 
     # If the container isn't running a native architecture, setup multiarch
     if [ "${arch}" != "${hostarch}" ]; then
         # Test if dpkg supports multiarch
-        if ! chroot $rootfs dpkg --print-foreign-architecture 2>&1; then
-            chroot $rootfs dpkg --add-architecture ${hostarch}
+        if ! chroot "$rootfs" dpkg --print-foreign-architecture 2>&1; then
+            chroot "$rootfs" dpkg --add-architecture "${hostarch}"
         fi
     fi
 
@@ -456,18 +456,18 @@ EOF
     if [ "${arch}" = "${hostarch}" ]; then
         write_sourceslist ${rootfs} ${release} ${arch}
     else
-        write_sourceslist ${rootfs} ${release}
+        write_sourceslist "${rootfs}" "${release}"
     fi
 
     # Install Packages in container
     if [ -n "${packages}" ]; then
-        local pack_list="`echo ${packages} | sed 's/,/ /g'`"
+        local pack_list="$(echo "${packages}" | sed 's/,/ /g')"
         echo "Installing packages: ${pack_list}"
-        install_packages ${rootfs} ${pack_list}
+        install_packages "${rootfs}" "${pack_list}"
     fi
 
     # Re-enable service startup
-    rm ${rootfs}/usr/sbin/policy-rc.d
+    rm "${rootfs}/usr/sbin/policy-rc.d"
     
     # end
 }
@@ -476,7 +476,7 @@ clean()
 {
     cache=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc/debian"}
 
-    if [ ! -e $cache ]; then
+    if [ ! -e "$cache" ]; then
         exit 0
     fi
 
@@ -489,7 +489,7 @@ clean()
         fi
 
         echo -n "Purging the download cache..."
-        rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
+        rm --preserve-root --one-file-system -rf "$cache" && echo "Done." || exit 1
         exit 0
 
     ) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian
@@ -537,7 +537,7 @@ EOF
 
 options=$(getopt -o hp:n:a:r:c -l arch:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror: -- "$@")
 if [ $? -ne 0 ]; then
-        usage $(basename $0)
+        usage "$(basename "$0")"
         exit 1
 fi
 eval set -- "$options"
@@ -556,7 +556,7 @@ mainonly=1
 while true
 do
     case "$1" in
-        -h|--help)            usage $0 && exit 1;;
+        -h|--help)            usage "$0" && exit 1;;
            --)                shift 1; break ;;
 
         -a|--arch)            arch=$2; shift 2;;
@@ -618,7 +618,7 @@ if [ "$(id -u)" != "0" ]; then
     exit 1
 fi
 
-current_release=`wget ${MIRROR}/dists/stable/Release -O - 2> /dev/null | head |awk '/^Codename: (.*)$/ { print $2; }'`
+current_release=$(wget "${MIRROR}/dists/stable/Release" -O - 2> /dev/null | head |awk '/^Codename: (.*)$/ { print $2; }')
 release=${release:-${current_release}}
 valid_releases=('wheezy' 'jessie' 'stretch' 'sid')
 if [[ ! "${valid_releases[*]}" =~ (^|[^[:alpha:]])$release([^[:alpha:]]|$) ]]; then
@@ -629,41 +629,41 @@ fi
 # detect rootfs
 config="$path/config"
 if [ -z "$rootfs" ]; then
-    if grep -q '^lxc.rootfs' $config 2> /dev/null ; then
-        rootfs=$(awk -F= '/^lxc.rootfs[ \t]+=/{ print $2 }' $config)
+    if grep -q '^lxc.rootfs' "$config" 2> /dev/null ; then
+        rootfs=$(awk -F= '/^lxc.rootfs[ \t]+=/{ print $2 }' "$config")
     else
         rootfs=$path/rootfs
     fi
 fi
 
 # determine the number of ttys - default is 4
-if grep -q '^lxc.tty' $config 2> /dev/null ; then
-    num_tty=$(awk -F= '/^lxc.tty[ \t]+=/{ print $2 }' $config)
+if grep -q '^lxc.tty' "$config" 2> /dev/null ; then
+    num_tty=$(awk -F= '/^lxc.tty[ \t]+=/{ print $2 }' "$config")
 else
     num_tty=4
 fi
 
-install_debian $rootfs $release $arch $LXC_CACHE_PATH
+install_debian "$rootfs" "$release" "$arch" "$LXC_CACHE_PATH"
 if [ $? -ne 0 ]; then
     echo "failed to install debian"
     exit 1
 fi
 
-configure_debian $rootfs $name $num_tty
+configure_debian "$rootfs" "$name" $num_tty
 if [ $? -ne 0 ]; then
     echo "failed to configure debian for a container"
     exit 1
 fi
 
-copy_configuration $path $rootfs $name $arch $num_tty
+copy_configuration "$path" "$rootfs" "$name" $arch $num_tty
 if [ $? -ne 0 ]; then
     echo "failed write configuration file"
     exit 1
 fi
 
-configure_debian_systemd $path $rootfs $config $num_tty
+configure_debian_systemd "$path" "$rootfs" "$config" $num_tty
 
-post_process ${rootfs} ${release} ${arch} ${hostarch} ${packages}
+post_process "${rootfs}" "${release}" ${arch} ${hostarch} ${packages}
 
 if [ ! -z "$clean" ]; then
     clean || exit 1

From c71f845ce4728b16b18c6d145c13a2e81061376d Mon Sep 17 00:00:00 2001
From: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
Date: Fri, 15 Jul 2016 16:59:01 +0200
Subject: [PATCH 094/334] templates: make shellcheck (Ubuntu: 0.3.7-5 amd64)
 most possible happy

Signed-off-by: Andreas Freudenberg <andreas.freudenberg at licomonch.net>
---
 templates/lxc-debian.in | 33 +++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 509ea3a..ac8158c 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -158,7 +158,7 @@ EOF
         echo "Timezone in container is not configured. Adjust it manually."
     fi
 
-    echo "root:root" | chroot $rootfs chpasswd
+    echo "root:root" | chroot "$rootfs" chpasswd
     echo "Root password is 'root', please change !"
 
     return 0
@@ -224,7 +224,8 @@ configure_debian_systemd()
 
     # Fix getty-static-service as debootstrap does not install dbus
     if [ -e "$rootfs//lib/systemd/system/getty-static.service" ] ; then
-        local tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty at tty${i}.service "; done; )
+        local tty_services
+        tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty at tty${i}.service "; done; )
         sed 's/ getty at tty.*/'" $tty_services "'/g' \
                 "$rootfs/lib/systemd/system/getty-static.service" |  \
                 sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > "$rootfs/etc/systemd/system/getty-static.service"
@@ -253,8 +254,8 @@ configure_debian_systemd()
 
 cleanup()
 {
-    rm -rf $cache/partial-$release-$arch
-    rm -rf $cache/rootfs-$release-$arch
+    rm -rf "$cache/partial-$release-$arch"
+    rm -rf "$cache/rootfs-$release-$arch"
 }
 
 download_debian()
@@ -315,9 +316,9 @@ openssh-server
 
     # download a mini debian into a cache
     echo "Downloading debian minimal ..."
-    debootstrap --verbose --variant=minbase --arch=$arch \
-        --include=$packages --keyring=${releasekeyring} \
-        "$release" "$cache/partial-$release-$arch" $MIRROR
+    debootstrap --verbose --variant=minbase --arch="$arch" \
+        --include="$packages" --keyring="${releasekeyring}" \
+        "$release" "$cache/partial-$release-$arch" "$MIRROR"
     if [ $? -ne 0 ]; then
         echo "Failed to download the rootfs, aborting."
         return 1
@@ -342,8 +343,8 @@ copy_debian()
 
     # make a local copy of the minidebian
     echo -n "Copying rootfs to $rootfs..."
-    mkdir -p $rootfs
-    rsync -Ha "$cache/rootfs-$release-$arch"/ $rootfs/ || return 1
+    mkdir -p "$rootfs"
+    rsync -Ha "$cache/rootfs-$release-$arch"/ "$rootfs"/ || return 1
     return 0
 }
 
@@ -363,7 +364,7 @@ install_debian()
 
         echo "Checking cache download in $cache/rootfs-$release-$arch ... "
         if [ ! -e "$cache/rootfs-$release-$arch" ]; then
-            download_debian $cache $arch $release
+            download_debian "$cache" "$arch" "$release"
             if [ $? -ne 0 ]; then
                 echo "Failed to download 'debian base'"
                 return 1
@@ -394,7 +395,7 @@ copy_configuration()
     # Generate the configuration file
     # if there is exactly one veth network entry, make sure it has an
     # associated hwaddr.
-    nics=$(grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' "$path/config" | wc -l)
+    nics=$(grep -ce '^lxc\.network\.type[ \t]*=[ \t]*veth' "$path/config")
     if [ "$nics" -eq 1 ]; then
         grep -q "^lxc.network.hwaddr" "$path/config" || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" "$path/config"
     fi
@@ -452,23 +453,23 @@ EOF
     fi
 
     # Write a new sources.list containing both native and multiarch entries
-    > ${rootfs}/etc/apt/sources.list
+    > "${rootfs}/etc/apt/sources.list"
     if [ "${arch}" = "${hostarch}" ]; then
-        write_sourceslist ${rootfs} ${release} ${arch}
+        write_sourceslist "${rootfs}" "${release}" "${arch}"
     else
         write_sourceslist "${rootfs}" "${release}"
     fi
 
     # Install Packages in container
     if [ -n "${packages}" ]; then
-        local pack_list="$(echo "${packages}" | sed 's/,/ /g')"
+        local pack_list
+        pack_list="${packages//,/ }"
         echo "Installing packages: ${pack_list}"
         install_packages "${rootfs}" "${pack_list}"
     fi
 
     # Re-enable service startup
     rm "${rootfs}/usr/sbin/policy-rc.d"
-    
     # end
 }
 
@@ -663,7 +664,7 @@ fi
 
 configure_debian_systemd "$path" "$rootfs" "$config" $num_tty
 
-post_process "${rootfs}" "${release}" ${arch} ${hostarch} ${packages}
+post_process "${rootfs}" "${release}" "${arch}" "${hostarch}" "${packages}"
 
 if [ ! -z "$clean" ]; then
     clean || exit 1

From be3ee4adbabb62f0d5a8564e21c8b47fd13793c9 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Fri, 12 Aug 2016 17:04:15 +0900
Subject: [PATCH 095/334] doc: Update lxc-attach(1)

* Add undocumented options (-v/--set-var, --keep-var, -f/--rcfile)
* Change order of option in SYNOPSIS (-L that is placed after "command")
* Add long options in SYNOPSIS

Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 doc/lxc-attach.sgml.in | 59 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/doc/lxc-attach.sgml.in b/doc/lxc-attach.sgml.in
index 3b103f9..7535bb1 100644
--- a/doc/lxc-attach.sgml.in
+++ b/doc/lxc-attach.sgml.in
@@ -50,15 +50,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>lxc-attach</command>
-      <arg choice="req">-n <replaceable>name</replaceable></arg>
-      <arg choice="opt">-a <replaceable>arch</replaceable></arg>
-      <arg choice="opt">-e</arg>
-      <arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
-      <arg choice="opt">-R</arg>
+      <arg choice="req">-n, --name <replaceable>name</replaceable></arg>
+      <arg choice="opt">-f, --rcfile <replaceable>config_file</replaceable></arg>
+      <arg choice="opt">-a, --arch <replaceable>arch</replaceable></arg>
+      <arg choice="opt">-e, --elevated-privileges <replaceable>privileges</replaceable></arg>
+      <arg choice="opt">-s, --namespaces <replaceable>namespaces</replaceable></arg>
+      <arg choice="opt">-R, --remount-sys-proc</arg>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
+      <arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
+      <arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
+      <arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
-      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -104,6 +107,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
       <varlistentry>
 	<term>
+	  <option>-f, --rcfile <replaceable>config_file</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    Specify the configuration file to configure the virtualization
+	    and isolation functionalities for the container.
+	  </para>
+	  <para>
+	   This configuration file if present will be used even if there is
+	   already a configuration file present in the previously created
+	   container (via lxc-create).
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
 	  <option>-a, --arch <replaceable>arch</replaceable></option>
 	</term>
 	<listitem>
@@ -252,6 +272,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 	</listitem>
       </varlistentry>
 
+      <varlistentry>
+	<term>
+	  <option>-v, --set-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    Set an additional environment variable that is seen by the
+	    attached program in the container. It is specified in the
+	    form of "VAR=VALUE", and can be specified multiple times.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
+	  <option>--keep-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    Keep a specified environment variable. It can only be
+	    specified in conjunction
+	    with <replaceable>--clear-env</replaceable>, and can be
+	    specified multiple times.
+	  </para>
+	</listitem>
+      </varlistentry>
+
      </variablelist>
 
   </refsect1>

From 9b9e2d5e20be33cb7534f3fedceb9e2a7e04dd43 Mon Sep 17 00:00:00 2001
From: KATOH Yasufumi <karma at jazz.email.ne.jp>
Date: Fri, 12 Aug 2016 17:29:55 +0900
Subject: [PATCH 096/334] doc: Update Japanese lxc-attach(1)

* Add undocumented options (-v/--set-var, --keep-var, -f/--rcfile)
* Change order of option in SYNOPSIS (-L that is placed after "command")
* Add long options in SYNOPSIS

Signed-off-by: KATOH Yasufumi <karma at jazz.email.ne.jp>
---
 doc/ja/lxc-attach.sgml.in | 71 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 65 insertions(+), 6 deletions(-)

diff --git a/doc/ja/lxc-attach.sgml.in b/doc/ja/lxc-attach.sgml.in
index 25322da..f04ee02 100644
--- a/doc/ja/lxc-attach.sgml.in
+++ b/doc/ja/lxc-attach.sgml.in
@@ -55,15 +55,18 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>lxc-attach</command>
-      <arg choice="req">-n <replaceable>name</replaceable></arg>
-      <arg choice="opt">-a <replaceable>arch</replaceable></arg>
-      <arg choice="opt">-e</arg>
-      <arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
-      <arg choice="opt">-R</arg>
+      <arg choice="req">-n, --name <replaceable>name</replaceable></arg>
+      <arg choice="opt">-f, --rcfile <replaceable>config_file</replaceable></arg>
+      <arg choice="opt">-a, --arch <replaceable>arch</replaceable></arg>
+      <arg choice="opt">-e, --elevated-privileges <replaceable>privileges</replaceable></arg>
+      <arg choice="opt">-s, --namespaces <replaceable>namespaces</replaceable></arg>
+      <arg choice="opt">-R, --remount-sys-proc</arg>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
+      <arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
+      <arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
+      <arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
-      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -123,6 +126,29 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
 
       <varlistentry>
 	<term>
+	  <option>-f, --rcfile <replaceable>config_file</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+            <!--
+	    Specify the configuration file to configure the virtualization
+	    and isolation functionalities for the container.
+            -->
+            コンテナの仮想化、隔離機能の設定のための設定ファイルを指定します。
+	  </para>
+	  <para>
+            <!--
+	   This configuration file if present will be used even if there is
+	   already a configuration file present in the previously created
+	   container (via lxc-create).
+           -->
+            (lxc-create 経由で) 前もってコンテナが作られた際の設定ファイルが既にあった場合でも、このオプションが指定された場合は、指定した設定ファイルが使用されます。
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
 	  <option>-a, --arch <replaceable>arch</replaceable></option>
 	</term>
 	<listitem>
@@ -334,6 +360,39 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+	<term>
+	  <option>-v, --set-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    <!--
+	    Set an additional environment variable that is seen by the
+	    attached program in the container. It is specified in the
+	    form of "VAR=VALUE", and can be specified multiple times.
+	    -->
+	    コンテナにアタッチしたプログラムから見える環境変数を追加します。このオプションは "VAR=VALUE" の形式で指定し、複数回指定できます。
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
+	  <option>--keep-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    <!--
+	    Keep a specified environment variable. It can only be
+	    specified in conjunction
+	    with <replaceable>\-\-clear-env</replaceable>, and can be
+	    specified multiple times.
+	    -->
+	    <replaceable>--clear-env</replaceable> を指定した際に、クリアせずに保持したままにしたい環境変数を指定します。<replaceable>--clear-env</replaceable> と同時にしか使えません。複数回指定できます。
+	  </para>
+	</listitem>
+      </varlistentry>
+
     </variablelist>
 
   </refsect1>

From 014c8714f5af15829a6683be9db228d11133b635 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 12 Aug 2016 21:07:34 +0200
Subject: [PATCH 097/334] bdev: be smarter about btrfs subvolume detection

When a container c is on a btrfs filesystem but is directory backed, copying
the container will default to snapshot. This is because of
should_default_to_snapshot() returning true in this case because c is on a
btrfs filesystem. We should make sure that should_default_to_snapshot() only
returns true, when c itself is a btrfs subvolume.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/bdev/lxcbtrfs.c | 27 +++++++++++++++++++++++++++
 src/lxc/bdev/lxcbtrfs.h |  5 +++++
 src/lxc/lxccontainer.c  |  4 ++++
 3 files changed, 36 insertions(+)

diff --git a/src/lxc/bdev/lxcbtrfs.c b/src/lxc/bdev/lxcbtrfs.c
index 5ee6dd3..7879d71 100644
--- a/src/lxc/bdev/lxcbtrfs.c
+++ b/src/lxc/bdev/lxcbtrfs.c
@@ -33,6 +33,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/vfs.h>
 
 #include "bdev.h"
 #include "log.h"
@@ -142,6 +143,32 @@ bool is_btrfs_fs(const char *path)
 	return true;
 }
 
+/*
+ * Taken from btrfs toolsuite. Test if path is a subvolume.
+ *	return 0;   path exists but it is not a subvolume
+ *	return 1;   path exists and it is  a subvolume
+ *	return < 0; error
+ */
+int is_btrfs_subvol(const char *path)
+{
+	struct stat st;
+	struct statfs stfs;
+	int ret;
+
+	ret = stat(path, &st);
+	if (ret < 0)
+		return -errno;
+
+	if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode))
+		return 0;
+
+	ret = statfs(path, &stfs);
+	if (ret < 0)
+		return -errno;
+
+	return stfs.f_type == BTRFS_SUPER_MAGIC;
+}
+
 int btrfs_detect(const char *path)
 {
 	struct stat st;
diff --git a/src/lxc/bdev/lxcbtrfs.h b/src/lxc/bdev/lxcbtrfs.h
index 3b2742f..ebd8421 100644
--- a/src/lxc/bdev/lxcbtrfs.h
+++ b/src/lxc/bdev/lxcbtrfs.h
@@ -30,6 +30,10 @@
 #include <stdint.h>
 #include <byteswap.h>
 
+#ifndef BTRFS_SUPER_MAGIC
+#  define BTRFS_SUPER_MAGIC       0x9123683E
+#endif
+
 typedef uint8_t u8;
 typedef uint16_t u16;
 typedef uint32_t u32;
@@ -404,6 +408,7 @@ char *get_btrfs_subvol_path(int fd, u64 dir_id, u64 objid, char *name,
 			    int name_len);
 int btrfs_list_get_path_rootid(int fd, u64 *treeid);
 bool is_btrfs_fs(const char *path);
+int is_btrfs_subvol(const char *path);
 bool btrfs_try_remove_subvol(const char *path);
 int btrfs_same_fs(const char *orig, const char *new);
 int btrfs_snapshot(const char *orig, const char *new);
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index ae0286f..5721977 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2826,6 +2826,7 @@ bool should_default_to_snapshot(struct lxc_container *c0,
 	size_t l1 = strlen(c1->config_path) + strlen(c1->name) + 2;
 	char *p0 = alloca(l0 + 1);
 	char *p1 = alloca(l1 + 1);
+	char *rootfs = c0->lxc_conf->rootfs.path;
 
 	snprintf(p0, l0, "%s/%s", c0->config_path, c0->name);
 	snprintf(p1, l1, "%s/%s", c1->config_path, c1->name);
@@ -2833,6 +2834,9 @@ bool should_default_to_snapshot(struct lxc_container *c0,
 	if (!is_btrfs_fs(p0) || !is_btrfs_fs(p1))
 		return false;
 
+	if (is_btrfs_subvol(rootfs) <= 0)
+		return false;
+
 	return btrfs_same_fs(p0, p1) == 0;
 }
 

From 3778a008f8de274aefe2a93281d5c6e0e6cd7f21 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sat, 13 Aug 2016 00:56:33 +0200
Subject: [PATCH 098/334] tools: use correct runtime path for lxc-ls

So far we've simply been using RUNTIME_PATH for the privileged and unprivileged
case. We should actually use XDG_RUNTIME_DIR for the unprivileged case.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/tools/lxc_ls.c | 25 ++++++++++++++++++++-----
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index e2a4c34..0575277 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -986,25 +986,40 @@ static int ls_get_wrapper(void *wrap)
 static int ls_remove_lock(const char *path, const char *name,
 		char **lockpath, size_t *len_lockpath, bool recalc)
 {
+	int ret = -1;
+	char *rundir;
+
+	/* lockfile will be:
+	 * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
+	 * or
+	 * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
+	 */
+	rundir = get_rundir();
+	if (!rundir)
+		goto out;
+
 	/* Avoid doing unnecessary work if we can. */
 	if (recalc) {
-		size_t newlen = strlen(path) + strlen(name) + strlen(RUNTIME_PATH) + /* / + lxc + / + lock + / + / = */ 11 + 1;
+		size_t newlen = strlen(path) + strlen(name) + strlen(rundir) + /* / + lxc + / + lock + / + / = */ 11 + 1;
 		if (newlen > *len_lockpath) {
 			char *tmp = realloc(*lockpath, newlen * 2);
 			if (!tmp)
-				return -1;
+				goto out;
 			*lockpath = tmp;
 			*len_lockpath = newlen * 2;
 		}
 	}
 
-	int check = snprintf(*lockpath, *len_lockpath, "%s/lxc/lock/%s/%s", RUNTIME_PATH, path, name);
+	int check = snprintf(*lockpath, *len_lockpath, "%s/lxc/lock/%s/%s", rundir, path, name);
 	if (check < 0 || (size_t)check >= *len_lockpath)
-		return -1;
+		goto out;
 
 	lxc_rmdir_onedev(*lockpath, NULL);
+	ret = 0;
 
-	return 0;
+out:
+	free(rundir);
+	return ret;
 }
 
 static int ls_send_str(int fd, const char *buf)

From ce64b2ca5ec518c1583430250f07f1b0367d6906 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sat, 13 Aug 2016 16:04:44 +0200
Subject: [PATCH 099/334] tools: add missing newline in lxc-create output

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/tools/lxc_create.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_create.c b/src/lxc/tools/lxc_create.c
index 4b0e9d7..6e8acf0 100644
--- a/src/lxc/tools/lxc_create.c
+++ b/src/lxc/tools/lxc_create.c
@@ -258,7 +258,7 @@ int main(int argc, char *argv[])
 		}
 		if (strcmp(my_args.bdevtype, "dir") && strcmp(my_args.bdevtype, "_unset") &&
 				strcmp(my_args.bdevtype, "btrfs")) {
-			fprintf(stderr, "Unprivileged users cannot create %s containers", my_args.bdevtype);
+			fprintf(stderr, "Unprivileged users cannot create %s containers.\n", my_args.bdevtype);
 			exit(EXIT_FAILURE);
 		}
 	}

From 03d3bbc95dfc882e03764c1d7a06427de6ea40b9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sat, 13 Aug 2016 22:38:52 +0200
Subject: [PATCH 100/334] tests: add unit tests for lxc_string_replace()

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/tests/Makefile.am      |  6 +++-
 src/tests/lxc-test-utils.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
 src/tests/lxctest.h        | 42 ++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 src/tests/lxc-test-utils.c
 create mode 100644 src/tests/lxctest.h

diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 26beeda..15b32f6 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -2,6 +2,8 @@ if ENABLE_TESTS
 
 LDADD = ../lxc/liblxc.so
 
+noinst_HEADERS += lxctest.h
+
 lxc_test_containertests_SOURCES = containertests.c
 lxc_test_locktests_SOURCES = locktests.c
 lxc_test_startone_SOURCES = startone.c
@@ -23,6 +25,7 @@ lxc_test_list_SOURCES = list.c
 lxc_test_attach_SOURCES = attach.c
 lxc_test_device_add_remove_SOURCES = device_add_remove.c
 lxc_test_apparmor_SOURCES = aa.c
+lxc_test_utils_SOURCES = lxc-test-utils.c lxctest.h
 
 AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
 	-DLXCPATH=\"$(LXCPATH)\" \
@@ -50,7 +53,7 @@ bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
 	lxc-test-cgpath lxc-test-clonetest lxc-test-console \
 	lxc-test-snapshot lxc-test-concurrent lxc-test-may-control \
 	lxc-test-reboot lxc-test-list lxc-test-attach lxc-test-device-add-remove \
-	lxc-test-apparmor
+	lxc-test-apparmor lxc-test-utils
 
 bin_SCRIPTS = lxc-test-automount lxc-test-autostart lxc-test-cloneconfig \
 	lxc-test-createconfig
@@ -94,6 +97,7 @@ EXTRA_DIST = \
 	lxc-test-symlink \
 	lxc-test-ubuntu \
 	lxc-test-unpriv \
+	lxc-test-utils \
 	may_control.c \
 	saveconfig.c \
 	shutdowntest.c \
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
new file mode 100644
index 0000000..8e7205c
--- /dev/null
+++ b/src/tests/lxc-test-utils.c
@@ -0,0 +1,73 @@
+/*
+ * lxc: linux Container library
+ *
+ * Copyright © 2016 Canonical Ltd.
+ *
+ * Authors:
+ * Christian Brauner <christian.brauner at mailbox.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lxctest.h"
+#include "utils.h"
+
+void test_string_replace(void)
+{
+	char *s;
+
+	s = lxc_string_replace("A", "A", "A");
+	lxc_test_assert_abort(strcmp(s, "A") == 0);
+	free(s);
+
+	s = lxc_string_replace("A", "AA", "A");
+	lxc_test_assert_abort(strcmp(s, "AA") == 0);
+	free(s);
+
+	s = lxc_string_replace("A", "AA", "BA");
+	lxc_test_assert_abort(strcmp(s, "BAA") == 0);
+	free(s);
+
+	s = lxc_string_replace("A", "AA", "BAB");
+	lxc_test_assert_abort(strcmp(s, "BAAB") == 0);
+	free(s);
+
+	s = lxc_string_replace("AA", "A", "AA");
+	lxc_test_assert_abort(strcmp(s, "A") == 0);
+	free(s);
+
+	s = lxc_string_replace("AA", "A", "BAA");
+	lxc_test_assert_abort(strcmp(s, "BA") == 0);
+	free(s);
+
+	s = lxc_string_replace("AA", "A", "BAAB");
+	lxc_test_assert_abort(strcmp(s, "BAB") == 0);
+	free(s);
+
+	s = lxc_string_replace("\"A\"A", "\"A\"", "B\"A\"AB");
+	lxc_test_assert_abort(strcmp(s, "B\"A\"B") == 0);
+	free(s);
+}
+
+int main(int argc, char *argv[])
+{
+	test_string_replace();
+
+	exit(EXIT_SUCCESS);
+}
diff --git a/src/tests/lxctest.h b/src/tests/lxctest.h
new file mode 100644
index 0000000..2793ca2
--- /dev/null
+++ b/src/tests/lxctest.h
@@ -0,0 +1,42 @@
+/*
+ * lxc: linux Container library
+ *
+ * Copyright © 2016 Canonical Ltd.
+ *
+ * Authors:
+ * Christian Brauner <christian.brauner at mailbox.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __LXC_TEST_H_
+#define __LXC_TEST_H_
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define lxc_test_assert_stringify(expression, stringify_expression)            \
+	do {                                                                   \
+		if (!(expression)) {                                           \
+			fprintf(stderr, "%s: %s: %d: %s\n", __FILE__,          \
+				__func__, __LINE__, stringify_expression);     \
+			abort();                                               \
+		}                                                              \
+	} while (false)
+
+#define lxc_test_assert_abort(expression) lxc_test_assert_stringify(expression, #expression)
+
+#endif /* __LXC_TEST_H */

From f3f690b80b7fae1d8ea4ed426f67876476a72669 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Sun, 14 Aug 2016 22:42:17 +0200
Subject: [PATCH 101/334] tests: add unit tests for lxc_string_in_array()

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/Makefile.am        |  3 ++-
 src/tests/Makefile.am      |  2 --
 src/tests/lxc-test-utils.c | 20 ++++++++++++++++++--
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 73a0971..c38320f 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -32,7 +32,8 @@ noinst_HEADERS = \
 	start.h \
 	state.h \
 	utils.h \
-	criu.h
+	criu.h \
+	../tests/lxctest.h
 
 if IS_BIONIC
 noinst_HEADERS += \
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 15b32f6..92a4500 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -2,8 +2,6 @@ if ENABLE_TESTS
 
 LDADD = ../lxc/liblxc.so
 
-noinst_HEADERS += lxctest.h
-
 lxc_test_containertests_SOURCES = containertests.c
 lxc_test_locktests_SOURCES = locktests.c
 lxc_test_startone_SOURCES = startone.c
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 8e7205c..4c1c373 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -28,7 +28,7 @@
 #include "lxctest.h"
 #include "utils.h"
 
-void test_string_replace(void)
+void test_lxc_string_replace(void)
 {
 	char *s;
 
@@ -65,9 +65,25 @@ void test_string_replace(void)
 	free(s);
 }
 
+void test_lxc_string_in_array(void)
+{
+	lxc_test_assert_abort(lxc_string_in_array("", (const char *[]){"", NULL}));
+	lxc_test_assert_abort(!lxc_string_in_array("A", (const char *[]){"", NULL}));
+	lxc_test_assert_abort(!lxc_string_in_array("AAA", (const char *[]){"", "3472", "jshH", NULL}));
+
+	lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", NULL}));
+	lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", "B", "C", NULL}));
+	lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"B", "A", "C", NULL}));
+
+	lxc_test_assert_abort(lxc_string_in_array("ABC", (const char *[]){"ASD", "ATR", "ABC", NULL}));
+	lxc_test_assert_abort(lxc_string_in_array("GHJ", (const char *[]){"AZIU", "WRT567B", "879C", "GHJ", "IUZ89", NULL}));
+	lxc_test_assert_abort(lxc_string_in_array("XYZ", (const char *[]){"BERTA", "ARQWE(9", "C8Zhkd", "7U", "XYZ", "UOIZ9", "=)()", NULL}));
+}
+
 int main(int argc, char *argv[])
 {
-	test_string_replace();
+	test_lxc_string_replace();
+	test_lxc_string_in_array();
 
 	exit(EXIT_SUCCESS);
 }

From 6605c50ffbd2da334191c87cbe36138147848a5f Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Tue, 16 Aug 2016 01:42:38 +0200
Subject: [PATCH 102/334] autotools: fix tests

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/tests/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 92a4500..cffc742 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -95,7 +95,7 @@ EXTRA_DIST = \
 	lxc-test-symlink \
 	lxc-test-ubuntu \
 	lxc-test-unpriv \
-	lxc-test-utils \
+	lxc-test-utils.c \
 	may_control.c \
 	saveconfig.c \
 	shutdowntest.c \

From 2c7ef9196cef03383a1b6a13628e0227736f8164 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 15 Aug 2016 22:37:38 -0400
Subject: [PATCH 103/334] change version to 2.0.4 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 54c987b..c3d891a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 3)
+m4_define([lxc_version_micro], 4)
 m4_define([lxc_version_beta], [])
 m4_define([lxc_version_abi], 1.2.0)
 

From 8e82b76ed05374a864a6ab339feba1d76b8b385c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 15 Aug 2016 22:42:21 -0400
Subject: [PATCH 104/334] Fix .gitignore after /tools/ split
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 .gitignore | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index adc965e..1f9cd22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,7 +36,7 @@ src/lxc/init.lxc.static
 src/lxc/lxc-attach
 src/lxc/lxc-autostart
 src/lxc/lxc-cgroup
-src/lxc/lxc-checkconfig
+src/lxc/tools/lxc-checkconfig
 src/lxc/lxc-checkpoint
 src/lxc/lxc-clone
 src/lxc/lxc-console
@@ -56,7 +56,7 @@ src/lxc/lxc-monitord
 src/lxc/lxc-shutdown
 src/lxc/lxc-snapshot
 src/lxc/lxc-start
-src/lxc/lxc-start-ephemeral
+src/lxc/tools/lxc-start-ephemeral
 src/lxc/lxc-stop
 src/lxc/lxc-top
 src/lxc/lxc-unfreeze

From e44003f95a73145f48ced29345a24d498c359263 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 15 Aug 2016 22:42:45 -0400
Subject: [PATCH 105/334] Add lxc-test-utils to .gitignore
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 1f9cd22..67a8692 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,6 +92,7 @@ src/tests/lxc-test-shutdowntest
 src/tests/lxc-test-snapshot
 src/tests/lxc-test-startone
 src/tests/lxc-test-usernic
+src/tests/lxc-test-utils
 src/tests/lxc-usernic-test
 
 config/compile

From c3612dc03d7b2d43799334095be1566e567a03f9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Tue, 16 Aug 2016 20:00:35 +0200
Subject: [PATCH 106/334] bdev: use correct overlay module name

- Assume that the module name is "overlay" per default and not "overlayfs".
- Assume that the overlay version we are using requires a workdir.
- When we mount an overlay filesystem and we fail with ENODEV retry once with
  the module name we haven't already used.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/bdev/lxcoverlay.c | 53 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/src/lxc/bdev/lxcoverlay.c b/src/lxc/bdev/lxcoverlay.c
index 3caadbc..e8d0f6d 100644
--- a/src/lxc/bdev/lxcoverlay.c
+++ b/src/lxc/bdev/lxcoverlay.c
@@ -39,6 +39,7 @@
 lxc_log_define(lxcoverlay, lxc);
 
 static char *ovl_name;
+static char *ovl_version[] = {"overlay", "overlayfs"};
 
 /* defined in lxccontainer.c: needs to become common helper */
 extern char *dir_new_path(char *src, const char *oldname, const char *name,
@@ -49,6 +50,9 @@ static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
 			struct lxc_conf *conf);
 static int ovl_rsync(struct rsync_data *data);
 static int ovl_rsync_wrapper(void *data);
+static int ovl_remount_on_enodev(const char *lower, const char *target,
+				 const char *name, unsigned long mountflags,
+				 const void *options);
 
 int ovl_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
 		   const char *cname, const char *oldpath, const char *lxcpath,
@@ -408,23 +412,28 @@ int ovl_mount(struct bdev *bdev)
 		return -1;
 	}
 
-	// mount without workdir option for overlayfs before v21
-	ret = mount(lower, bdev->dest, ovl_name, MS_MGC_VAL | mntflags, options);
+        /* Assume we need a workdir as we are on a overlay version >= v22. */
+	ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
+				    MS_MGC_VAL | mntflags, options_work);
 	if (ret < 0) {
-		INFO("overlayfs: error mounting %s onto %s options %s. retry with workdir",
-			lower, bdev->dest, options);
+		INFO("Overlayfs: Error mounting %s onto %s with options %s. "
+		     "Retrying without workdir: %s.",
+		     lower, bdev->dest, options_work, strerror(errno));
 
-		// retry with workdir option for overlayfs v22 and higher
-		ret = mount(lower, bdev->dest, ovl_name, MS_MGC_VAL | mntflags, options_work);
+                /* Assume we cannot use a workdir as we are on a version <= v21. */
+		ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
+					  MS_MGC_VAL | mntflags, options);
 		if (ret < 0)
-			SYSERROR("overlayfs: error mounting %s onto %s options %s",
-				lower, bdev->dest, options_work);
+			SYSERROR("Overlayfs: Error mounting %s onto %s with "
+				 "options %s: %s.",
+				 lower, bdev->dest, options,
+				 strerror(errno));
 		else
-			INFO("overlayfs: mounted %s onto %s options %s",
-				lower, bdev->dest, options_work);
+			INFO("Overlayfs: Mounted %s onto %s with options %s.",
+			     lower, bdev->dest, options);
 	} else {
-		INFO("overlayfs: mounted %s onto %s options %s",
-			lower, bdev->dest, options);
+		INFO("Overlayfs: Mounted %s onto %s with options %s.", lower,
+		     bdev->dest, options_work);
 	}
 	return ret;
 }
@@ -652,6 +661,20 @@ int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
 	return fret;
 }
 
+static int ovl_remount_on_enodev(const char *lower, const char *target,
+				 const char *name, unsigned long mountflags,
+				 const void *options)
+{
+        int ret;
+        ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
+        if (ret < 0 && errno == ENODEV) /* Try other module name. */
+		ret = mount(lower, target,
+			    ovl_name == ovl_version[0] ? ovl_version[1]
+						       : ovl_version[0],
+			    MS_MGC_VAL | mountflags, options);
+        return ret;
+}
+
 static int ovl_rsync(struct rsync_data *data)
 {
 	int ret;
@@ -700,7 +723,7 @@ static int ovl_rsync(struct rsync_data *data)
 
 static char *ovl_detect_name(void)
 {
-	char *v = "overlayfs";
+	char *v = ovl_version[0];
 	char *line = NULL;
 	size_t len = 0;
 	FILE *f = fopen("/proc/filesystems", "r");
@@ -708,8 +731,8 @@ static char *ovl_detect_name(void)
 		return v;
 
 	while (getline(&line, &len, f) != -1) {
-		if (strcmp(line, "nodev\toverlay\n") == 0) {
-			v = "overlay";
+		if (strcmp(line, "nodev\toverlayfs\n") == 0) {
+			v = ovl_version[1];
 			break;
 		}
 	}

From 476402ab6c7daea1db8ff103767dc88ac5331570 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 12:28:16 +0200
Subject: [PATCH 107/334] cleanup: tools: remove --name from lxc-top usage
 message

It doesn't have any effect on what lxc-top does and is only
accepted on account of being part of the common option list.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_top.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c
index c4cb871..47deddd 100644
--- a/src/lxc/tools/lxc_top.c
+++ b/src/lxc/tools/lxc_top.c
@@ -91,7 +91,7 @@ static const struct option my_longopts[] = {
 static struct lxc_arguments my_args = {
 	.progname = "lxc-top",
 	.help     = "\
-[--name=NAME]\n\
+\n\
 \n\
 lxc-top monitors the state of the active containers\n\
 \n\

From b4e66653f4c3ac0240e5ff810c74a44f554e2bac Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 12:33:10 +0200
Subject: [PATCH 108/334] cleanup: whitespaces in option alignment for
 lxc-execute

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_execute.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c
index 50d481f..c7c5096 100644
--- a/src/lxc/tools/lxc_execute.c
+++ b/src/lxc/tools/lxc_execute.c
@@ -86,8 +86,8 @@ Options :\n\
   -n, --name=NAME      NAME of the container\n\
   -f, --rcfile=FILE    Load configuration file FILE\n\
   -s, --define KEY=VAL Assign VAL to configuration variable KEY\n\
-  -u, --uid=UID Execute COMMAND with UID inside the container\n\
-  -g, --gid=GID Execute COMMAND with GID inside the container\n",
+  -u, --uid=UID        Execute COMMAND with UID inside the container\n\
+  -g, --gid=GID        Execute COMMAND with GID inside the container\n",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = my_checker,

From 3b9494bd64334d9c02a4fd2f9af04fa839830667 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 17 Aug 2016 15:42:34 -0400
Subject: [PATCH 109/334] Use full GPG fingerprint instead of long IDs.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With how easy it is to create a collision on a short ID nowadays and
given that the user doesn't actually have to remember or manually enter
the key ID, lets just use the full fingerprint from now on.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 templates/lxc-download.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-download.in b/templates/lxc-download.in
index d4cf830..4a67a7c 100644
--- a/templates/lxc-download.in
+++ b/templates/lxc-download.in
@@ -33,7 +33,7 @@ DOWNLOAD_DIST=
 DOWNLOAD_FLUSH_CACHE="false"
 DOWNLOAD_FORCE_CACHE="false"
 DOWNLOAD_INTERACTIVE="false"
-DOWNLOAD_KEYID="0xBAEFF88C22F6E216"
+DOWNLOAD_KEYID="0xE7FB0CAEC8173D669066514CBAEFF88C22F6E216"
 DOWNLOAD_KEYSERVER="hkp://pool.sks-keyservers.net"
 DOWNLOAD_LIST_IMAGES="false"
 DOWNLOAD_MODE="system"

From fe3b02ff94da199a8a327b3e92b6e42f2d875a45 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 12:21:22 +0200
Subject: [PATCH 110/334] tools: move --rcfile to the common options list

In almost all commands it's a useful addition to the -n
switch which is a common option, too.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/arguments.c            |  1 +
 src/lxc/arguments.h            |  2 ++
 src/lxc/tools/lxc_cgroup.c     | 12 +++++++++++-
 src/lxc/tools/lxc_checkpoint.c | 10 ++++++++++
 src/lxc/tools/lxc_console.c    | 12 +++++++++++-
 src/lxc/tools/lxc_copy.c       | 11 ++++++++++-
 src/lxc/tools/lxc_destroy.c    | 12 +++++++++++-
 src/lxc/tools/lxc_device.c     | 11 ++++++++++-
 src/lxc/tools/lxc_freeze.c     | 12 +++++++++++-
 src/lxc/tools/lxc_info.c       | 12 +++++++++++-
 src/lxc/tools/lxc_snapshot.c   | 12 +++++++++++-
 src/lxc/tools/lxc_stop.c       | 11 ++++++++++-
 src/lxc/tools/lxc_unfreeze.c   | 12 +++++++++++-
 src/lxc/tools/lxc_wait.c       | 12 +++++++++++-
 14 files changed, 131 insertions(+), 11 deletions(-)

diff --git a/src/lxc/arguments.c b/src/lxc/arguments.c
index c2f7b67..0d2b203 100644
--- a/src/lxc/arguments.c
+++ b/src/lxc/arguments.c
@@ -203,6 +203,7 @@ extern int lxc_arguments_parse(struct lxc_arguments *args,
 		case 'o':	args->log_file = optarg; break;
 		case 'l':	args->log_priority = optarg; break;
 		case 'q':	args->quiet = 1; break;
+		case OPT_RCFILE: args->rcfile = optarg; break;
 		case 'P':
 			remove_trailing_slashes(optarg);
 			ret = lxc_arguments_lxcpath_add(args, optarg);
diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
index 6bc6fcd..956cb37 100644
--- a/src/lxc/arguments.h
+++ b/src/lxc/arguments.h
@@ -148,11 +148,13 @@ struct lxc_arguments {
 	{"logfile", required_argument, 0, 'o'}, \
 	{"logpriority", required_argument, 0, 'l'}, \
 	{"lxcpath", required_argument, 0, 'P'}, \
+	{"rcfile", required_argument, 0, OPT_RCFILE}, \
 	{0, 0, 0, 0}
 
 /* option keys for long only options */
 #define	OPT_USAGE 0x1000
 #define	OPT_VERSION OPT_USAGE-1
+#define	OPT_RCFILE OPT_USAGE-2
 
 extern int lxc_arguments_parse(struct lxc_arguments *args,
 			       int argc, char *const argv[]);
diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index dd60fd1..c644501 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -56,7 +56,8 @@ Get or set the value of a state object (for example, 'cpuset.cpus')\n\
 in the container's cgroup for the corresponding subsystem.\n\
 \n\
 Options :\n\
-  -n, --name=NAME      NAME of the container",
+  -n, --name=NAME      NAME of the container\n\
+  --rcfile=FILE        Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = NULL,
 	.checker  = my_checker,
@@ -84,6 +85,15 @@ int main(int argc, char *argv[])
 	if (!c)
 		return 1;
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			ERROR("Failed to load rcfile");
+			lxc_container_put(c);
+			return 1;
+		}
+	}
+
 	if (!c->may_control(c)) {
 		ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
index 7130245..bc18b80 100644
--- a/src/lxc/tools/lxc_checkpoint.c
+++ b/src/lxc/tools/lxc_checkpoint.c
@@ -114,6 +114,7 @@ Options :\n\
   Restore options:\n\
   -d, --daemon              Daemonize the container (default)\n\
   -F, --foreground          Start with the current tty attached to /dev/console\n\
+  --rcfile=FILE             Load configuration file FILE\n\
 ",
 	.options   = my_longopts,
 	.parser    = my_parser,
@@ -214,6 +215,15 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			exit(1);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c
index adbd7e0..8a4d1c0 100644
--- a/src/lxc/tools/lxc_console.c
+++ b/src/lxc/tools/lxc_console.c
@@ -80,7 +80,8 @@ lxc-console logs on the container with the identifier NAME\n\
 Options :\n\
   -n, --name=NAME      NAME of the container\n\
   -t, --tty=NUMBER     console tty number\n\
-  -e, --escape=PREFIX  prefix for escape command\n",
+  -e, --escape=PREFIX  prefix for escape command\n\
+  --rcfile=FILE        Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = NULL,
@@ -112,6 +113,15 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index db63a6c..900a590 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -123,7 +123,8 @@ Options :\n\
   -D, --keedata	            pass together with -e start a persistent snapshot \n\
   -K, --keepname	    keep the hostname of the original container\n\
   --  hook options	    arguments passed to the hook program\n\
-  -M, --keepmac		    keep the MAC address of the original container\n",
+  -M, --keepmac		    keep the MAC address of the original container\n\
+  --rcfile=FILE		    Load configuration file FILE\n",
 	.options = my_longopts,
 	.parser = my_parser,
 	.task = CLONE,
@@ -199,6 +200,14 @@ int main(int argc, char *argv[])
 	if (!c)
 		exit(ret);
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			goto out;
+		}
+	}
+
 	if (!c->may_control(c)) {
 		if (!my_args.quiet)
 			fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
diff --git a/src/lxc/tools/lxc_destroy.c b/src/lxc/tools/lxc_destroy.c
index b521739..50fd708 100644
--- a/src/lxc/tools/lxc_destroy.c
+++ b/src/lxc/tools/lxc_destroy.c
@@ -53,7 +53,8 @@ lxc-destroy destroys a container with the identifier NAME\n\
 Options :\n\
   -n, --name=NAME   NAME of the container\n\
   -s, --snapshots   destroy including all snapshots\n\
-  -f, --force       wait for the container to shut down\n",
+  -f, --force       wait for the container to shut down\n\
+  --rcfile=FILE     Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = NULL,
@@ -88,6 +89,15 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		if (!quiet)
 			fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index 0c9e066..0f1ee8b 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -53,7 +53,8 @@ static struct lxc_arguments my_args = {
 lxc-device attach or detach DEV to or from container.\n\
 \n\
 Options :\n\
-  -n, --name=NAME      NAME of the container",
+  -n, --name=NAME      NAME of the container\n\
+  --rcfile=FILE        Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = NULL,
 	.checker  = NULL,
@@ -125,6 +126,14 @@ int main(int argc, char *argv[])
 		goto err;
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			ERROR("Failed to load rcfile");
+			goto err1;
+		}
+	}
+
 	if (!c->is_running(c)) {
 		ERROR("Container %s is not running.", c->name);
 		goto err1;
diff --git a/src/lxc/tools/lxc_freeze.c b/src/lxc/tools/lxc_freeze.c
index ea8bd3e..d0239bf 100644
--- a/src/lxc/tools/lxc_freeze.c
+++ b/src/lxc/tools/lxc_freeze.c
@@ -47,7 +47,8 @@ static struct lxc_arguments my_args = {
 lxc-freeze freezes a container with the identifier NAME\n\
 \n\
 Options :\n\
-  -n, --name=NAME      NAME of the container",
+  -n, --name=NAME      NAME of the container\n\
+  --rcfile=FILE        Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = NULL,
 	.checker  = NULL,
@@ -74,6 +75,15 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			ERROR("Failed to load rcfile");
+			lxc_container_put(c);
+			exit(1);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_info.c b/src/lxc/tools/lxc_info.c
index 58ff619..e833697 100644
--- a/src/lxc/tools/lxc_info.c
+++ b/src/lxc/tools/lxc_info.c
@@ -93,7 +93,8 @@ Options :\n\
   -p, --pid             shows the process id of the init container\n\
   -S, --stats           shows usage stats\n\
   -H, --no-humanize     shows stats as raw numbers, not humanized\n\
-  -s, --state           shows the state of the container\n",
+  -s, --state           shows the state of the container\n\
+  --rcfile=FILE         Load configuration file FILE\n",
 	.name     = NULL,
 	.options  = my_longopts,
 	.parser   = my_parser,
@@ -295,6 +296,15 @@ static int print_info(const char *name, const char *lxcpath)
 		return -1;
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			return -1;
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
index 8f44891..aa9b6fe 100644
--- a/src/lxc/tools/lxc_snapshot.c
+++ b/src/lxc/tools/lxc_snapshot.c
@@ -62,7 +62,8 @@ Options :\n\
   -d, --destroy=NAME     destroy snapshot NAME, e.g. 'snap0'\n\
                          use ALL to destroy all snapshots\n\
   -c, --comment=FILE     add FILE as a comment\n\
-  -C, --showcomments     show snapshot comments\n",
+  -C, --showcomments     show snapshot comments\n\
+  --rcfile=FILE          Load configuration file FILE\n",
 	.options = my_longopts,
 	.parser = my_parser,
 	.checker = NULL,
@@ -107,6 +108,15 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n",
 			my_args.name);
diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index 10ddce6..bbe1f1c 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -75,7 +75,8 @@ Options :\n\
   -t, --timeout=T   wait T seconds before hard-stopping\n\
   -k, --kill        kill container rather than request clean shutdown\n\
       --nolock      Avoid using API locks\n\
-      --nokill      Only request clean shutdown, don't force kill after timeout\n",
+      --nokill      Only request clean shutdown, don't force kill after timeout\n\
+  --rcfile=FILE     Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = NULL,
@@ -203,6 +204,14 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			goto out;
+		}
+	}
+
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
 		goto out;
diff --git a/src/lxc/tools/lxc_unfreeze.c b/src/lxc/tools/lxc_unfreeze.c
index 3a13d37..b7bbea6 100644
--- a/src/lxc/tools/lxc_unfreeze.c
+++ b/src/lxc/tools/lxc_unfreeze.c
@@ -45,7 +45,8 @@ static struct lxc_arguments my_args = {
 lxc-unfreeze unfreezes a container with the identifier NAME\n\
 \n\
 Options :\n\
-  -n, --name=NAME   NAME of the container\n",
+  -n, --name=NAME   NAME of the container\n\
+  --rcfile=FILE     Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = NULL,
 	.checker  = NULL,
@@ -78,6 +79,15 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			ERROR("Failed to load rcfile");
+			lxc_container_put(c);
+			exit(1);
+		}
+	}
+
 	if (!c->unfreeze(c)) {
 		ERROR("Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
diff --git a/src/lxc/tools/lxc_wait.c b/src/lxc/tools/lxc_wait.c
index 712ba52..deeff98 100644
--- a/src/lxc/tools/lxc_wait.c
+++ b/src/lxc/tools/lxc_wait.c
@@ -72,7 +72,8 @@ Options :\n\
   -s, --state=STATE ORed states to wait for\n\
                     STOPPED, STARTING, RUNNING, STOPPING,\n\
                     ABORTING, FREEZING, FROZEN, THAWED\n\
-  -t, --timeout=TMO Seconds to wait for state changes\n",
+  -t, --timeout=TMO Seconds to wait for state changes\n\
+  --rcfile=FILE     Load configuration file FILE\n",
 	.options  = my_longopts,
 	.parser   = my_parser,
 	.checker  = my_checker,
@@ -104,6 +105,15 @@ int main(int argc, char *argv[])
 		return 1;
 	}
 
+	if (my_args.rcfile) {
+		c->clear_config(c);
+		if (!c->load_config(c, my_args.rcfile)) {
+			fprintf(stderr, "Failed to load rcfile\n");
+			lxc_container_put(c);
+			return 1;
+		}
+	}
+
 	if (!c->wait(c, my_args.states, my_args.timeout)) {
 		lxc_container_put(c);
 		return 1;

From 700f5c364c4650149006131ded6baf4f85dcd32c Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 14:49:37 +0200
Subject: [PATCH 111/334] tools: set configfile after load_config

In order to cause c->is_defined() to become true.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_attach.c     | 6 ++++++
 src/lxc/tools/lxc_cgroup.c     | 6 ++++++
 src/lxc/tools/lxc_checkpoint.c | 6 ++++++
 src/lxc/tools/lxc_console.c    | 6 ++++++
 src/lxc/tools/lxc_copy.c       | 5 +++++
 src/lxc/tools/lxc_destroy.c    | 6 ++++++
 src/lxc/tools/lxc_device.c     | 5 +++++
 src/lxc/tools/lxc_freeze.c     | 6 ++++++
 src/lxc/tools/lxc_info.c       | 6 ++++++
 src/lxc/tools/lxc_snapshot.c   | 6 ++++++
 src/lxc/tools/lxc_stop.c       | 5 +++++
 src/lxc/tools/lxc_unfreeze.c   | 6 ++++++
 src/lxc/tools/lxc_wait.c       | 6 ++++++
 13 files changed, 75 insertions(+)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 281f97a..9d71388 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -385,6 +385,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(EXIT_FAILURE);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index c644501..4dc2682 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -92,6 +92,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			return 1;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			lxc_container_put(c);
+			return 1;
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
index bc18b80..6de3d23 100644
--- a/src/lxc/tools/lxc_checkpoint.c
+++ b/src/lxc/tools/lxc_checkpoint.c
@@ -222,6 +222,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(1);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			exit(1);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c
index 8a4d1c0..829c908 100644
--- a/src/lxc/tools/lxc_console.c
+++ b/src/lxc/tools/lxc_console.c
@@ -120,6 +120,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(EXIT_FAILURE);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 900a590..f8ca861 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -206,6 +206,11 @@ int main(int argc, char *argv[])
 			fprintf(stderr, "Failed to load rcfile\n");
 			goto out;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			goto out;
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_destroy.c b/src/lxc/tools/lxc_destroy.c
index 50fd708..3f46415 100644
--- a/src/lxc/tools/lxc_destroy.c
+++ b/src/lxc/tools/lxc_destroy.c
@@ -96,6 +96,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(EXIT_FAILURE);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index 0f1ee8b..49af062 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -132,6 +132,11 @@ int main(int argc, char *argv[])
 			ERROR("Failed to load rcfile");
 			goto err1;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			goto err1;
+		}
 	}
 
 	if (!c->is_running(c)) {
diff --git a/src/lxc/tools/lxc_freeze.c b/src/lxc/tools/lxc_freeze.c
index d0239bf..ac0802e 100644
--- a/src/lxc/tools/lxc_freeze.c
+++ b/src/lxc/tools/lxc_freeze.c
@@ -82,6 +82,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(1);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			lxc_container_put(c);
+			exit(1);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_info.c b/src/lxc/tools/lxc_info.c
index e833697..08c698d 100644
--- a/src/lxc/tools/lxc_info.c
+++ b/src/lxc/tools/lxc_info.c
@@ -303,6 +303,12 @@ static int print_info(const char *name, const char *lxcpath)
 			lxc_container_put(c);
 			return -1;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			return -1;
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
index aa9b6fe..a1166bc 100644
--- a/src/lxc/tools/lxc_snapshot.c
+++ b/src/lxc/tools/lxc_snapshot.c
@@ -115,6 +115,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(EXIT_FAILURE);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			exit(EXIT_FAILURE);
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index bbe1f1c..cb7cfe2 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -210,6 +210,11 @@ int main(int argc, char *argv[])
 			fprintf(stderr, "Failed to load rcfile\n");
 			goto out;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			goto out;
+		}
 	}
 
 	if (!c->may_control(c)) {
diff --git a/src/lxc/tools/lxc_unfreeze.c b/src/lxc/tools/lxc_unfreeze.c
index b7bbea6..24faf5e 100644
--- a/src/lxc/tools/lxc_unfreeze.c
+++ b/src/lxc/tools/lxc_unfreeze.c
@@ -86,6 +86,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(1);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			lxc_container_put(c);
+			exit(1);
+		}
 	}
 
 	if (!c->unfreeze(c)) {
diff --git a/src/lxc/tools/lxc_wait.c b/src/lxc/tools/lxc_wait.c
index deeff98..61fd869 100644
--- a/src/lxc/tools/lxc_wait.c
+++ b/src/lxc/tools/lxc_wait.c
@@ -112,6 +112,12 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			return 1;
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			fprintf(stderr, "Out of memory setting new config filename\n");
+			lxc_container_put(c);
+			return 1;
+		}
 	}
 
 	if (!c->wait(c, my_args.states, my_args.timeout)) {

From d36ccc89dbd1dd1e564a70999f0780d08e48cab5 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 14:55:42 +0200
Subject: [PATCH 112/334] doc: add --rcfile to common opts

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 doc/common_options.sgml.in | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/doc/common_options.sgml.in b/doc/common_options.sgml.in
index 38783dd..978c0ba 100644
--- a/doc/common_options.sgml.in
+++ b/doc/common_options.sgml.in
@@ -107,6 +107,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     </varlistentry>
 
     <varlistentry>
+      <term><option>--rcfile=<replaceable>FILE</replaceable></option></term>
+      <listitem>
+	<para>
+	  Specify the configuration file to configure the virtualization
+	  and isolation functionalities for the container.
+	</para>
+	<para>
+	 This configuration file if present will be used even if there is
+	 already a configuration file present in the previously created
+	 container (via lxc-create).
+	</para>
+      </listitem>
+    </varlistentry>
+
+    <varlistentry>
       <term><option>--version</option></term>
       <listitem>
         <para>

From d2fc8f3bac94504ff99c26bdbb31007703c8ac43 Mon Sep 17 00:00:00 2001
From: Sungbae Yoo <sungbae.yoo at samsung.com>
Date: Thu, 18 Aug 2016 16:36:24 +0900
Subject: [PATCH 113/334] doc: Update Korean lxc-attach(1)

 * Update for commit 03b0398
 * Fix mistranslation words

Signed-off-by: Sungbae Yoo <sungbae.yoo at samsung.com>
---
 doc/ko/lxc-attach.sgml.in | 91 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 75 insertions(+), 16 deletions(-)

diff --git a/doc/ko/lxc-attach.sgml.in b/doc/ko/lxc-attach.sgml.in
index eb7baf0..7a7dfa5 100644
--- a/doc/ko/lxc-attach.sgml.in
+++ b/doc/ko/lxc-attach.sgml.in
@@ -55,15 +55,18 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>lxc-attach</command>
-      <arg choice="req">-n <replaceable>name</replaceable></arg>
-      <arg choice="opt">-a <replaceable>arch</replaceable></arg>
-      <arg choice="opt">-e</arg>
-      <arg choice="opt">-s <replaceable>namespaces</replaceable></arg>
-      <arg choice="opt">-R</arg>
+      <arg choice="req">-n, --name <replaceable>name</replaceable></arg>
+      <arg choice="opt">-f, --rcfile <replaceable>config_file</replaceable></arg>
+      <arg choice="opt">-a, --arch <replaceable>arch</replaceable></arg>
+      <arg choice="opt">-e, --elevated-privileges <replaceable>privileges</replaceable></arg>
+      <arg choice="opt">-s, --namespaces <replaceable>namespaces</replaceable></arg>
+      <arg choice="opt">-R, --remount-sys-proc</arg>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
+      <arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
+      <arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
+      <arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
-      <arg choice="opt">-L <replaceable>file</replaceable></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -107,10 +110,10 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
       will not try to allocate a pseudo terminal. Instead it will simply attach
       to the containers namespaces and run a shell or the specified command.
       -->
-      이전 버전의 <command>lxc-attach</command>는 단순히 컨테이너의 특정 네임스페이스에 붙어, 쉘을 실행하거나 첫 번째 pseudo 터미널 할당 없이 특정 명령어를 실행하였다.
+      이전 버전의 <command>lxc-attach</command>는 단순히 컨테이너의 특정 네임스페이스 내에서 쉘이나 명령어를 pseudo 터미널 할당 없이 실행하였다.
       이는 다른 특권 수준을 갖는 사용자 영역 컨텍스트 간의 전환후 TIOCSTI <command>ioctl</command>를 호출하여 입력을 가로챌 수 있는 취약점이 있다.
-      새로운 버전의 <command>lxc-attach</command>는 쉘이나 명령어를 실행하기 전에, pseudo 터미널 마스터/슬레이브 쌍을 호스트에 할당하고 터미널을 가리키고 있던 표준 입출력 파일 디스크립터들은 슬레이브 pseudo 터미널로 붙인다.
-      터미널을 가리키고 있던 표준 입출력 파일 디스크립터가 아예 없었다면, <command>lxc-attach</command>는 pseudo 터미널 할당을 시도하지 않음에 주의해야 한다. 단순히 컨테이너 네임스페이스에 붙어 쉘이나 지정한 명령어만 실행할 뿐이다.
+      새로운 버전의 <command>lxc-attach</command>는 쉘이나 명령어를 실행하기 전, 호스트에서 pseudo 터미널 마스터/슬레이브 쌍을 할당하고, 터미널을 가리키고 있던 표준 입출력 파일 디스크립터들을 pseudo 터미널의 슬레이브로 연결한다.
+      터미널을 가리키고 있던 표준 입출력 파일 디스크립터가 아예 없었다면, <command>lxc-attach</command>는 pseudo 터미널 할당을 시도하지 않음에 주의해야 한다. 단순히 컨테이너 네임스페이스 내부에서 쉘이나 지정한 명령어를 실행할 뿐이다.
     </para>
 
   </refsect1>
@@ -123,6 +126,29 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
 
       <varlistentry>
 	<term>
+       <option>-f, --rcfile <replaceable>config_file</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+         <!--
+	    Specify the configuration file to configure the virtualization
+	    and isolation functionalities for the container.
+        -->
+		컨테이너의 가상화 및 고립 기능들을 설정할 파일을 지정한다.
+	  </para>
+	  <para>
+        <!--
+	    This configuration file if present will be used even if there is
+	    already a configuration file present in the previously created
+	    container (via lxc-create).
+        -->
+       이전에 만들어졌던 컨테이너에 설정 파일이 이미 있더라도, 이 옵션이 지정되어 있다면 해당 파일을 사용한다.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
 	  <option>-a, --arch <replaceable>arch</replaceable></option>
 	</term>
 	<listitem>
@@ -217,7 +243,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
             <replaceable>MOUNT\|PID</replaceable> or quoted, e.g.
             <replaceable>"MOUNT|PID"</replaceable>.)
             -->
-            붙일 네임스페이스를 지정한다. <replaceable>NETWORK|IPC</replaceable>와 같이 파이프(|)로 구분된 리스트를 사용할 수 있다. 허용되는 값은 <replaceable>MOUNT</replaceable>, <replaceable>PID</replaceable>, <replaceable>UTSNAME</replaceable>, <replaceable>IPC</replaceable>, <replaceable>USER </replaceable>, <replaceable>NETWORK</replaceable>이다. 이를 사용하여, 컨테이너의 네트워크 네임스페이스를 사용하면서도 다른 네임스페이스는 호스트의 것을 그대로 사용하는 등의 조작이 가능하다.
+           컨테이너의 어떤 네임스페이스와 연결할지 지정한다. <replaceable>NETWORK|IPC</replaceable>와 같이 파이프(|)로 구분된 리스트를 사용할 수 있다. 허용되는 값은 <replaceable>MOUNT</replaceable>, <replaceable>PID</replaceable>, <replaceable>UTSNAME</replaceable>, <replaceable>IPC</replaceable>, <replaceable>USER </replaceable>, <replaceable>NETWORK</replaceable>이다. 이를 사용하여, 컨테이너의 네트워크 네임스페이스를 사용하면서도 다른 네임스페이스는 호스트의 것을 그대로 사용하는 등의 조작이 가능하다.
             (파이프 기호는 <replaceable>MOUNT\|PID</replaceable>처럼 \로 처리를 해주거나, <replaceable>"MOUNT|PID"</replaceable>처럼 따옴표를 붙여야 한다.)
 	  </para>
 	  <para>
@@ -258,7 +284,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
 	    This option will be ignored if one tries to attach to the
 	    mount namespace anyway.
             -->
-            만약 마운트 네임스페이스에 attach하려고 한다면, 이 옵션은 무시된다.
+            만약 마운트 네임스페이스에 연결하려고 한다면, 이 옵션은 무시된다.
 	  </para>
 	</listitem>
       </varlistentry>
@@ -278,7 +304,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
 	    please use this option to be future-proof. In addition to
 	    current environment variables, container=lxc will be set.
             -->
-            현재의 환경변수를 attach될 프로그램에도 그대로 적용한다. 이것은 현재 기본 동작이지만 (버전 0.9에서), 향후에 충분히 바뀔 수도 있다. 왜냐하면, 이것은 컨테이너에게 바람직하지 않은 정보를 넘겨줄 수 있는 위험성이 있기 때문이다. 따라서 이 기능에 의존하고 있다면, 향후에도 이를 보장할 수 있도록 이 옵션을 사용하는 것이 좋다. 또한 현재 환경 변수와 더불어, container=lxc도 설정된다.
+            현재의 환경변수를 실행할 프로그램에도 그대로 적용한다. 이것은 현재 기본 동작이지만 (버전 0.9에서), 향후에 충분히 바뀔 수도 있다. 왜냐하면, 이것은 컨테이너에게 바람직하지 않은 정보를 넘겨줄 수 있는 위험성이 있기 때문이다. 따라서 이 기능에 의존하고 있다면, 향후에도 이를 보장할 수 있도록 이 옵션을 사용하는 것이 좋다. 또한 현재 환경 변수와 더불어, container=lxc도 설정된다.
 	  </para>
 	</listitem>
       </varlistentry>
@@ -295,8 +321,8 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
 	    container=lxc will be the only environment with which the
 	    attached program starts.
             -->
-            attach하기 전에 모든 환경변수를 지운다.
-            이를 통해 바람직하지 않은 환경변수 누출을 막을 수 있다. container=lxc 만이 attach된 프로그램이 실행되기 전에 설정되는 유일한 환경변수이다.
+            프로그램을 실행하기 전에 모든 환경변수를 지운다.
+            이를 통해 바람직하지 않은 환경변수 누출을 막을 수 있다. container=lxc 만이 프로그램이 실행되기 전에 설정되는 유일한 환경변수이다.
 	  </para>
 	</listitem>
       </varlistentry>
@@ -322,6 +348,39 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
           </para>
         </listitem>
       </varlistentry>
+     <varlistentry>
+	<term>
+	  <option>-v, --set-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    <!--
+	    Set an additional environment variable that is seen by the
+	    attached program in the container. It is specified in the
+	    form of "VAR=VALUE", and can be specified multiple times.
+	    -->
+        컨테이너 내에서 실행되는 프로그램이 볼 수 있는 환경변수를 추가한다.
+        이는 "VAR=VALUE" 형태로 지정되며, 여러 번 지정할 수 있다.
+	  </para>
+	</listitem>
+      </varlistentry>
+
+      <varlistentry>
+	<term>
+	  <option>--keep-var <replaceable>variable</replaceable></option>
+	</term>
+	<listitem>
+	  <para>
+	    <!--
+	    Keep a specified environment variable. It can only be
+	    specified in conjunction
+	    with <replaceable>\-\-clear-env</replaceable>, and can be
+	    specified multiple times.
+	    -->
+        <replaceable>\-\-clear-env</replaceable>와 함께 사용되며, 지정한 환경변수를 지우지 않고 그대로 유지한다. 여러 번 지정할 수 있다.
+	  </para>
+	</listitem>
+      </varlistentry>
 
     </variablelist>
 
@@ -399,7 +458,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
       Attaching to user namespaces is supported by kernel 3.8 or higher
       with enabling user namespace.
       -->
-      사용자 네임스페이스에 attach하기 위해서는 커널 버전이 3.8 이상이어야 하고 사용자 네임스페이스가 활성화되어야 한다.
+      사용자 네임스페이스와 연결되기 위해서는 커널 버전이 3.8 이상이어야 하고 사용자 네임스페이스가 활성화되어야 한다.
     </para>
   </refsect1>
 
@@ -419,7 +478,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
       <replaceable>/sys</replaceable>.
       -->
       리눅스의 <replaceable>/proc</replaceable>와 <replaceable>/sys</replaceable> 파일시스템은 네임스페이스의해 영향받는 몇가지 정보들을 포함하고 있다. 예를 들어 <replaceable>/proc</replaceable>의 프로세스 id로 된 폴더들이나 <replaceable>/sys/class/net</replaceable>의 네트워크 인터페이스 정보 등이다.
-의사파일시스템을 마운트하는 프로세스의 네임스페이스가 여기에 어떤 정보를 표시할지 결정하는 것이지, <replaceable>/proc</replaceable> 또는 <replaceable>/sys</replaceable>에 접근하는 프로세스의 네임스페이스가 결정하는 것은 <emphasis>아니다.</emphasis>
+pseudo 파일시스템을 마운트하는 프로세스의 네임스페이스가 여기에 어떤 정보를 표시할지 결정하는 것이지, <replaceable>/proc</replaceable> 또는 <replaceable>/sys</replaceable>에 접근하는 프로세스의 네임스페이스가 결정하는 것은 <emphasis>아니다.</emphasis>
     </para>
     <para>
       <!--

From 88a2aad66bfd4aec5da8ff684572cb98a4ce981d Mon Sep 17 00:00:00 2001
From: Sungbae Yoo <sungbae.yoo at samsung.com>
Date: Thu, 18 Aug 2016 16:49:26 +0900
Subject: [PATCH 114/334] doc: Add --rcfile to Korean common opts

Update for commit 71d74a8

Signed-off-by: Sungbae Yoo <sungbae.yoo at samsung.com>
---
 doc/ko/common_options.sgml.in | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/doc/ko/common_options.sgml.in b/doc/ko/common_options.sgml.in
index a7c405e..9e8b1b1 100644
--- a/doc/ko/common_options.sgml.in
+++ b/doc/ko/common_options.sgml.in
@@ -141,6 +141,27 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
     </varlistentry>
 
     <varlistentry>
+      <term><option>--rcfile=<replaceable>FILE</replaceable></option></term>
+      <listitem>
+	<para>
+	  <!--
+	  Specify the configuration file to configure the virtualization
+	  and isolation functionalities for the container.
+	  -->
+	  컨테이너의 가상화 및 고립 기능들을 설정할 파일을 지정한다.
+	</para>
+	<para>
+	  <!--
+	  This configuration file if present will be used even if there is
+	  already a configuration file present in the previously created
+	  container (via lxc-create).
+	  -->
+	  이전에 만들어졌던 컨테이너에 설정 파일이 이미 있더라도, 이 옵션이 지정되어 있다면 해당 파일을 사용한다.
+	</para>
+      </listitem>
+    </varlistentry>
+
+    <varlistentry>
       <term><option>--version</option></term>
       <listitem>
 	<para>

From e30ace060250dbf0ed50cb117db8f123779d6136 Mon Sep 17 00:00:00 2001
From: Sungbae Yoo <sungbae.yoo at samsung.com>
Date: Thu, 18 Aug 2016 17:09:00 +0900
Subject: [PATCH 115/334] doc: Add --rcfile to Japanese common opts

Update for commit 71d74a8

Signed-off-by: Sungbae Yoo <sungbae.yoo at samsung.com>
---
 doc/ja/common_options.sgml.in | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/doc/ja/common_options.sgml.in b/doc/ja/common_options.sgml.in
index 912298f..5360945 100644
--- a/doc/ja/common_options.sgml.in
+++ b/doc/ja/common_options.sgml.in
@@ -141,6 +141,27 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
     </varlistentry>
 
     <varlistentry>
+     <term><option>--rcfile=<replaceable>FILE</replaceable></option></term>
+      <listitem>
+	<para>
+	  <!--
+	  Specify the configuration file to configure the virtualization
+	  and isolation functionalities for the container.
+	  -->
+	  コンテナの仮想化、隔離機能の設定のための設定ファイルを指定します。
+	</para>
+	<para>
+	  <!--
+	  This configuration file if present will be used even if there is
+	  already a configuration file present in the previously created
+	  container (via lxc-create).
+	  -->
+	  (lxc-create 経由で) 前もってコンテナが作られた際の設定ファイルが既にあった場合でも、このオプションが指定された場合は、指定した設定ファイルが使用されます。
+	</para>
+      </listitem>
+    </varlistentry>
+
+    <varlistentry>
       <term><option>--version</option></term>
       <listitem>
         <para>

From 2aec5fd4cacb53e191c4c0c31a50305078ae7c17 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Thu, 18 Aug 2016 09:16:41 +0200
Subject: [PATCH 116/334] tools: use exit(EXIT_*) everywhere

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/tools/lxc_autostart.c  |  8 ++++----
 src/lxc/tools/lxc_cgroup.c     | 20 ++++++++++----------
 src/lxc/tools/lxc_checkpoint.c | 19 +++++++++++--------
 src/lxc/tools/lxc_config.c     |  4 ++--
 src/lxc/tools/lxc_console.c    |  2 +-
 src/lxc/tools/lxc_device.c     |  6 +++---
 src/lxc/tools/lxc_execute.c    | 18 +++++++++---------
 src/lxc/tools/lxc_freeze.c     | 16 ++++++++--------
 src/lxc/tools/lxc_info.c       |  6 +++---
 src/lxc/tools/lxc_monitor.c    | 18 +++++++-----------
 src/lxc/tools/lxc_start.c      | 24 +++++++++++------------
 src/lxc/tools/lxc_stop.c       | 43 +++++++++++++++++++++---------------------
 src/lxc/tools/lxc_top.c        |  2 +-
 src/lxc/tools/lxc_unfreeze.c   | 16 ++++++++--------
 src/lxc/tools/lxc_unshare.c    | 19 ++++++++++---------
 src/lxc/tools/lxc_usernsexec.c | 18 +++++++++---------
 src/lxc/tools/lxc_wait.c       | 16 ++++++++--------
 17 files changed, 128 insertions(+), 127 deletions(-)

diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index eed0f5f..267cb6c 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -334,17 +334,17 @@ int main(int argc, char *argv[])
 	struct lxc_list *cmd_group;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	count = list_defined_containers(my_args.lxcpath[0], NULL, &containers);
 
 	if (count < 0)
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (!my_args.all) {
 		/* Allocate an array for our container group lists */
@@ -522,5 +522,5 @@ int main(int argc, char *argv[])
 	toss_list( cmd_groups_list );
 	free(containers);
 
-	return 0;
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index 4dc2682..32d333a 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -69,47 +69,47 @@ int main(int argc, char *argv[])
 	struct lxc_container *c;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	state_object = my_args.argv[0];
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c)
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (my_args.rcfile) {
 		c->clear_config(c);
 		if (!c->load_config(c, my_args.rcfile)) {
 			ERROR("Failed to load rcfile");
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 		c->configfile = strdup(my_args.rcfile);
 		if (!c->configfile) {
 			ERROR("Out of memory setting new config filename");
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 	}
 
 	if (!c->may_control(c)) {
 		ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (!c->is_running(c)) {
 		ERROR("'%s:%s' is not running", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if ((my_args.argc) > 1) {
@@ -118,7 +118,7 @@ int main(int argc, char *argv[])
 			ERROR("failed to assign '%s' value to '%s' for '%s'",
 				value, state_object, my_args.name);
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 	} else {
 		int len = 4096;
@@ -128,11 +128,11 @@ int main(int argc, char *argv[])
 			ERROR("failed to retrieve value of '%s' for '%s:%s'",
 			      state_object, my_args.lxcpath[0], my_args.name);
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 		printf("%*s", ret, buffer);
 	}
 
 	lxc_container_put(c);
-	return 0;
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_checkpoint.c b/src/lxc/tools/lxc_checkpoint.c
index 6de3d23..462aba3 100644
--- a/src/lxc/tools/lxc_checkpoint.c
+++ b/src/lxc/tools/lxc_checkpoint.c
@@ -198,21 +198,21 @@ int main(int argc, char *argv[])
 	bool ret;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		exit(1);
+		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		exit(1);
+		exit(EXIT_FAILURE);
 
 	lxc_log_options_no_override();
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c) {
 		fprintf(stderr, "System error loading %s\n", my_args.name);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (my_args.rcfile) {
@@ -220,26 +220,26 @@ int main(int argc, char *argv[])
 		if (!c->load_config(c, my_args.rcfile)) {
 			fprintf(stderr, "Failed to load rcfile\n");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		c->configfile = strdup(my_args.rcfile);
 		if (!c->configfile) {
 			fprintf(stderr, "Out of memory setting new config filename\n");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (!c->is_defined(c)) {
 		fprintf(stderr, "%s is not defined\n", my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 
@@ -248,5 +248,8 @@ int main(int argc, char *argv[])
 	else
 		ret = checkpoint(c);
 
-	return !ret;
+	if (!ret)
+		exit(EXIT_FAILURE);
+
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_config.c b/src/lxc/tools/lxc_config.c
index d146ad8..998fa32 100644
--- a/src/lxc/tools/lxc_config.c
+++ b/src/lxc/tools/lxc_config.c
@@ -73,9 +73,9 @@ int main(int argc, char *argv[])
 				printf("%s\n", value);
 			else
 				printf("%s is not set.\n", argv[1]);
-			exit(0);
+			exit(EXIT_SUCCESS);
 		}
 	}
 	printf("Unknown configuration item: %s\n", argv[1]);
-	exit(1);
+	exit(EXIT_FAILURE);
 }
diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c
index 829c908..5d8dd4d 100644
--- a/src/lxc/tools/lxc_console.c
+++ b/src/lxc/tools/lxc_console.c
@@ -146,5 +146,5 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 	lxc_container_put(c);
-	return EXIT_SUCCESS;
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index 49af062..9cd7614 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -106,7 +106,7 @@ int main(int argc, char *argv[])
 
 	if (geteuid() != 0) {
 		ERROR("%s must be run as root", argv[0]);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
@@ -184,9 +184,9 @@ int main(int argc, char *argv[])
 		ERROR("Error: Please use add or del (Please see --help output)");
 		goto err1;
 	}
-	exit(0);
+	exit(EXIT_SUCCESS);
 err1:
 	lxc_container_put(c);
 err:
-	exit(ret);
+	exit(EXIT_FAILURE);
 }
diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c
index c7c5096..13fa799 100644
--- a/src/lxc/tools/lxc_execute.c
+++ b/src/lxc/tools/lxc_execute.c
@@ -102,14 +102,14 @@ int main(int argc, char *argv[])
 	lxc_list_init(&defines);
 
 	if (lxc_caps_init())
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	/* rcfile is specified in the cli option */
@@ -121,7 +121,7 @@ int main(int argc, char *argv[])
 		rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name);
 		if (rc == -1) {
 			SYSERROR("failed to allocate memory");
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 
 		/* container configuration does not exist */
@@ -134,16 +134,16 @@ int main(int argc, char *argv[])
 	conf = lxc_conf_init();
 	if (!conf) {
 		ERROR("failed to initialize configuration");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (rcfile && lxc_config_read(rcfile, conf, NULL)) {
 		ERROR("failed to read configuration file");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (lxc_config_define_load(&defines, conf))
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (my_args.uid)
 		conf->init_uid = my_args.uid;
@@ -156,6 +156,6 @@ int main(int argc, char *argv[])
 	lxc_conf_free(conf);
 
 	if (ret < 0)
-		return 1;
-	return ret;
+		exit(EXIT_FAILURE);
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_freeze.c b/src/lxc/tools/lxc_freeze.c
index ac0802e..33445c8 100644
--- a/src/lxc/tools/lxc_freeze.c
+++ b/src/lxc/tools/lxc_freeze.c
@@ -59,20 +59,20 @@ int main(int argc, char *argv[])
 	struct lxc_container *c;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		exit(1);
+		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		exit(1);
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c) {
 		ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (my_args.rcfile) {
@@ -80,29 +80,29 @@ int main(int argc, char *argv[])
 		if (!c->load_config(c, my_args.rcfile)) {
 			ERROR("Failed to load rcfile");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		c->configfile = strdup(my_args.rcfile);
 		if (!c->configfile) {
 			ERROR("Out of memory setting new config filename");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
 	if (!c->may_control(c)) {
 		ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (!c->freeze(c)) {
 		ERROR("Failed to freeze %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	lxc_container_put(c);
 
-	exit(0);
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_info.c b/src/lxc/tools/lxc_info.c
index 08c698d..2888537 100644
--- a/src/lxc/tools/lxc_info.c
+++ b/src/lxc/tools/lxc_info.c
@@ -396,18 +396,18 @@ int main(int argc, char *argv[])
 	int ret = EXIT_FAILURE;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return ret;
+		exit(ret);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return ret;
+		exit(ret);
 	lxc_log_options_no_override();
 
 	if (print_info(my_args.name, my_args.lxcpath[0]) == 0)
 		ret = EXIT_SUCCESS;
 
-	return ret;
+	exit(ret);
 }
diff --git a/src/lxc/tools/lxc_monitor.c b/src/lxc/tools/lxc_monitor.c
index 797ae8b..d9da9b8 100644
--- a/src/lxc/tools/lxc_monitor.c
+++ b/src/lxc/tools/lxc_monitor.c
@@ -92,17 +92,17 @@ int main(int argc, char *argv[])
 	nfds_t nfds;
 	int len, rc_main, rc_snp, i;
 
-	rc_main = 0;
+	rc_main = EXIT_FAILURE;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(rc_main);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(rc_main);
 	lxc_log_options_no_override();
 
 	if (quit_monitord) {
@@ -124,32 +124,29 @@ int main(int argc, char *argv[])
 			}
 			close(fd);
 		}
-		return ret;
+		exit(ret);
 	}
 
 	len = strlen(my_args.name) + 3;
 	regexp = malloc(len + 3);
 	if (!regexp) {
 		ERROR("failed to allocate memory");
-		return 1;
+		exit(rc_main);
 	}
 	rc_snp = snprintf(regexp, len, "^%s$", my_args.name);
 	if (rc_snp < 0 || rc_snp >= len) {
 		ERROR("Name too long");
-		rc_main = 1;
 		goto error;
 	}
 
 	if (regcomp(&preg, regexp, REG_NOSUB|REG_EXTENDED)) {
 		ERROR("failed to compile the regex '%s'", my_args.name);
-		rc_main = 1;
 		goto error;
 	}
 
 	fds = malloc(my_args.lxcpath_cnt * sizeof(struct pollfd));
 	if (!fds) {
 		SYSERROR("out of memory");
-		rc_main = -1;
 		goto cleanup;
 	}
 
@@ -162,7 +159,6 @@ int main(int argc, char *argv[])
 		fd = lxc_monitor_open(my_args.lxcpath[i]);
 		if (fd < 0) {
 			close_fds(fds, i);
-			rc_main = 1;
 			goto cleanup;
 		}
 		fds[i].fd = fd;
@@ -174,7 +170,6 @@ int main(int argc, char *argv[])
 
 	for (;;) {
 		if (lxc_monitor_read_fdset(fds, nfds, &msg, -1) < 0) {
-			rc_main = 1;
 			goto close_and_clean;
 		}
 
@@ -196,6 +191,7 @@ int main(int argc, char *argv[])
 			break;
 		}
 	}
+	rc_main = 0;
 
 close_and_clean:
 	close_fds(fds, nfds);
@@ -207,5 +203,5 @@ int main(int argc, char *argv[])
 error:
 	free(regexp);
 
-	return rc_main;
+	exit(rc_main);
 }
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 6b942ac..25d8f19 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -203,7 +203,7 @@ Options :\n\
 
 int main(int argc, char *argv[])
 {
-	int err = 1;
+	int err = EXIT_FAILURE;
 	struct lxc_conf *conf;
 	char *const *args;
 	char *rcfile = NULL;
@@ -216,10 +216,10 @@ int main(int argc, char *argv[])
 	lxc_list_init(&defines);
 
 	if (lxc_caps_init())
-		return err;
+		exit(err);
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return err;
+		exit(err);
 
 	if (!my_args.argc)
 		args = default_args;
@@ -228,7 +228,7 @@ int main(int argc, char *argv[])
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return err;
+		exit(err);
 	lxc_log_options_no_override();
 
 	const char *lxcpath = my_args.lxcpath[0];
@@ -245,13 +245,13 @@ int main(int argc, char *argv[])
 		c = lxc_container_new(my_args.name, lxcpath);
 		if (!c) {
 			ERROR("Failed to create lxc_container");
-			return err;
+			exit(err);
 		}
 		c->clear_config(c);
 		if (!c->load_config(c, rcfile)) {
 			ERROR("Failed to load rcfile");
 			lxc_container_put(c);
-			return err;
+			exit(err);
 		}
 	} else {
 		int rc;
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
 		rc = asprintf(&rcfile, "%s/%s/config", lxcpath, my_args.name);
 		if (rc == -1) {
 			SYSERROR("failed to allocate memory");
-			return err;
+			exit(err);
 		}
 		INFO("using rcfile %s", rcfile);
 
@@ -271,7 +271,7 @@ int main(int argc, char *argv[])
 		c = lxc_container_new(my_args.name, lxcpath);
 		if (!c) {
 			ERROR("Failed to create lxc_container");
-			return err;
+			exit(err);
 		}
 	}
 
@@ -336,9 +336,9 @@ int main(int argc, char *argv[])
 		c->want_close_all_fds(c, true);
 
 	if (args == default_args)
-		err = c->start(c, 0, NULL) ? 0 : 1;
+		err = c->start(c, 0, NULL) ? EXIT_SUCCESS : EXIT_FAILURE;
 	else
-		err = c->start(c, 0, args) ? 0 : 1;
+		err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE;
 
 	if (err) {
 		ERROR("The container failed to start.");
@@ -348,10 +348,10 @@ int main(int argc, char *argv[])
 		      "--logfile and --logpriority options.");
 		err = c->error_num;
 		lxc_container_put(c);
-		return err;
+		exit(err);
 	}
 
 out:
 	lxc_container_put(c);
-	return err;
+	exit(err);
 }
diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index cb7cfe2..498aac1 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -143,14 +143,14 @@ int main(int argc, char *argv[])
 {
 	struct lxc_container *c;
 	bool s;
-	int ret = 1;
+	int ret = EXIT_FAILURE;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(ret);
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(ret);
 	lxc_log_options_no_override();
 
 	/* Set default timeout */
@@ -170,33 +170,35 @@ int main(int argc, char *argv[])
 	/* some checks */
 	if (!my_args.hardstop && my_args.timeout < -1) {
 		fprintf(stderr, "invalid timeout\n");
-		return 1;
+		exit(ret);
 	}
 
 	if (my_args.hardstop && my_args.nokill) {
 		fprintf(stderr, "-k can't be used with --nokill\n");
-		return 1;
+		exit(ret);
 	}
 
 	if (my_args.hardstop && my_args.reboot) {
 		fprintf(stderr, "-k can't be used with -r\n");
-		return 1;
+		exit(ret);
 	}
 
 	if (my_args.hardstop && my_args.timeout) {
 		fprintf(stderr, "-k doesn't allow timeouts\n");
-		return 1;
+		exit(ret);
 	}
 
 	if (my_args.nolock && !my_args.hardstop) {
 		fprintf(stderr, "--nolock may only be used with -k\n");
-		return 1;
+		exit(ret);
 	}
 
 	/* shortcut - if locking is bogus, we should be able to kill
 	 * containers at least */
-	if (my_args.nolock)
-		return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
+	if (my_args.nolock) {
+		ret = lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
+		exit(ret);
+	}
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c) {
@@ -224,19 +226,19 @@ int main(int argc, char *argv[])
 
 	if (!c->is_running(c)) {
 		fprintf(stderr, "%s is not running\n", c->name);
-		ret = 2;
+		ret = EXIT_FAILURE;
 		goto out;
 	}
 
 	/* kill */
 	if (my_args.hardstop) {
-		ret = c->stop(c) ? 0 : 1;
+		ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE;
 		goto out;
 	}
 
 	/* reboot */
 	if (my_args.reboot) {
-		ret = do_reboot_and_check(&my_args, c);
+		ret = do_reboot_and_check(&my_args, c) < 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 		goto out;
 	}
 
@@ -244,17 +246,16 @@ int main(int argc, char *argv[])
 	s = c->shutdown(c, my_args.timeout);
 	if (!s) {
 		if (my_args.timeout == 0)
-			ret = 0;
+			ret = EXIT_SUCCESS;
 		else if (my_args.nokill)
-			ret = 1;
+			ret = EXIT_FAILURE;
 		else
-			ret = c->stop(c) ? 0 : 1;
-	} else
-		ret = 0;
+			ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE;
+	} else {
+		ret = EXIT_SUCCESS;
+	}
 
 out:
 	lxc_container_put(c);
-	if (ret < 0)
-		return 1;
-	return ret;
+	exit(ret);
 }
diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c
index 47deddd..faeab33 100644
--- a/src/lxc/tools/lxc_top.c
+++ b/src/lxc/tools/lxc_top.c
@@ -506,5 +506,5 @@ int main(int argc, char *argv[])
 err1:
 	lxc_mainloop_close(&descr);
 out:
-	return ret;
+	exit(EXIT_FAILURE);
 }
diff --git a/src/lxc/tools/lxc_unfreeze.c b/src/lxc/tools/lxc_unfreeze.c
index 24faf5e..539654d 100644
--- a/src/lxc/tools/lxc_unfreeze.c
+++ b/src/lxc/tools/lxc_unfreeze.c
@@ -57,26 +57,26 @@ int main(int argc, char *argv[])
 	struct lxc_container *c;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		exit(1);
+		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		exit(1);
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c) {
 		ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (!c->may_control(c)) {
 		ERROR("Insufficent privileges to control %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (my_args.rcfile) {
@@ -84,23 +84,23 @@ int main(int argc, char *argv[])
 		if (!c->load_config(c, my_args.rcfile)) {
 			ERROR("Failed to load rcfile");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		c->configfile = strdup(my_args.rcfile);
 		if (!c->configfile) {
 			ERROR("Out of memory setting new config filename");
 			lxc_container_put(c);
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
 	if (!c->unfreeze(c)) {
 		ERROR("Failed to unfreeze %s:%s", my_args.lxcpath[0], my_args.name);
 		lxc_container_put(c);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	lxc_container_put(c);
 
-	exit(0);
+	exit(EXIT_SUCCESS);
 }
diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
index e629525..646c97f 100644
--- a/src/lxc/tools/lxc_unshare.c
+++ b/src/lxc/tools/lxc_unshare.c
@@ -197,21 +197,21 @@ int main(int argc, char *argv[])
 			break;
 		case 'u':
 			if (!lookup_user(optarg, &uid))
-				return 1;
+				exit(EXIT_FAILURE);
 			start_arg.setuid = true;
 		}
 	}
 
 	if (argv[optind] == NULL) {
 		ERROR("a command to execute in the new namespace is required");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	args = &argv[optind];
 
 	ret = lxc_caps_init();
 	if (ret)
-		return 1;
+		exit(EXIT_FAILURE);
 
 	ret = lxc_fill_namespace_flags(namespaces, &flags);
 	if (ret)
@@ -219,23 +219,23 @@ int main(int argc, char *argv[])
 
 	if (!(flags & CLONE_NEWNET) && my_iflist) {
 		ERROR("-i <interfacename> needs -s NETWORK option");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (!(flags & CLONE_NEWUTS) && start_arg.want_hostname) {
 		ERROR("-H <hostname> needs -s UTSNAME option");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (!(flags & CLONE_NEWNS) && start_arg.want_default_mounts) {
 		ERROR("-M needs -s MOUNT option");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	pid = lxc_clone(do_start, &start_arg, flags);
 	if (pid < 0) {
 		ERROR("failed to clone");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (my_iflist) {
@@ -250,8 +250,9 @@ int main(int argc, char *argv[])
 
 	if (waitpid(pid, &status, 0) < 0) {
 		ERROR("failed to wait for '%d'", pid);
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
-	return  lxc_error_set_and_log(pid, status);
+	/* Call exit() directly on this function because it retuns an exit code. */
+	exit(lxc_error_set_and_log(pid, status));
 }
diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c
index 6745ac3..6ba9d1e 100644
--- a/src/lxc/tools/lxc_usernsexec.c
+++ b/src/lxc/tools/lxc_usernsexec.c
@@ -282,7 +282,7 @@ int main(int argc, char *argv[])
 		ret = readlink("/proc/self/fd/0", ttyname0, sizeof(ttyname0));
 		if (ret < 0) {
 			perror("unable to open stdin.");
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		ret = readlink("/proc/self/fd/1", ttyname1, sizeof(ttyname1));
 		if (ret < 0) {
@@ -310,7 +310,7 @@ int main(int argc, char *argv[])
 	if (lxc_list_empty(&active_map)) {
 		if (find_default_map()) {
 			fprintf(stderr, "You have no allocated subuids or subgids\n");
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 	}
 
@@ -323,7 +323,7 @@ int main(int argc, char *argv[])
 
 	if (pipe(pipe1) < 0 || pipe(pipe2) < 0) {
 		perror("pipe");
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 	if ((pid = fork()) == 0) {
 		// Child.
@@ -342,15 +342,15 @@ int main(int argc, char *argv[])
 		buf[0] = '1';
 		if (write(pipe1[1], buf, 1) < 1) {
 			perror("write pipe");
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		if (read(pipe2[0], buf, 1) < 1) {
 			perror("read pipe");
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 		if (buf[0] != '1') {
 			fprintf(stderr, "parent had an error, child exiting\n");
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 
 		close(pipe1[1]);
@@ -362,7 +362,7 @@ int main(int argc, char *argv[])
 	close(pipe2[0]);
 	if (read(pipe1[0], buf, 1) < 1) {
 		perror("read pipe");
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	buf[0] = '1';
@@ -373,12 +373,12 @@ int main(int argc, char *argv[])
 	}
 	if (write(pipe2[1], buf, 1) < 0) {
 		perror("write to pipe");
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if ((ret = waitpid(pid, &status, __WALL)) < 0) {
 		printf("waitpid() returns %d, errno %d\n", ret, errno);
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	exit(WEXITSTATUS(status));
diff --git a/src/lxc/tools/lxc_wait.c b/src/lxc/tools/lxc_wait.c
index 61fd869..de95696 100644
--- a/src/lxc/tools/lxc_wait.c
+++ b/src/lxc/tools/lxc_wait.c
@@ -85,24 +85,24 @@ int main(int argc, char *argv[])
 	struct lxc_container *c;
 
 	if (lxc_arguments_parse(&my_args, argc, argv))
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (!my_args.log_file)
 		my_args.log_file = "none";
 
 	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
 			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
-		return 1;
+		exit(EXIT_FAILURE);
 	lxc_log_options_no_override();
 
 	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
 	if (!c)
-		return 1;
+		exit(EXIT_FAILURE);
 
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
 		lxc_container_put(c);
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	if (my_args.rcfile) {
@@ -110,19 +110,19 @@ int main(int argc, char *argv[])
 		if (!c->load_config(c, my_args.rcfile)) {
 			fprintf(stderr, "Failed to load rcfile\n");
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 		c->configfile = strdup(my_args.rcfile);
 		if (!c->configfile) {
 			fprintf(stderr, "Out of memory setting new config filename\n");
 			lxc_container_put(c);
-			return 1;
+			exit(EXIT_FAILURE);
 		}
 	}
 
 	if (!c->wait(c, my_args.states, my_args.timeout)) {
 		lxc_container_put(c);
-		return 1;
+		exit(EXIT_FAILURE);
 	}
-	return 0;
+	exit(EXIT_SUCCESS);
 }

From d61666a3c3d3925dab671947d55a7af6a2448bc3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Thu, 18 Aug 2016 11:11:34 +0200
Subject: [PATCH 117/334] tools: unify exit() calls outside of main()

This also changes the help exit status of lxc-unshare and lxc-usernsexec. So
far they did exit(EXIT_FAILURE) whereas all other tools do exit(EXIT_SUCCESS).
Let's align them with the rest of the tools. This should be safe to do.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/tools/lxc_clone.c      |  2 +-
 src/lxc/tools/lxc_config.c     |  4 ++--
 src/lxc/tools/lxc_device.c     |  6 +++---
 src/lxc/tools/lxc_unshare.c    | 10 +++++-----
 src/lxc/tools/lxc_usernsexec.c |  2 +-
 5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/lxc/tools/lxc_clone.c b/src/lxc/tools/lxc_clone.c
index 6bd2226..e7ecd0c 100644
--- a/src/lxc/tools/lxc_clone.c
+++ b/src/lxc/tools/lxc_clone.c
@@ -89,7 +89,7 @@ static void usage(const char *me)
 	printf("  -p: use container orig from custom lxcpath\n");
 	printf("  -P: create container new in custom lxcpath\n");
 	printf("  -R: rename existing container\n");
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 static struct option options[] = {
diff --git a/src/lxc/tools/lxc_config.c b/src/lxc/tools/lxc_config.c
index 998fa32..c26b1a0 100644
--- a/src/lxc/tools/lxc_config.c
+++ b/src/lxc/tools/lxc_config.c
@@ -45,7 +45,7 @@ static void usage(char *me)
 {
 	printf("Usage: %s -l: list all available configuration items\n", me);
 	printf("       %s item: print configuration item\n", me);
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 static void list_config_items(void)
@@ -54,7 +54,7 @@ static void list_config_items(void)
 
 	for (i = &items[0]; i->name; i++)
 		printf("%s\n", i->name);
-	exit(0);
+	exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index 9cd7614..abf52b9 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -66,7 +66,7 @@ static bool is_interface(const char* dev_name, pid_t pid)
 
 	if (p < 0) {
 		SYSERROR("failed to fork task.");
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (p == 0) {
@@ -86,10 +86,10 @@ static bool is_interface(const char* dev_name, pid_t pid)
 		/* Iterate through the interfaces */
 		for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
 			if (strcmp(tempIfAddr->ifa_name, dev_name) == 0) {
-				exit(0);
+				exit(EXIT_SUCCESS);
 			}
 		}
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	if (wait_for_pid(p) == 0) {
diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
index 646c97f..6c9423f 100644
--- a/src/lxc/tools/lxc_unshare.c
+++ b/src/lxc/tools/lxc_unshare.c
@@ -77,7 +77,7 @@ static void usage(char *cmd)
 	fprintf(stderr, "\t -H <hostname>: Set the hostname in the container\n");
 	fprintf(stderr, "\t -d           : Daemonize (do not wait for container to exit)\n");
 	fprintf(stderr, "\t -M           : reMount default fs inside container (/proc /dev/shm /dev/mqueue)\n");
-	_exit(1);
+	_exit(EXIT_SUCCESS);
 }
 
 static bool lookup_user(const char *optarg, uid_t *uid)
@@ -134,13 +134,13 @@ static int do_start(void *arg)
 	if ((flags & CLONE_NEWUTS) && want_hostname)
 		if (sethostname(want_hostname, strlen(want_hostname)) < 0) {
 			ERROR("failed to set hostname %s: %s", want_hostname, strerror(errno));
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
 
 	// Setuid is useful even without a new user id space
 	if (start_arg->setuid && setuid(uid)) {
 		ERROR("failed to set uid %d: %s", uid, strerror(errno));
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	execvp(args[0], args);
@@ -177,7 +177,7 @@ int main(int argc, char *argv[])
 		case 'i':
 			if (!(tmpif = malloc(sizeof(*tmpif)))) {
 				perror("malloc");
-				exit(1);
+				exit(EXIT_FAILURE);
 			}
 			tmpif->mi_ifname = optarg;
 			tmpif->mi_next = my_iflist;
@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
 	}
 
 	if (daemonize)
-		exit(0);
+		exit(EXIT_SUCCESS);
 
 	if (waitpid(pid, &status, 0) < 0) {
 		ERROR("failed to wait for '%d'", pid);
diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c
index 6ba9d1e..d4c730a 100644
--- a/src/lxc/tools/lxc_usernsexec.c
+++ b/src/lxc/tools/lxc_usernsexec.c
@@ -71,7 +71,7 @@ static void usage(const char *name)
 	printf("  Note: This program uses newuidmap(2) and newgidmap(2).\n");
 	printf("        As such, /etc/subuid and /etc/subgid must grant the\n");
 	printf("        calling user permission to use the mapped ranges\n");
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 static void opentty(const char * tty, int which) {

From 5837b986d840a34e1e185fa4b88369e00bb66315 Mon Sep 17 00:00:00 2001
From: James Cowgill <james410 at cowgill.org.uk>
Date: Fri, 12 Aug 2016 15:54:14 +0000
Subject: [PATCH 118/334] utils: Add mips signalfd syscall numbers

Signed-off-by: James Cowgill <james410 at cowgill.org.uk>
---
 src/lxc/utils.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index b541e07..98b4e13 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -117,6 +117,12 @@ struct signalfd_siginfo
 #      define __NR_signalfd4 322
 #    elif __arm__
 #      define __NR_signalfd4 355
+#    elif __mips__ && _MIPS_SIM == _ABIO32
+#      define __NR_signalfd4 4324
+#    elif __mips__ && _MIPS_SIM == _ABI64
+#      define __NR_signalfd4 5283
+#    elif __mips__ && _MIPS_SIM == _ABIN32
+#      define __NR_signalfd4 6287
 #    endif
 #endif
 
@@ -132,6 +138,12 @@ struct signalfd_siginfo
 #      define __NR_signalfd 316
 #    elif __arm__
 #      define __NR_signalfd 349
+#    elif __mips__ && _MIPS_SIM == _ABIO32
+#      define __NR_signalfd 4317
+#    elif __mips__ && _MIPS_SIM == _ABI64
+#      define __NR_signalfd 5276
+#    elif __mips__ && _MIPS_SIM == _ABIN32
+#      define __NR_signalfd 6280
 #    endif
 #endif
 

From 39df19c4f72408f9961cd05e8a31a3a91e477896 Mon Sep 17 00:00:00 2001
From: James Cowgill <james410 at cowgill.org.uk>
Date: Mon, 15 Aug 2016 16:09:44 +0000
Subject: [PATCH 119/334] seccomp: Implement MIPS seccomp handling

MIPS processors implement 3 ABIs: o32, n64 and n32 (similar to x32). The kernel
treats each ABI separately so syscalls disallowed on "all" arches should be
added to all three seccomp sets. This is implemented by expanding compat_arch
and compat_ctx to accept two compat architectures.

After this, the MIPS hostarch detection code and config section code is added.

Signed-off-by: James Cowgill <james410 at cowgill.org.uk>
---
 src/lxc/seccomp.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 123 insertions(+), 18 deletions(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 451e315..0374eca 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -125,9 +125,23 @@ enum lxc_hostarch_t {
 	lxc_seccomp_arch_ppc64,
 	lxc_seccomp_arch_ppc64le,
 	lxc_seccomp_arch_ppc,
+	lxc_seccomp_arch_mips,
+	lxc_seccomp_arch_mips64,
+	lxc_seccomp_arch_mips64n32,
+	lxc_seccomp_arch_mipsel,
+	lxc_seccomp_arch_mipsel64,
+	lxc_seccomp_arch_mipsel64n32,
 	lxc_seccomp_arch_unknown = 999,
 };
 
+#ifdef __MIPSEL__
+# define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel
+# define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64
+#else
+# define MIPS_ARCH_O32 lxc_seccomp_arch_mips
+# define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
+#endif
+
 int get_hostarch(void)
 {
 	struct utsname uts;
@@ -149,6 +163,10 @@ int get_hostarch(void)
 		return lxc_seccomp_arch_ppc64;
 	else if (strncmp(uts.machine, "ppc", 3) == 0)
 		return lxc_seccomp_arch_ppc;
+	else if (strncmp(uts.machine, "mips64", 6) == 0)
+		return MIPS_ARCH_N64;
+	else if (strncmp(uts.machine, "mips", 4) == 0)
+		return MIPS_ARCH_O32;
 	return lxc_seccomp_arch_unknown;
 }
 
@@ -174,6 +192,14 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_
 #ifdef SCMP_ARCH_PPC
 	case lxc_seccomp_arch_ppc: arch = SCMP_ARCH_PPC; break;
 #endif
+#ifdef SCMP_ARCH_MIPS
+	case lxc_seccomp_arch_mips: arch = SCMP_ARCH_MIPS; break;
+	case lxc_seccomp_arch_mips64: arch = SCMP_ARCH_MIPS64; break;
+	case lxc_seccomp_arch_mips64n32: arch = SCMP_ARCH_MIPS64N32; break;
+	case lxc_seccomp_arch_mipsel: arch = SCMP_ARCH_MIPSEL; break;
+	case lxc_seccomp_arch_mipsel64: arch = SCMP_ARCH_MIPSEL64; break;
+	case lxc_seccomp_arch_mipsel64n32: arch = SCMP_ARCH_MIPSEL64N32; break;
+#endif
 	default: return NULL;
 	}
 
@@ -260,12 +286,12 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 {
 	char *p;
 	int ret;
-	scmp_filter_ctx compat_ctx = NULL;
+	scmp_filter_ctx compat_ctx[2] = { NULL, NULL };
 	bool blacklist = false;
 	uint32_t default_policy_action = -1, default_rule_action = -1, action;
 	enum lxc_hostarch_t native_arch = get_hostarch(),
 			    cur_rule_arch = native_arch;
-	uint32_t compat_arch = SCMP_ARCH_NATIVE;
+	uint32_t compat_arch[2] = { SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE };
 
 	if (strncmp(line, "blacklist", 9) == 0)
 		blacklist = true;
@@ -295,27 +321,49 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 
 	if (native_arch == lxc_seccomp_arch_amd64) {
 		cur_rule_arch = lxc_seccomp_arch_all;
-		compat_arch = SCMP_ARCH_X86;
-		compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
+		compat_arch[0] = SCMP_ARCH_X86;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_i386,
 				default_policy_action);
-		if (!compat_ctx)
+		if (!compat_ctx[0])
 			goto bad;
 #ifdef SCMP_ARCH_PPC
 	} else if (native_arch == lxc_seccomp_arch_ppc64) {
 		cur_rule_arch = lxc_seccomp_arch_all;
-		compat_arch = SCMP_ARCH_PPC;
-		compat_ctx = get_new_ctx(lxc_seccomp_arch_ppc,
+		compat_arch[0] = SCMP_ARCH_PPC;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_ppc,
 				default_policy_action);
-		if (!compat_ctx)
+		if (!compat_ctx[0])
 			goto bad;
 #endif
 #ifdef SCMP_ARCH_ARM
 	} else if (native_arch == lxc_seccomp_arch_arm64) {
 		cur_rule_arch = lxc_seccomp_arch_all;
-		compat_arch = SCMP_ARCH_ARM;
-		compat_ctx = get_new_ctx(lxc_seccomp_arch_arm,
+		compat_arch[0] = SCMP_ARCH_ARM;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_arm,
+				default_policy_action);
+		if (!compat_ctx[0])
+			goto bad;
+#endif
+#ifdef SCMP_ARCH_MIPS
+	} else if (native_arch == lxc_seccomp_arch_mips64) {
+		cur_rule_arch = lxc_seccomp_arch_all;
+		compat_arch[0] = SCMP_ARCH_MIPS;
+		compat_arch[1] = SCMP_ARCH_MIPS64N32;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mips,
+				default_policy_action);
+		compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mips64n32,
+				default_policy_action);
+		if (!compat_ctx[0] || !compat_ctx[1])
+			goto bad;
+	} else if (native_arch == lxc_seccomp_arch_mipsel64) {
+		cur_rule_arch = lxc_seccomp_arch_all;
+		compat_arch[0] = SCMP_ARCH_MIPSEL;
+		compat_arch[1] = SCMP_ARCH_MIPSEL64N32;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_mipsel,
 				default_policy_action);
-		if (!compat_ctx)
+		compat_ctx[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32,
+				default_policy_action);
+		if (!compat_ctx[0] || !compat_ctx[1])
 			goto bad;
 #endif
 	}
@@ -413,6 +461,53 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 				cur_rule_arch = lxc_seccomp_arch_ppc;
 			}
 #endif
+#ifdef SCMP_ARCH_MIPS
+			else if (strcmp(line, "[mips64]") == 0 ||
+					strcmp(line, "[MIPS64]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mips64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mips64;
+			} else if (strcmp(line, "[mips64n32]") == 0 ||
+					strcmp(line, "[MIPS64N32]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mips64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mips64n32;
+			} else if (strcmp(line, "[mips]") == 0 ||
+					strcmp(line, "[MIPS]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mips &&
+						native_arch != lxc_seccomp_arch_mips64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mips;
+			} else if (strcmp(line, "[mipsel64]") == 0 ||
+					strcmp(line, "[MIPSEL64]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mipsel64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mipsel64;
+			} else if (strcmp(line, "[mipsel64n32]") == 0 ||
+					strcmp(line, "[MIPSEL64N32]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mipsel64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mipsel64n32;
+			} else if (strcmp(line, "[mipsel]") == 0 ||
+					strcmp(line, "[MIPSEL]") == 0) {
+				if (native_arch != lxc_seccomp_arch_mipsel &&
+						native_arch != lxc_seccomp_arch_mipsel64) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_mipsel;
+			}
+#endif
 			else
 				goto bad_arch;
 
@@ -432,14 +527,18 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 
 		if (cur_rule_arch == native_arch ||
 		    cur_rule_arch == lxc_seccomp_arch_native ||
-		    compat_arch == SCMP_ARCH_NATIVE) {
+		    compat_arch[0] == SCMP_ARCH_NATIVE) {
 			INFO("Adding native rule for %s action %d", line, action);
 			if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
 				goto bad_rule;
 		}
 		else if (cur_rule_arch != lxc_seccomp_arch_all) {
+			int arch_index =
+				cur_rule_arch == lxc_seccomp_arch_mips64n32 ||
+				cur_rule_arch == lxc_seccomp_arch_mipsel64n32 ? 1 : 0;
+
 			INFO("Adding compat-only rule for %s action %d", line, action);
-			if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
+			if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], action))
 				goto bad_rule;
 		}
 		else {
@@ -447,14 +546,18 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 			if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
 				goto bad_rule;
 			INFO("Adding compat rule for %s action %d", line, action);
-			if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
+			if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], action))
+				goto bad_rule;
+			if (compat_arch[1] != SCMP_ARCH_NATIVE &&
+				!do_resolve_add_rule(compat_arch[1], line, compat_ctx[1], action))
 				goto bad_rule;
 		}
 	}
 
-	if (compat_ctx) {
+	if (compat_ctx[0]) {
 		INFO("Merging in the compat seccomp ctx into the main one");
-		if (seccomp_merge(conf->seccomp_ctx, compat_ctx) != 0) {
+		if (seccomp_merge(conf->seccomp_ctx, compat_ctx[0]) != 0 ||
+			(compat_ctx[1] != NULL && seccomp_merge(conf->seccomp_ctx, compat_ctx[1]) != 0)) {
 			ERROR("Error merging compat seccomp contexts");
 			goto bad;
 		}
@@ -466,8 +569,10 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 	ERROR("Unsupported arch: %s", line);
 bad_rule:
 bad:
-	if (compat_ctx)
-		seccomp_release(compat_ctx);
+	if (compat_ctx[0])
+		seccomp_release(compat_ctx[0]);
+	if (compat_ctx[1])
+		seccomp_release(compat_ctx[1]);
 	return -1;
 }
 #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */

From 24cbc4434c8c4b11b356cc399182ad8e155a9225 Mon Sep 17 00:00:00 2001
From: James Cowgill <james410 at cowgill.org.uk>
Date: Thu, 18 Aug 2016 14:27:35 +0100
Subject: [PATCH 120/334] seccomp: Add mips and mips64 entries to
 lxc_config_parse_arch

Fixes "unsupported personality" warnings when starting containers.

Signed-off-by: James Cowgill <james410 at cowgill.org.uk>
---
 src/lxc/confile.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 2cbf375..5235b3d 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -2059,9 +2059,13 @@ signed long lxc_config_parse_arch(const char *arch)
 		{ "i586", PER_LINUX32 },
 		{ "i686", PER_LINUX32 },
 		{ "athlon", PER_LINUX32 },
+		{ "mips", PER_LINUX32 },
+		{ "mipsel", PER_LINUX32 },
 		{ "linux64", PER_LINUX },
 		{ "x86_64", PER_LINUX },
 		{ "amd64", PER_LINUX },
+		{ "mips64", PER_LINUX },
+		{ "mips64el", PER_LINUX },
 	};
 	size_t len = sizeof(pername) / sizeof(pername[0]);
 

From 8f484e2fa0d56eb2412da5505de2703d2a192d73 Mon Sep 17 00:00:00 2001
From: James Cowgill <james410 at cowgill.org.uk>
Date: Thu, 18 Aug 2016 16:48:24 +0100
Subject: [PATCH 121/334] seccomp: fix strerror()

Signed-off-by: James Cowgill <james410 at cowgill.org.uk>
---
 src/lxc/seccomp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 0374eca..ec77c45 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -215,7 +215,7 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_
 	ret = seccomp_arch_add(ctx, arch);
 	if (ret != 0) {
 		ERROR("Seccomp error %d (%s) adding arch: %d", ret,
-				strerror(ret), (int)n_arch);
+				strerror(-ret), (int)n_arch);
 		seccomp_release(ctx);
 		return NULL;
 	}

From d8b7637476fe39fe6acd43f61a8e1c9a20bd72c0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 19 Aug 2016 11:15:30 +0200
Subject: [PATCH 122/334] confile: add more archs to lxc_config_parse_arch()

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/confile.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 5235b3d..9c250f3 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -2061,11 +2061,24 @@ signed long lxc_config_parse_arch(const char *arch)
 		{ "athlon", PER_LINUX32 },
 		{ "mips", PER_LINUX32 },
 		{ "mipsel", PER_LINUX32 },
+		{ "ppc", PER_LINUX32 },
+		{ "arm", PER_LINUX32 },
+		{ "armv7l", PER_LINUX32 },
+		{ "armhf", PER_LINUX32 },
+		{ "armel", PER_LINUX32 },
+		{ "powerpc", PER_LINUX32 },
 		{ "linux64", PER_LINUX },
 		{ "x86_64", PER_LINUX },
 		{ "amd64", PER_LINUX },
 		{ "mips64", PER_LINUX },
 		{ "mips64el", PER_LINUX },
+		{ "ppc64", PER_LINUX },
+		{ "ppc64le", PER_LINUX },
+		{ "ppc64el", PER_LINUX },
+		{ "powerpc64", PER_LINUX },
+		{ "s390x", PER_LINUX },
+		{ "aarch64", PER_LINUX },
+		{ "arm64", PER_LINUX },
 	};
 	size_t len = sizeof(pername) / sizeof(pername[0]);
 

From e68715eee02a9d7aaa7fb1c573e7d6411e7cdc11 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 19 Aug 2016 11:57:14 +0200
Subject: [PATCH 123/334] seccomp: add support for s390x

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/seccomp.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index ec77c45..28c4d62 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -131,6 +131,7 @@ enum lxc_hostarch_t {
 	lxc_seccomp_arch_mipsel,
 	lxc_seccomp_arch_mipsel64,
 	lxc_seccomp_arch_mipsel64n32,
+	lxc_seccomp_arch_s390x,
 	lxc_seccomp_arch_unknown = 999,
 };
 
@@ -167,6 +168,8 @@ int get_hostarch(void)
 		return MIPS_ARCH_N64;
 	else if (strncmp(uts.machine, "mips", 4) == 0)
 		return MIPS_ARCH_O32;
+	else if (strncmp(uts.machine, "s390x", 5) == 0)
+		return lxc_seccomp_arch_s390x;
 	return lxc_seccomp_arch_unknown;
 }
 
@@ -200,6 +203,9 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_
 	case lxc_seccomp_arch_mipsel64: arch = SCMP_ARCH_MIPSEL64; break;
 	case lxc_seccomp_arch_mipsel64n32: arch = SCMP_ARCH_MIPSEL64N32; break;
 #endif
+#ifdef SCMP_ARCH_S390X
+	case lxc_seccomp_arch_s390x: arch = SCMP_ARCH_S390X; break;
+#endif
 	default: return NULL;
 	}
 
@@ -366,6 +372,15 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 		if (!compat_ctx[0] || !compat_ctx[1])
 			goto bad;
 #endif
+#ifdef SCMP_ARCH_S390X
+	} else if (native_arch == lxc_seccomp_arch_s390x) {
+		cur_rule_arch = lxc_seccomp_arch_all;
+		compat_arch[0] = SCMP_ARCH_S390X;
+		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_s390x,
+				default_policy_action);
+		if (!compat_ctx[0])
+			goto bad;
+#endif
 	}
 
 	if (default_policy_action != SCMP_ACT_KILL) {
@@ -508,6 +523,16 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 				cur_rule_arch = lxc_seccomp_arch_mipsel;
 			}
 #endif
+#ifdef SCMP_ARCH_S390X
+			else if (strcmp(line, "[s390x]") == 0 ||
+					strcmp(line, "[S390X]") == 0) {
+				if (native_arch != lxc_seccomp_arch_s390x) {
+					cur_rule_arch = lxc_seccomp_arch_unknown;
+					continue;
+				}
+				cur_rule_arch = lxc_seccomp_arch_s390x;
+			}
+#endif
 			else
 				goto bad_arch;
 

From 4e2d66eab423794a589382a86109ad004b579bfc Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 19 Aug 2016 15:20:22 +0200
Subject: [PATCH 124/334] seccomp: remove double include and order includes

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/seccomp.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 28c4d62..3548725 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -22,17 +22,16 @@
  */
 
 #define _GNU_SOURCE
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <seccomp.h>
-#include <errno.h>
-#include <seccomp.h>
-#include <sys/utsname.h>
 #include <sys/mount.h>
+#include <sys/utsname.h>
 
 #include "config.h"
-#include "lxcseccomp.h"
 #include "log.h"
+#include "lxcseccomp.h"
 
 lxc_log_define(lxc_seccomp, lxc);
 

From 2b3a8ceb51ff4c14a143c59ae02df9f17318ce13 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 19 Aug 2016 18:53:02 +0200
Subject: [PATCH 125/334] seccomp: non functional changes

- log more errnos
- adapt coding style

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/seccomp.c | 144 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 76 insertions(+), 68 deletions(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 3548725..5069730 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -47,11 +47,11 @@ static int parse_config_v1(FILE *f, struct lxc_conf *conf)
 			return -1;
 		ret = seccomp_rule_add(
 #if HAVE_SCMP_FILTER_CTX
-			conf->seccomp_ctx,
+		    conf->seccomp_ctx,
 #endif
-			SCMP_ACT_ALLOW, nr, 0);
+		    SCMP_ACT_ALLOW, nr, 0);
 		if (ret < 0) {
-			ERROR("failed loading allow rule for %d", nr);
+			ERROR("Failed loading allow rule for %d.", nr);
 			return ret;
 		}
 	}
@@ -73,14 +73,15 @@ static uint32_t get_v2_default_action(char *line)
 {
 	uint32_t ret_action = -1;
 
-	while (*line == ' ') line++;
+	while (*line == ' ')
+		line++;
 	// after 'whitelist' or 'blacklist' comes default behavior
 	if (strncmp(line, "kill", 4) == 0)
 		ret_action = SCMP_ACT_KILL;
 	else if (strncmp(line, "errno", 5) == 0) {
 		int e;
-		if (sscanf(line+5, "%d", &e) != 1) {
-			ERROR("Bad errno value in %s", line);
+		if (sscanf(line + 5, "%d", &e) != 1) {
+			ERROR("Bad errno value in %s.", line);
 			return -2;
 		}
 		ret_action = SCMP_ACT_ERRNO(e);
@@ -146,7 +147,7 @@ int get_hostarch(void)
 {
 	struct utsname uts;
 	if (uname(&uts) < 0) {
-		SYSERROR("Failed to read host arch");
+		SYSERROR("Failed to read host arch.");
 		return -1;
 	}
 	if (strcmp(uts.machine, "i686") == 0)
@@ -209,18 +210,18 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_
 	}
 
 	if ((ctx = seccomp_init(default_policy_action)) == NULL) {
-		ERROR("Error initializing seccomp context");
+		ERROR("Error initializing seccomp context.");
 		return NULL;
 	}
 	if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)) {
-		ERROR("failed to turn off n-new-privs");
+		ERROR("Failed to turn off n-new-privs.");
 		seccomp_release(ctx);
 		return NULL;
 	}
 	ret = seccomp_arch_add(ctx, arch);
 	if (ret != 0) {
 		ERROR("Seccomp error %d (%s) adding arch: %d", ret,
-				strerror(-ret), (int)n_arch);
+		      strerror(-ret), (int)n_arch);
 		seccomp_release(ctx);
 		return NULL;
 	}
@@ -238,17 +239,22 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx,
 {
 	int nr, ret;
 
-	if (arch && seccomp_arch_exist(ctx, arch) != 0) {
-		ERROR("BUG: seccomp: rule and context arch do not match (arch %d)", arch);
+	ret = seccomp_arch_exist(ctx, arch);
+	if (arch && ret != 0) {
+		ERROR("BUG: Seccomp: rule and context arch do not match (arch "
+		      "%d): %s.",
+		      arch, strerror(-ret));
 		return false;
 	}
 
 	if (strncmp(line, "reject_force_umount", 19) == 0) {
-		INFO("Setting seccomp rule to reject force umounts\n");
+		INFO("Setting Seccomp rule to reject force umounts.");
 		ret = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(umount2),
 				1, SCMP_A1(SCMP_CMP_MASKED_EQ , MNT_FORCE , MNT_FORCE ));
 		if (ret < 0) {
-			ERROR("failed (%d) loading rule to reject force umount", ret);
+			ERROR("Failed (%d) loading rule to reject force "
+			      "umount: %s.",
+			      ret, strerror(-ret));
 			return false;
 		}
 		return true;
@@ -256,18 +262,19 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx,
 
 	nr = seccomp_syscall_resolve_name(line);
 	if (nr == __NR_SCMP_ERROR) {
-		WARN("Seccomp: failed to resolve syscall: %s", line);
-		WARN("This syscall will NOT be blacklisted");
+		WARN("Seccomp: failed to resolve syscall: %s.", line);
+		WARN("This syscall will NOT be blacklisted.");
 		return true;
 	}
 	if (nr < 0) {
-		WARN("Seccomp: got negative # for syscall: %s", line);
-		WARN("This syscall will NOT be blacklisted");
+		WARN("Seccomp: got negative for syscall: %d: %s.", nr, line);
+		WARN("This syscall will NOT be blacklisted.");
 		return true;
 	}
 	ret = seccomp_rule_add_exact(ctx, action, nr, 0);
 	if (ret < 0) {
-		ERROR("failed (%d) loading rule for %s (nr %d action %d)", ret, line, nr, action);
+		ERROR("Failed (%d) loading rule for %s (nr %d action %d): %s.",
+		      ret, line, nr, action, strerror(-ret));
 		return false;
 	}
 	return true;
@@ -291,22 +298,22 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 {
 	char *p;
 	int ret;
-	scmp_filter_ctx compat_ctx[2] = { NULL, NULL };
+	scmp_filter_ctx compat_ctx[2] = {NULL, NULL};
 	bool blacklist = false;
 	uint32_t default_policy_action = -1, default_rule_action = -1, action;
 	enum lxc_hostarch_t native_arch = get_hostarch(),
 			    cur_rule_arch = native_arch;
-	uint32_t compat_arch[2] = { SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE };
+	uint32_t compat_arch[2] = {SCMP_ARCH_NATIVE, SCMP_ARCH_NATIVE};
 
 	if (strncmp(line, "blacklist", 9) == 0)
 		blacklist = true;
 	else if (strncmp(line, "whitelist", 9) != 0) {
-		ERROR("Bad seccomp policy style: %s", line);
+		ERROR("Bad seccomp policy style: %s.", line);
 		return -1;
 	}
 
 	if ((p = strchr(line, ' '))) {
-		default_policy_action = get_v2_default_action(p+1);
+		default_policy_action = get_v2_default_action(p + 1);
 		if (default_policy_action == -2)
 			return -1;
 	}
@@ -385,11 +392,11 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 	if (default_policy_action != SCMP_ACT_KILL) {
 		ret = seccomp_reset(conf->seccomp_ctx, default_policy_action);
 		if (ret != 0) {
-			ERROR("Error re-initializing seccomp");
+			ERROR("Error re-initializing Seccomp.");
 			return -1;
 		}
 		if (seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0)) {
-			ERROR("failed to turn off n-new-privs");
+			ERROR("Failed to turn off n-new-privs.");
 			return -1;
 		}
 	}
@@ -405,7 +412,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 		if (line[0] == '[') {
 			// read the architecture for next set of rules
 			if (strcmp(line, "[x86]") == 0 ||
-					strcmp(line, "[X86]") == 0) {
+			    strcmp(line, "[X86]") == 0) {
 				if (native_arch != lxc_seccomp_arch_i386 &&
 						native_arch != lxc_seccomp_arch_amd64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
@@ -413,19 +420,19 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 				}
 				cur_rule_arch = lxc_seccomp_arch_i386;
 			} else if (strcmp(line, "[X86_64]") == 0 ||
-					strcmp(line, "[x86_64]") == 0) {
+				   strcmp(line, "[x86_64]") == 0) {
 				if (native_arch != lxc_seccomp_arch_amd64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
 				}
 				cur_rule_arch = lxc_seccomp_arch_amd64;
 			} else if (strcmp(line, "[all]") == 0 ||
-					strcmp(line, "[ALL]") == 0) {
+				   strcmp(line, "[ALL]") == 0) {
 				cur_rule_arch = lxc_seccomp_arch_all;
 			}
 #ifdef SCMP_ARCH_ARM
 			else if (strcmp(line, "[arm]") == 0 ||
-					strcmp(line, "[ARM]") == 0) {
+				 strcmp(line, "[ARM]") == 0) {
 				if (native_arch != lxc_seccomp_arch_arm &&
 						native_arch != lxc_seccomp_arch_arm64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
@@ -436,7 +443,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_AARCH64
 			else if (strcmp(line, "[arm64]") == 0 ||
-					strcmp(line, "[ARM64]") == 0) {
+				 strcmp(line, "[ARM64]") == 0) {
 				if (native_arch != lxc_seccomp_arch_arm64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
@@ -446,7 +453,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_PPC64LE
 			else if (strcmp(line, "[ppc64le]") == 0 ||
-					strcmp(line, "[PPC64LE]") == 0) {
+				 strcmp(line, "[PPC64LE]") == 0) {
 				if (native_arch != lxc_seccomp_arch_ppc64le) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
@@ -456,7 +463,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_PPC64
 			else if (strcmp(line, "[ppc64]") == 0 ||
-					strcmp(line, "[PPC64]") == 0) {
+				 strcmp(line, "[PPC64]") == 0) {
 				if (native_arch != lxc_seccomp_arch_ppc64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
@@ -466,7 +473,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_PPC
 			else if (strcmp(line, "[ppc]") == 0 ||
-					strcmp(line, "[PPC]") == 0) {
+				 strcmp(line, "[PPC]") == 0) {
 				if (native_arch != lxc_seccomp_arch_ppc &&
 						native_arch != lxc_seccomp_arch_ppc64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
@@ -477,21 +484,21 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_MIPS
 			else if (strcmp(line, "[mips64]") == 0 ||
-					strcmp(line, "[MIPS64]") == 0) {
+				 strcmp(line, "[MIPS64]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mips64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
 				}
 				cur_rule_arch = lxc_seccomp_arch_mips64;
 			} else if (strcmp(line, "[mips64n32]") == 0 ||
-					strcmp(line, "[MIPS64N32]") == 0) {
+				   strcmp(line, "[MIPS64N32]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mips64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
 				}
 				cur_rule_arch = lxc_seccomp_arch_mips64n32;
 			} else if (strcmp(line, "[mips]") == 0 ||
-					strcmp(line, "[MIPS]") == 0) {
+				   strcmp(line, "[MIPS]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mips &&
 						native_arch != lxc_seccomp_arch_mips64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
@@ -499,21 +506,21 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 				}
 				cur_rule_arch = lxc_seccomp_arch_mips;
 			} else if (strcmp(line, "[mipsel64]") == 0 ||
-					strcmp(line, "[MIPSEL64]") == 0) {
+				   strcmp(line, "[MIPSEL64]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mipsel64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
 				}
 				cur_rule_arch = lxc_seccomp_arch_mipsel64;
 			} else if (strcmp(line, "[mipsel64n32]") == 0 ||
-					strcmp(line, "[MIPSEL64N32]") == 0) {
+				   strcmp(line, "[MIPSEL64N32]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mipsel64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
 				}
 				cur_rule_arch = lxc_seccomp_arch_mipsel64n32;
 			} else if (strcmp(line, "[mipsel]") == 0 ||
-					strcmp(line, "[MIPSEL]") == 0) {
+				   strcmp(line, "[MIPSEL]") == 0) {
 				if (native_arch != lxc_seccomp_arch_mipsel &&
 						native_arch != lxc_seccomp_arch_mipsel64) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
@@ -524,7 +531,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 #endif
 #ifdef SCMP_ARCH_S390X
 			else if (strcmp(line, "[s390x]") == 0 ||
-					strcmp(line, "[S390X]") == 0) {
+				 strcmp(line, "[S390X]") == 0) {
 				if (native_arch != lxc_seccomp_arch_s390x) {
 					cur_rule_arch = lxc_seccomp_arch_unknown;
 					continue;
@@ -545,14 +552,14 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 		/* read optional action which follows the syscall */
 		action = get_and_clear_v2_action(line, default_rule_action);
 		if (action == -1) {
-			ERROR("Failed to interpret action");
+			ERROR("Failed to interpret action.");
 			goto bad_rule;
 		}
 
 		if (cur_rule_arch == native_arch ||
 		    cur_rule_arch == lxc_seccomp_arch_native ||
 		    compat_arch[0] == SCMP_ARCH_NATIVE) {
-			INFO("Adding native rule for %s action %d", line, action);
+			INFO("Adding native rule for %s action %d.", line, action);
 			if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
 				goto bad_rule;
 		}
@@ -561,15 +568,15 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 				cur_rule_arch == lxc_seccomp_arch_mips64n32 ||
 				cur_rule_arch == lxc_seccomp_arch_mipsel64n32 ? 1 : 0;
 
-			INFO("Adding compat-only rule for %s action %d", line, action);
+			INFO("Adding compat-only rule for %s action %d.", line, action);
 			if (!do_resolve_add_rule(compat_arch[arch_index], line, compat_ctx[arch_index], action))
 				goto bad_rule;
 		}
 		else {
-			INFO("Adding native rule for %s action %d", line, action);
+			INFO("Adding native rule for %s action %d.", line, action);
 			if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
 				goto bad_rule;
-			INFO("Adding compat rule for %s action %d", line, action);
+			INFO("Adding compat rule for %s action %d.", line, action);
 			if (!do_resolve_add_rule(compat_arch[0], line, compat_ctx[0], action))
 				goto bad_rule;
 			if (compat_arch[1] != SCMP_ARCH_NATIVE &&
@@ -579,10 +586,10 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 	}
 
 	if (compat_ctx[0]) {
-		INFO("Merging in the compat seccomp ctx into the main one");
+		INFO("Merging in the compat Seccomp ctx into the main one.");
 		if (seccomp_merge(conf->seccomp_ctx, compat_ctx[0]) != 0 ||
 			(compat_ctx[1] != NULL && seccomp_merge(conf->seccomp_ctx, compat_ctx[1]) != 0)) {
-			ERROR("Error merging compat seccomp contexts");
+			ERROR("Error merging compat Seccomp contexts.");
 			goto bad;
 		}
 	}
@@ -590,7 +597,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 	return 0;
 
 bad_arch:
-	ERROR("Unsupported arch: %s", line);
+	ERROR("Unsupported arch: %s.", line);
 bad_rule:
 bad:
 	if (compat_ctx[0])
@@ -621,20 +628,20 @@ static int parse_config(FILE *f, struct lxc_conf *conf)
 
 	ret = fscanf(f, "%d\n", &version);
 	if (ret != 1 || (version != 1 && version != 2)) {
-		ERROR("invalid version");
+		ERROR("Invalid version.");
 		return -1;
 	}
 	if (!fgets(line, 1024, f)) {
-		ERROR("invalid config file");
+		ERROR("Invalid config file.");
 		return -1;
 	}
 	if (version == 1 && !strstr(line, "whitelist")) {
-		ERROR("only whitelist policy is supported");
+		ERROR("Only whitelist policy is supported.");
 		return -1;
 	}
 
 	if (strstr(line, "debug")) {
-		ERROR("debug not yet implemented");
+		ERROR("Debug not yet implemented.");
 		return -1;
 	}
 
@@ -664,7 +671,7 @@ static bool use_seccomp(void)
 	while (fgets(line, 1024, f)) {
 		if (strncmp(line, "Seccomp:", 8) == 0) {
 			found = true;
-			ret = sscanf(line+8, "%d", &v);
+			ret = sscanf(line + 8, "%d", &v);
 			if (ret == 1 && v != 0)
 				already_enabled = true;
 			break;
@@ -672,12 +679,12 @@ static bool use_seccomp(void)
 	}
 
 	fclose(f);
-	if (!found) {  /* no Seccomp line, no seccomp in kernel */
-		INFO("Seccomp is not enabled in the kernel");
+	if (!found) { /* no Seccomp line, no seccomp in kernel */
+		INFO("Seccomp is not enabled in the kernel.");
 		return false;
 	}
-	if (already_enabled) {  /* already seccomp-confined */
-		INFO("Already seccomp-confined, not loading new policy");
+	if (already_enabled) { /* already seccomp-confined */
+		INFO("Already seccomp-confined, not loading new policy.");
 		return false;
 	}
 	return true;
@@ -702,25 +709,25 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
 	ret = seccomp_init(SCMP_ACT_KILL) < 0;
 #endif
 	if (ret) {
-		ERROR("failed initializing seccomp");
+		ERROR("Failed initializing seccomp.");
 		return -1;
 	}
 
-	/* turn of no-new-privs.  We don't want it in lxc, and it breaks
-	 * with apparmor */
+/* turn of no-new-privs.  We don't want it in lxc, and it breaks
+ * with apparmor */
 #if HAVE_SCMP_FILTER_CTX
-  check_seccomp_attr_set = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
+	check_seccomp_attr_set = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
 #else
-  check_seccomp_attr_set = seccomp_attr_set(SCMP_FLTATR_CTL_NNP, 0);
+	check_seccomp_attr_set = seccomp_attr_set(SCMP_FLTATR_CTL_NNP, 0);
 #endif
 	if (check_seccomp_attr_set) {
-		ERROR("failed to turn off n-new-privs");
+		ERROR("Failed to turn off n-new-privs.");
 		return -1;
 	}
 
 	f = fopen(conf->seccomp, "r");
 	if (!f) {
-		SYSERROR("failed to open seccomp policy file %s", conf->seccomp);
+		SYSERROR("Failed to open seccomp policy file %s.", conf->seccomp);
 		return -1;
 	}
 	ret = parse_config(f, conf);
@@ -737,17 +744,18 @@ int lxc_seccomp_load(struct lxc_conf *conf)
 		return 0;
 	ret = seccomp_load(
 #if HAVE_SCMP_FILTER_CTX
-			conf->seccomp_ctx
+	    conf->seccomp_ctx
 #endif
-	);
+	    );
 	if (ret < 0) {
-		ERROR("Error loading the seccomp policy");
+		ERROR("Error loading the seccomp policy.");
 		return -1;
 	}
 	return 0;
 }
 
-void lxc_seccomp_free(struct lxc_conf *conf) {
+void lxc_seccomp_free(struct lxc_conf *conf)
+{
 	free(conf->seccomp);
 	conf->seccomp = NULL;
 #if HAVE_SCMP_FILTER_CTX

From 2c0f32e6432f24dcc698d8fe0bd84d83a3588bdc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= <glen at delfi.ee>
Date: Sat, 20 Aug 2016 17:09:28 +0300
Subject: [PATCH 126/334] templates: use fd 9 instead of 200
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

to catch up mksh changes from 17abf27

Signed-off-by: Elan Ruusamäe <glen at delfi.ee>
---
 templates/lxc-slackware.in | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/templates/lxc-slackware.in b/templates/lxc-slackware.in
index c8e8e73..5005918 100644
--- a/templates/lxc-slackware.in
+++ b/templates/lxc-slackware.in
@@ -501,7 +501,7 @@ install_slackware()
 rootfs=$1
 mkdir -p /var/lock/subsys/
 (
-flock -n -x 200
+flock -n -x 9
 if [ $? -ne 0 ]; then
 	echo "Cache repository is busy."
 	return 1
@@ -629,7 +629,7 @@ sed -i 's|3\ \-x|3 -x -s|' $ROOT/etc/rc.d/rc.syslog || true
 
 return 0
 
-) 200>/var/lock/subsys/lxc
+) 9>/var/lock/subsys/lxc
 
 return $?
 }
@@ -666,7 +666,7 @@ fi
 
 # lock, so we won't purge while someone is creating a repository
 (
-flock -n -x 200
+flock -n -x 9
 if [ $? != 0 ]; then
 	echo "Cache repository is busy."
 	exit 1
@@ -676,7 +676,7 @@ echo -n "Purging the download cache..."
 rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
 exit 0
 
-) 200>/var/lock/subsys/lxc
+) 9>/var/lock/subsys/lxc
 }
 
 usage()

From c86f214c1e07e13414d43c34711702ed659f8a65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= <glen at delfi.ee>
Date: Tue, 23 Aug 2016 19:31:38 +0300
Subject: [PATCH 127/334] templates: fedora requires openssl binary
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

/usr/share/lxc/templates/lxc-fedora: line 1078: openssl: command not found

Signed-off-by: Elan Ruusamäe <glen at delfi.ee>
---
 templates/lxc-fedora.in | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/templates/lxc-fedora.in b/templates/lxc-fedora.in
index a83a590..88f5ca9 100644
--- a/templates/lxc-fedora.in
+++ b/templates/lxc-fedora.in
@@ -1336,6 +1336,10 @@ type curl >/dev/null 2>&1
 if [ $? -ne 0 ]; then
     needed_pkgs="curl $needed_pkgs"
 fi
+type openssl >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+    needed_pkgs="openssl $needed_pkgs"
+fi
 
 if [ -n "$needed_pkgs" ]; then
     echo "Missing commands: $needed_pkgs"

From 599a84d5aa0798ff6aa896806829aa28351a5aff Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Fri, 26 Aug 2016 12:49:23 +0200
Subject: [PATCH 128/334] tools: use boolean for ret in lxc_device.c

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 src/lxc/tools/lxc_device.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/lxc/tools/lxc_device.c b/src/lxc/tools/lxc_device.c
index abf52b9..39c560c 100644
--- a/src/lxc/tools/lxc_device.c
+++ b/src/lxc/tools/lxc_device.c
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
 {
 	struct lxc_container *c;
 	char *cmd, *dev_name, *dst_name;
-	int ret = 1;
+	bool ret = false;
 
 	if (geteuid() != 0) {
 		ERROR("%s must be run as root", argv[0]);
@@ -164,7 +164,6 @@ int main(int argc, char *argv[])
 		}
 		if (ret != true) {
 			ERROR("Failed to add %s to %s.", dev_name, c->name);
-			ret = 1;
 			goto err1;
 		}
 		INFO("Add %s to %s.", dev_name, c->name);
@@ -176,7 +175,6 @@ int main(int argc, char *argv[])
 		}
 		if (ret != true) {
 			ERROR("Failed to del %s from %s.", dev_name, c->name);
-			ret = 1;
 			goto err1;
 		}
 		INFO("Delete %s from %s.", dev_name, c->name);

From 9bec7ccd65d53936ef41e5d2ffc0a6e9f6c1df7c Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 26 Aug 2016 16:07:19 +0000
Subject: [PATCH 129/334] c/r: use /proc/self/tid/children instead of pidfile

All we really needed a unique temp file for was passing the pid. Since CRIU
opened this with O_EXCL | O_CREAT, this was "safe" (users could still
overwrite it afterwards, but the monitor would immediately die since the
only valid number in there was the init process).

In any case, we can just read /proc/self/tid/children, which lists the
child process.

Closes #1150

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 38 ++++++++++++++------------------------
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 65998ed..76d7080 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -69,7 +69,6 @@ struct criu_opts {
 	char tty_id[32]; /* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
 
 	/* restore: the file to write the init process' pid into */
-	char *pidfile;
 	const char *cgroup_path;
 	int console_fd;
 	/* The path that is bind mounted from /dev/console, if any. We don't
@@ -176,10 +175,10 @@ static void exec_criu(struct criu_opts *opts)
 			static_args += 2;
 	} else if (strcmp(opts->action, "restore") == 0) {
 		/* --root $(lxc_mount_point) --restore-detached
-		 * --restore-sibling --pidfile $foo --cgroup-root $foo
+		 * --restore-sibling --cgroup-root $foo
 		 * --lsm-profile apparmor:whatever
 		 */
-		static_args += 10;
+		static_args += 8;
 
 		tty_info[0] = 0;
 		if (load_tty_major_minor(opts->user->directory, tty_info, sizeof(tty_info)))
@@ -330,8 +329,6 @@ static void exec_criu(struct criu_opts *opts)
 		DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
 		DECLARE_ARG("--restore-detached");
 		DECLARE_ARG("--restore-sibling");
-		DECLARE_ARG("--pidfile");
-		DECLARE_ARG(opts->pidfile);
 		DECLARE_ARG("--cgroup-root");
 		DECLARE_ARG(opts->cgroup_path);
 
@@ -604,13 +601,8 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 {
 	pid_t pid;
 	struct lxc_handler *handler;
-	int fd, status;
+	int status;
 	int pipes[2] = {-1, -1};
-	char pidfile[] = "criu_restore_XXXXXX";
-
-	fd = mkstemp(pidfile);
-	if (fd < 0)
-		goto out;
 
 	handler = lxc_init(c->name, c->lxc_conf, c->config_path);
 	if (!handler)
@@ -690,7 +682,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		os.action = "restore";
 		os.user = opts;
 		os.c = c;
-		os.pidfile = pidfile;
 		os.cgroup_path = cgroup_canonical_path(handler);
 		os.console_fd = c->lxc_conf->console.slave;
 		os.criu_version = criu_version;
@@ -742,8 +733,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		}
 
 		if (WIFEXITED(status)) {
+			char buf[4096];
+
 			if (WEXITSTATUS(status)) {
-				char buf[4096];
 				int n;
 
 				n = read(pipes[0], buf, sizeof(buf));
@@ -758,18 +750,21 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 				goto out_fini_handler;
 			} else {
 				int ret;
-				FILE *f = fdopen(fd, "r");
+
+				ret = snprintf(buf, sizeof(buf), "/proc/self/task/%" PRId64 "/children", syscall(__NR_gettid));
+				if (ret < 0 || ret >= sizeof(buf)) {
+					ERROR("snprintf'd too many characters: %d", ret);
+					goto out_fini_handler;
+				}
+
+				FILE *f = fopen(buf, "r");
 				if (!f) {
-					SYSERROR("couldn't read restore's init pidfile %s\n", pidfile);
+					SYSERROR("couldn't read restore's children file %s\n", buf);
 					goto out_fini_handler;
 				}
-				fd = -1;
 
 				ret = fscanf(f, "%d", (int*) &handler->pid);
 				fclose(f);
-				if (unlink(pidfile) < 0 && errno != ENOENT)
-					SYSERROR("unlinking pidfile failed");
-
 				if (ret != 1) {
 					ERROR("reading restore pid failed");
 					goto out_fini_handler;
@@ -809,8 +804,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		close(pipes[1]);
 
 	lxc_fini(c->name, handler);
-	if (unlink(pidfile) < 0 && errno != ENOENT)
-		SYSERROR("unlinking pidfile failed");
 
 out:
 	if (status_pipe >= 0) {
@@ -821,9 +814,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		close(status_pipe);
 	}
 
-	if (fd > 0)
-		close(fd);
-
 	exit(1);
 }
 

From eeca23a1f8a584732099a76e540d6aed87b39a94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 26 Aug 2016 15:41:34 -0400
Subject: [PATCH 130/334] c/r: Fix pid_t on some arches
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/lxc/criu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 76d7080..c20c00a 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -751,7 +751,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 			} else {
 				int ret;
 
-				ret = snprintf(buf, sizeof(buf), "/proc/self/task/%" PRId64 "/children", syscall(__NR_gettid));
+				ret = snprintf(buf, sizeof(buf), "/proc/self/task/%lu/children", (unsigned long)syscall(__NR_gettid));
 				if (ret < 0 || ret >= sizeof(buf)) {
 					ERROR("snprintf'd too many characters: %d", ret);
 					goto out_fini_handler;

From 6219206fc4e76d108f9bb2d0a8cd55b7070fd467 Mon Sep 17 00:00:00 2001
From: James Cowgill <james410 at cowgill.org.uk>
Date: Mon, 15 Aug 2016 16:10:00 +0000
Subject: [PATCH 131/334] templates: Add mips hostarch detection to debian

Signed-off-by: James Cowgill <james410 at cowgill.org.uk>
---
 templates/lxc-debian.in | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index ac8158c..7ebea90 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -543,6 +543,8 @@ if [ $? -ne 0 ]; then
 fi
 eval set -- "$options"
 
+littleendian=$(lscpu | grep '^Byte Order' | grep -q Little && echo yes)
+
 arch=$(uname -m)
 if [ "$arch" = "i686" ]; then
     arch="i386"
@@ -550,6 +552,10 @@ elif [ "$arch" = "x86_64" ]; then
     arch="amd64"
 elif [ "$arch" = "armv7l" ]; then
     arch="armhf"
+elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then
+    arch="mipsel"
+elif [ "$arch" = "mips64" -a "$littleendian" = "yes" ]; then
+    arch="mips64el"
 fi
 hostarch=$arch
 mainonly=1

From 6a49f2c6912d8e113fe478e0b86c96acd12fc155 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 12 Aug 2016 12:33:44 +0200
Subject: [PATCH 132/334] cleanup: replace tabs wth spaces in usage strings

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_copy.c       | 26 +++++++++++++-------------
 src/lxc/tools/lxc_ls.c         |  4 ++--
 src/lxc/tools/lxc_snapshot.c   |  2 +-
 src/lxc/tools/lxc_usernsexec.c |  2 +-
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index f8ca861..5a6ced2 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -111,20 +111,20 @@ Options :\n\
   -n, --name=NAME           NAME of the container\n\
   -N, --newname=NEWNAME     NEWNAME for the restored container\n\
   -p, --newpath=NEWPATH     NEWPATH for the container to be stored\n\
-  -R, --rename		    rename container\n\
-  -s, --snapshot	    create snapshot instead of clone\n\
-  -F, --foreground	    start with current tty attached to /dev/console\n\
-  -d, --daemon		    daemonize the container (default)\n\
-  -e, --ephemeral	    start ephemeral container\n\
-  -m, --mount	            directory to mount into container, either \n\
-			    {bind,aufs,overlay}=/src-path or {bind,aufs,overlay}=/src-path:/dst-path\n\
+  -R, --rename              rename container\n\
+  -s, --snapshot            create snapshot instead of clone\n\
+  -F, --foreground          start with current tty attached to /dev/console\n\
+  -d, --daemon              daemonize the container (default)\n\
+  -e, --ephemeral           start ephemeral container\n\
+  -m, --mount               directory to mount into container, either \n\
+                            {bind,aufs,overlay}=/src-path or {bind,aufs,overlay}=/src-path:/dst-path\n\
   -B, --backingstorage=TYPE backingstorage type for the container\n\
-  -L, --fssize		    size of the new block device for block device containers\n\
-  -D, --keedata	            pass together with -e start a persistent snapshot \n\
-  -K, --keepname	    keep the hostname of the original container\n\
-  --  hook options	    arguments passed to the hook program\n\
-  -M, --keepmac		    keep the MAC address of the original container\n\
-  --rcfile=FILE		    Load configuration file FILE\n",
+  -L, --fssize              size of the new block device for block device containers\n\
+  -D, --keedata             pass together with -e start a persistent snapshot \n\
+  -K, --keepname            keep the hostname of the original container\n\
+  --  hook options          arguments passed to the hook program\n\
+  -M, --keepmac             keep the MAC address of the original container\n\
+  --rcfile=FILE             Load configuration file FILE\n",
 	.options = my_longopts,
 	.parser = my_parser,
 	.task = CLONE,
diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index 0575277..e22c715 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -184,8 +184,8 @@ static struct lxc_arguments my_args = {
 lxc-ls list containers\n\
 \n\
 Options :\n\
-  -1, --line	     show one entry per line\n\
-  -f, --fancy	     column-based output\n\
+  -1, --line         show one entry per line\n\
+  -f, --fancy        column-based output\n\
   -F, --fancy-format column-based output\n\
   --active           list only active containers\n\
   --running          list only running containers\n\
diff --git a/src/lxc/tools/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
index a1166bc..1a79a7a 100644
--- a/src/lxc/tools/lxc_snapshot.c
+++ b/src/lxc/tools/lxc_snapshot.c
@@ -55,7 +55,7 @@ static struct lxc_arguments my_args = {
 lxc-snapshot snapshots a container\n\
 \n\
 Options :\n\
-  -n, --name=NAME	 NAME of the container\n\
+  -n, --name=NAME        NAME of the container\n\
   -L, --list             list all snapshots\n\
   -r, --restore=NAME     restore snapshot NAME, e.g. 'snap0'\n\
   -N, --newname=NEWNAME  NEWNAME for the restored container\n\
diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c
index d4c730a..9905d53 100644
--- a/src/lxc/tools/lxc_usernsexec.c
+++ b/src/lxc/tools/lxc_usernsexec.c
@@ -59,7 +59,7 @@ static void usage(const char *name)
 {
 	printf("usage: %s [-h] [-m <uid-maps>] -- [command [arg ..]]\n", name);
 	printf("\n");
-	printf("  -h		this message\n");
+	printf("  -h            this message\n");
 	printf("\n");
 	printf("  -m <uid-maps> uid maps to use\n");
 	printf("\n");

From 063ce0928fdb05f4812fb2b20bc661b17329f11a Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 26 Aug 2016 16:13:06 -0400
Subject: [PATCH 133/334] remove extra 'ret'

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index c20c00a..5a48c72 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -749,8 +749,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 				ERROR("criu process exited %d, output:\n%s\n", WEXITSTATUS(status), buf);
 				goto out_fini_handler;
 			} else {
-				int ret;
-
 				ret = snprintf(buf, sizeof(buf), "/proc/self/task/%lu/children", (unsigned long)syscall(__NR_gettid));
 				if (ret < 0 || ret >= sizeof(buf)) {
 					ERROR("snprintf'd too many characters: %d", ret);

From bc3da65ff15c926258189d182fc0d7b30ed5608e Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 26 Aug 2016 16:29:45 -0400
Subject: [PATCH 134/334] c/r: write status only after trying to parse the pid

Previously, we write a "success" status but tried to parse the pid. This
meant that we wouldn't notice a successful restore but failure to parse the
pid, which was a little strange.

We still don't know the child pid, so we will end up with a restored
process tree and a running container, but at least in this case the API
will return false indicating that something failed.

We could kill(-1, 9) in this case, but since liblxc runs as root sometimes
(e.g. LXD), that would be a Very Bad Thing.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 5a48c72..71c9b9c 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -723,15 +723,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 			goto out_fini_handler;
 		}
 
-		ret = write(status_pipe, &status, sizeof(status));
-		close(status_pipe);
-		status_pipe = -1;
-
-		if (sizeof(status) != ret) {
-			SYSERROR("failed to write all of status");
-			goto out_fini_handler;
-		}
-
 		if (WIFEXITED(status)) {
 			char buf[4096];
 
@@ -780,6 +771,15 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 
 		close(pipes[0]);
 
+		ret = write(status_pipe, &status, sizeof(status));
+		close(status_pipe);
+		status_pipe = -1;
+
+		if (sizeof(status) != ret) {
+			SYSERROR("failed to write all of status");
+			goto out_fini_handler;
+		}
+
 		/*
 		 * See comment in lxcapi_start; we don't care if these
 		 * fail because it's just a beauty thing. We just
@@ -805,7 +805,12 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 
 out:
 	if (status_pipe >= 0) {
-		status = 1;
+		/* ensure getting here was a failure, e.g. if we failed to
+		 * parse the child pid or something, even after a successful
+		 * restore
+		 */
+		if (!status)
+			status = 1;
 		if (write(status_pipe, &status, sizeof(status)) != sizeof(status)) {
 			SYSERROR("writing status failed");
 		}

From 4167ada83ec9ba89b8cd14e24e14922d959e07dd Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 27 Aug 2016 12:14:53 +0200
Subject: [PATCH 135/334] set FULL_PATH_NAMES=NO in doc/api/Doxyfile

otherwise the generated docs have the full build path in them
and nonbody cares that the files were built in
 /build/lxc-_BVY2u/lxc-2.0.4/src/lxc/

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 doc/api/Doxyfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/api/Doxyfile b/doc/api/Doxyfile
index e6ada00..59180f8 100644
--- a/doc/api/Doxyfile
+++ b/doc/api/Doxyfile
@@ -130,7 +130,7 @@ INLINE_INHERITED_MEMB  = NO
 # shortest path that makes the file name unique will be used
 # The default value is: YES.
 
-FULL_PATH_NAMES        = YES
+FULL_PATH_NAMES        = NO
 
 # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
 # Stripping is only done if one of the specified strings matches the left-hand

From 09b157d4437a50ca2c72ddb6ab3ee7838c35b377 Mon Sep 17 00:00:00 2001
From: Christian Brauner <cbrauner at suse.de>
Date: Wed, 31 Aug 2016 23:53:50 +0200
Subject: [PATCH 136/334] templates: rm halt.target -> sigpwr.target symlink

Given commit 330ae3d350e060e5702a0e5ef5d0faeeeea8df6e:

    lxccontainer: detect if we should send SIGRTMIN+3

    This is required by systemd to cleanly shutdown. Other init systems should not
    have SIGRTMIN+3 in the blocked signals set.

we should stop symlinking halt.target to sigpwr.target for systemd.

Signed-off-by: Christian Brauner <cbrauner at suse.de>
---
 templates/lxc-debian.in | 2 --
 templates/lxc-oracle.in | 3 ---
 2 files changed, 5 deletions(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 7ebea90..f44dd56 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -236,8 +236,6 @@ configure_debian_systemd()
     chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/udev.service
     chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/systemd-udevd.service
     chroot "${rootfs}" ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
-    # Make systemd honor SIGPWR
-    chroot "${rootfs}" ln -s /lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
     # Setup getty service on the ttys we are going to allow in the
     # default config.  Number should match lxc.tty
     ( cd "${rootfs}/etc/systemd/system/getty.target.wants"
diff --git a/templates/lxc-oracle.in b/templates/lxc-oracle.in
index eb01ecb..20c212b 100644
--- a/templates/lxc-oracle.in
+++ b/templates/lxc-oracle.in
@@ -169,9 +169,6 @@ EOF
         rm -f $container_rootfs/usr/lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service
         chroot $container_rootfs systemctl -q disable graphical.target
         chroot $container_rootfs systemctl -q enable multi-user.target
-        if [ ! -e $container_rootfs/etc/systemd/system/sigpwr.target ]; then
-            chroot $container_rootfs ln -s /usr/lib/systemd/system/halt.target /etc/systemd/system/sigpwr.target
-        fi
 
         # systemd in userns won't be able to set /proc/self/oom_score_adj which
         # prevents the dbus service from starting

From cdb7b5a7bf10d276192c8342d1e7f69c4c1c02d1 Mon Sep 17 00:00:00 2001
From: Maxime BESSON <maxime.besson at smile.fr>
Date: Thu, 1 Sep 2016 16:09:37 +0200
Subject: [PATCH 137/334] templates: remove creation of bogus directory

An incorrect quoting introduced in bf39edb caused a /{lib,etc} folder to
appear in Debian templates

The very next line :
    mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants

makes creating ${rootfs}/etc/systemd/system/ unnecessary in the first
place

Signed-off-by: Maxime Besson <maxime.besson at smile.fr>
---
 templates/lxc-debian.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index f44dd56..15aff91 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -219,7 +219,7 @@ configure_debian_systemd()
     fi
 
     # just in case systemd is not installed
-    mkdir -p "${rootfs}/{lib,etc}/systemd/system"
+    mkdir -p "${rootfs}/lib/systemd/system"
     mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants"
 
     # Fix getty-static-service as debootstrap does not install dbus

From b5eb7be11b80b6e9b2fa59ace8e1ff3bc0d03c42 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Sat, 3 Sep 2016 20:05:54 +0200
Subject: [PATCH 138/334] console: use correct log name

lxc_console is used with lxc_console.c

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/lxc/console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index 6d335ca..052512e 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -52,7 +52,7 @@
 #include <../include/openpty.h>
 #endif
 
-lxc_log_define(lxc_console, lxc);
+lxc_log_define(console, lxc);
 
 static struct lxc_list lxc_ttys;
 

From 18f96d107ec433105cfbcf8204410afbe9b1a3cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pouiller?= <jezz at sysmic.org>
Date: Sun, 4 Sep 2016 09:35:44 +0200
Subject: [PATCH 139/334] configure: add --disable-werror
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

-Werror may break builds on some scenarios with trivialities
(especially during developments).

Signed-off-by: Jérôme Pouiller <jezz at sysmic.org>
---
 configure.ac | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index c3d891a..6c512c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,6 +148,11 @@ if test "x$with_systemdsystemunitdir" != "xno"; then
   AC_SUBST([SYSTEMD_UNIT_DIR], [$with_systemdsystemunitdir])
 fi
 
+AC_ARG_ENABLE([werror],
+	[AC_HELP_STRING([--disable-werror],
+	[do not treat warnings as errors])],
+	[], [enable_werror=yes])
+
 # Allow enabling deprecated executables
 AC_ARG_ENABLE([deprecated],
 	[AC_HELP_STRING([--enable-deprecated],
@@ -626,7 +631,10 @@ AC_PROG_SED
 LXC_CHECK_TLS
 
 if test "x$GCC" = "xyes"; then
-	CFLAGS="$CFLAGS -Wall -Werror"
+	CFLAGS="$CFLAGS -Wall"
+	if test "x$enable_werror" = "xyes"; then
+		CFLAGS="$CFLAGS -Werror"
+	fi
 fi
 
 # Files requiring some variable expansion

From 0e5743d5531171b9522431620bca6a1f2a45fb30 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at mailbox.org>
Date: Mon, 5 Sep 2016 00:01:51 +0200
Subject: [PATCH 140/334] tests: fix get_item tests

Signed-off-by: Christian Brauner <christian.brauner at mailbox.org>
---
 src/tests/get_item.c | 58 +++++-----------------------------------------------
 1 file changed, 5 insertions(+), 53 deletions(-)

diff --git a/src/tests/get_item.c b/src/tests/get_item.c
index 9a9ae59..9750f31 100644
--- a/src/tests/get_item.c
+++ b/src/tests/get_item.c
@@ -32,25 +32,22 @@
 
 int main(int argc, char *argv[])
 {
+	int ret = EXIT_FAILURE;
 	struct lxc_container *c;
-	int ret;
 	char v1[2], v2[256], v3[2048];
 
 	if ((c = lxc_container_new("testxyz", NULL)) == NULL) {
 		fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
-		ret = 1;
-		goto out;
+		exit(EXIT_FAILURE);
 	}
 
 	if (!c->set_config_item(c, "lxc.hook.pre-start", "hi there")) {
 		fprintf(stderr, "%d: failed to set hook.pre-start\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.hook.pre-start", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.hook.pre-start) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	fprintf(stderr, "lxc.hook.pre-start returned %d %s\n", ret, v2);
@@ -58,58 +55,49 @@ int main(int argc, char *argv[])
 	ret = c->get_config_item(c, "lxc.network", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	fprintf(stderr, "%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2);
 	if (!c->set_config_item(c, "lxc.tty", "4")) {
 		fprintf(stderr, "%d: failed to set tty\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.tty", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.tty) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	fprintf(stderr, "lxc.tty returned %d %s\n", ret, v2);
 
 	if (!c->set_config_item(c, "lxc.arch", "x86")) {
 		fprintf(stderr, "%d: failed to set arch\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.arch", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.arch) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.arch returned %d %s\n", ret, v2);
 
 	if (!c->set_config_item(c, "lxc.init_uid", "100")) {
 		fprintf(stderr, "%d: failed to set init_uid\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.init_uid", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.init_uid) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.init_uid returned %d %s\n", ret, v2);
 
 	if (!c->set_config_item(c, "lxc.init_gid", "100")) {
 		fprintf(stderr, "%d: failed to set init_gid\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.init_gid", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.init_gid) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.init_gid returned %d %s\n", ret, v2);
@@ -119,7 +107,6 @@ int main(int argc, char *argv[])
 	char *alloced;
 	if (!c->set_config_item(c, "lxc.utsname", HNAME)) {
 		fprintf(stderr, "%d: failed to set utsname\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 
@@ -127,7 +114,6 @@ int main(int argc, char *argv[])
 	len = c->get_config_item(c, "lxc.utsname", NULL, 0);  // query the size of the string
 	if (len < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, len);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.utsname returned %d\n", len);
@@ -136,7 +122,6 @@ int main(int argc, char *argv[])
 	alloced = malloc(len+1);
 	if (!alloced) {
 		fprintf(stderr, "%d: failed to allocate %d bytes for utsname\n", __LINE__, len);
-		ret = 1;
 		goto out;
 	}
 	// now pass in the malloc'd array, and pass in length of string + 1: again
@@ -144,12 +129,10 @@ int main(int argc, char *argv[])
 	ret = c->get_config_item(c, "lxc.utsname", alloced, len+1);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	if (strcmp(alloced, HNAME) != 0 || ret != len) {
 		fprintf(stderr, "lxc.utsname returned wrong value: %d %s not %d %s\n", ret, alloced, len, HNAME);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.utsname returned %d %s\n", len, alloced);
@@ -157,26 +140,22 @@ int main(int argc, char *argv[])
 
 	if (!c->set_config_item(c, "lxc.mount.entry", "hi there")) {
 		fprintf(stderr, "%d: failed to set mount.entry\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.mount.entry", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.mount.entry) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.mount.entry returned %d %s\n", ret, v2);
 
 	if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) {
 		fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.aa_profile", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.aa_profile) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("lxc.aa_profile returned %d %s\n", ret, v2);
@@ -186,7 +165,6 @@ int main(int argc, char *argv[])
 	// new test with real container
 	if ((c = lxc_container_new(MYNAME, NULL)) == NULL) {
 		fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
-		ret = 1;
 		goto out;
 	}
 	c->destroy(c);
@@ -194,130 +172,109 @@ int main(int argc, char *argv[])
 
 	if ((c = lxc_container_new(MYNAME, NULL)) == NULL) {
 		fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
-		ret = 1;
 		goto out;
 	}
 	if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) {
 		fprintf(stderr, "%d: failed to create a trusty container\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
-
 	lxc_container_put(c);
 
 	/* XXX TODO load_config needs to clear out any old config first */
 	if ((c = lxc_container_new(MYNAME, NULL)) == NULL) {
 		fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
-		ret = 1;
 		goto out;
 	}
 
 	ret = c->get_config_item(c, "lxc.cap.drop", NULL, 300);
 	if (ret < 5 || ret > 255) {
 		fprintf(stderr, "%d: get_config_item(lxc.cap.drop) with NULL returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.cap.drop", v1, 1);
 	if (ret < 5 || ret > 255) {
 		fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.cap.drop", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2);
 	ret = c->get_config_item(c, "lxc.network", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2);
 
 	if (!c->set_config_item(c, "lxc.network.ipv4", "10.2.3.4")) {
 		fprintf(stderr, "%d: failed to set ipv4\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 
 	ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255);
 	if (ret <= 0) {
 		fprintf(stderr, "%d: lxc.network.0.ipv4 returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	if (!c->clear_config_item(c, "lxc.network.0.ipv4")) {
 		fprintf(stderr, "%d: failed clearing all ipv4 entries\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255);
 	if (ret != 0) {
 		fprintf(stderr, "%d: after clearing ipv4 entries get_item(lxc.network.0.ipv4 returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 
 	if (!c->set_config_item(c, "lxc.network.ipv4.gateway", "10.2.3.254")) {
 		fprintf(stderr, "%d: failed to set ipv4.gateway\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 
 	ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255);
 	if (ret <= 0) {
 		fprintf(stderr, "%d: lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	if (!c->set_config_item(c, "lxc.network.0.ipv4.gateway", "")) {
 		fprintf(stderr, "%d: failed clearing ipv4.gateway\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255);
 	if (ret != 0) {
 		fprintf(stderr, "%d: after clearing ipv4.gateway get_item(lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 
 	ret = c->get_config_item(c, "lxc.network.0.link", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item (link) returned %d %s\n", __LINE__, ret, v2);
 	ret = c->get_config_item(c, "lxc.network.0.name", v2, 255);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item (name) returned %d %s\n", __LINE__, ret, v2);
 
 	if (!c->clear_config_item(c, "lxc.network")) {
 		fprintf(stderr, "%d: clear_config_item failed\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	ret = c->get_config_item(c, "lxc.network", v2, 255);
 	if (ret != 0) {
 		fprintf(stderr, "%d: network was not actually cleared (get_network returned %d)\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 
 	ret = c->get_config_item(c, "lxc.cgroup", v3, 2047);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(cgroup.devices) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item (cgroup.devices) returned %d %s\n", __LINE__, ret, v3);
@@ -325,35 +282,30 @@ int main(int argc, char *argv[])
 	ret = c->get_config_item(c, "lxc.cgroup.devices.allow", v3, 2047);
 	if (ret < 0) {
 		fprintf(stderr, "%d: get_config_item(cgroup.devices.devices.allow) returned %d\n", __LINE__, ret);
-		ret = 1;
 		goto out;
 	}
 	printf("%d: get_config_item (cgroup.devices.devices.allow) returned %d %s\n", __LINE__, ret, v3);
 
 	if (!c->clear_config_item(c, "lxc.cgroup")) {
 		fprintf(stderr, "%d: failed clearing lxc.cgroup\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	if (!c->clear_config_item(c, "lxc.cap.drop")) {
 		fprintf(stderr, "%d: failed clearing lxc.cap.drop\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	if (!c->clear_config_item(c, "lxc.mount.entry")) {
 		fprintf(stderr, "%d: failed clearing lxc.mount.entry\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
 	if (!c->clear_config_item(c, "lxc.hook")) {
 		fprintf(stderr, "%d: failed clearing lxc.hook\n", __LINE__);
-		ret = 1;
 		goto out;
 	}
-	c->destroy(c);
 	printf("All get_item tests passed\n");
-	ret = 0;
+	ret = EXIT_SUCCESS;
 out:
+	c->destroy(c);
 	lxc_container_put(c);
 	exit(ret);
-};
+}

From 4674d20e336ae6d465cee7b605d68f3eb37db925 Mon Sep 17 00:00:00 2001
From: Alex Athanasopoulos <alex at melato.org>
Date: Tue, 6 Sep 2016 17:09:55 +0300
Subject: [PATCH 141/334] templates: use correct cron version in alpine
 template

Signed-off-by: Alex Athanasopoulos <alex at melato.org>
---
 templates/lxc-alpine.in | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in
index 988f109..a6b3363 100644
--- a/templates/lxc-alpine.in
+++ b/templates/lxc-alpine.in
@@ -364,8 +364,12 @@ setup_services() {
 	done
 
 	# default runlevel
-	for svc_name in networking cron; do
-		ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name
+	for svc_name in networking cron crond; do
+		# issue 1164: alpine renamed cron to crond
+		# Use the one that exists.
+		if [ -e etc/init.d/$svc_name ]; then
+			ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name
+		fi
 	done
 }
 

From 8319c93f2421396fdee8b50647ac4323ddd66565 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Thu, 8 Sep 2016 09:14:42 -0600
Subject: [PATCH 142/334] c/r: zero a smaller than known migrate_opts struct

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/lxccontainer.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 5721977..c02e587 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -3960,6 +3960,7 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
 			     struct migrate_opts *opts, unsigned int size)
 {
 	int ret;
+	struct migrate_opts *valid_opts = opts;
 
 	/* If the caller has a bigger (newer) struct migrate_opts, let's make
 	 * sure that the stuff on the end is zero, i.e. that they didn't ask us
@@ -3978,15 +3979,28 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
 		}
 	}
 
+	/* If the caller has a smaller struct, let's zero out the end for them
+	 * so we don't accidentally use bits of it that they didn't know about
+	 * to initialize.
+	 */
+	if (size < sizeof(*opts)) {
+		valid_opts = malloc(sizeof(*opts));
+		if (!valid_opts)
+			return -ENOMEM;
+
+		memset(valid_opts, 0, sizeof(*opts));
+		memcpy(valid_opts, opts, size);
+	}
+
 	switch (cmd) {
 	case MIGRATE_PRE_DUMP:
-		ret = !__criu_pre_dump(c, opts);
+		ret = !__criu_pre_dump(c, valid_opts);
 		break;
 	case MIGRATE_DUMP:
-		ret = !__criu_dump(c, opts);
+		ret = !__criu_dump(c, valid_opts);
 		break;
 	case MIGRATE_RESTORE:
-		ret = !__criu_restore(c, opts);
+		ret = !__criu_restore(c, valid_opts);
 		break;
 	default:
 		ERROR("invalid migrate command %u", cmd);

From 07eb27233195034e09e9a4e869baf22bdd70a5b7 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 13 Sep 2016 17:18:23 +0200
Subject: [PATCH 143/334] lxczfs: small fixes

- We expect destroy to fail in zfs_clone() so try to silence it so users are
  not irritated when they create zfs snapshots.
- Add -r recursive to zfs_destroy(). This code is only hit when a) the
  container has no snapshots or b) the user calls destroy with snapshots. So
  this should be safe. Without -r snapshots will remain.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/bdev/lxczfs.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/lxc/bdev/lxczfs.c b/src/lxc/bdev/lxczfs.c
index dd1005b..6412945 100644
--- a/src/lxc/bdev/lxczfs.c
+++ b/src/lxc/bdev/lxczfs.c
@@ -26,6 +26,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/mount.h>
 
 #include "bdev.h"
@@ -170,6 +171,9 @@ int zfs_clone(const char *opath, const char *npath, const char *oname,
 		if ((pid = fork()) < 0)
 			return -1;
 		if (!pid) {
+			int dev0 = open("/dev/null", O_WRONLY);
+			if (dev0 >= 0)
+				dup2(dev0, STDERR_FILENO);
 			execlp("zfs", "zfs", "destroy", path1, (char *)NULL);
 			exit(EXIT_FAILURE);
 		}
@@ -252,7 +256,7 @@ int zfs_destroy(struct bdev *orig)
 		return -1;
 	*p = '\0';
 
-	execlp("zfs", "zfs", "destroy", output, (char *)NULL);
+	execlp("zfs", "zfs", "destroy", "-r", output, (char *)NULL);
 	exit(EXIT_FAILURE);
 }
 

From 5fbd50cd85c0e7c8e95ae6c199b967f2497cba48 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Tue, 13 Sep 2016 16:42:20 -0600
Subject: [PATCH 144/334] c/r: free valid_opts if necessary

2cb80427bc468f7647309c3eca66cfc9afa85b61 introduced a malloc without a
matching free.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/lxccontainer.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index c02e587..a1c94a1 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -4007,6 +4007,9 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
 		ret = -EINVAL;
 	}
 
+	if (size < sizeof(*opts))
+		free(valid_opts);
+
 	return ret;
 }
 

From 0725879b4f4de8d1c8f51d2d3983ed705c6e8ac7 Mon Sep 17 00:00:00 2001
From: Lukas Pirl <github at lukas-pirl.de>
Date: Wed, 14 Sep 2016 17:40:16 +0200
Subject: [PATCH 145/334] make rsync deal with sparse files efficiently

Signed-off-by: Lukas Pirl <git at lukas-pirl.de>
---
 src/lxc/bdev/lxcrsync.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/bdev/lxcrsync.c b/src/lxc/bdev/lxcrsync.c
index 17f0b6e..8af3989 100644
--- a/src/lxc/bdev/lxcrsync.c
+++ b/src/lxc/bdev/lxcrsync.c
@@ -61,7 +61,7 @@ int do_rsync(const char *src, const char *dest)
 	s[l-2] = '/';
 	s[l-1] = '\0';
 
-	execlp("rsync", "rsync", "-aHX", "--delete", s, dest, (char *)NULL);
+	execlp("rsync", "rsync", "-aHXS", "--delete", s, dest, (char *)NULL);
 	exit(1);
 }
 

From 2658578ea76bb0203c5f3fc0cecffb6936c307a4 Mon Sep 17 00:00:00 2001
From: Thierry Fauck <tfauck at free.fr>
Date: Fri, 16 Sep 2016 08:34:41 -0500
Subject: [PATCH 146/334] lxc-create -t debian fails on ppc64el arch

Template catches arch from uname -m, but for ppc64el system, arch reports ppc64le
which doesn't match image repo.

Signed-off-by: Thierry Fauck <tfauck at free.fr>
Signed-off-by: Serge Hallyn <serge at hallyn.com>
---
 templates/lxc-debian.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 15aff91..ee4c4f1 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -550,6 +550,8 @@ elif [ "$arch" = "x86_64" ]; then
     arch="amd64"
 elif [ "$arch" = "armv7l" ]; then
     arch="armhf"
+elif [ "$arch" = "ppc64le" ]; then
+    arch="ppc64el"
 elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then
     arch="mipsel"
 elif [ "$arch" = "mips64" -a "$littleendian" = "yes" ]; then

From f3727c9458f4a2251b3b3f0da158353503c8ee8c Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 12 Sep 2016 18:04:18 +0000
Subject: [PATCH 147/334] c/r: fix typo in comment

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 71c9b9c..2799102 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -140,7 +140,7 @@ static void exec_criu(struct criu_opts *opts)
 
 	/* The command line always looks like:
 	 * criu $(action) --tcp-established --file-locks --link-remap \
-	 * --manage-cgroups=full action-script foo.sh -D $(directory) \
+	 * --manage-cgroups=full --action-script foo.sh -D $(directory) \
 	 * -o $(directory)/$(action).log --ext-mount-map auto
 	 * --enable-external-sharing --enable-external-masters
 	 * --enable-fs hugetlbfs --enable-fs tracefs --ext-mount-map console:/dev/pts/n

From 336b642f5d71db280387f5e4c7ccd89e8c7eac38 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:38:46 +0000
Subject: [PATCH 148/334] cgroup: add new functions for interacting with
 hierachies

N.B. that these are only implemented in cgfsng, but,

15:28:28    tych0 | do we still use cgfs anywhere? or the cgm backend?
15:29:19 stgraber | not anywhere we care about

...I think that's okay.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/cgroups/cgfs.c      | 14 ++++++++++++++
 src/lxc/cgroups/cgfsng.c    | 27 +++++++++++++++++++++++++++
 src/lxc/cgroups/cgmanager.c | 14 ++++++++++++++
 src/lxc/cgroups/cgroup.c    | 16 ++++++++++++++++
 src/lxc/cgroups/cgroup.h    |  4 ++++
 5 files changed, 75 insertions(+)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 2d0de0c..80a336d 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -2434,6 +2434,18 @@ static bool cgfs_escape(void *hdata)
 	return ret;
 }
 
+static int cgfs_num_hierarchies(void)
+{
+	/* not implemented */
+	return -1;
+}
+
+static bool cgfs_get_hierarchies(int i, char ***out)
+{
+	/* not implemented */
+	return false;
+}
+
 static bool cgfs_unfreeze(void *hdata)
 {
 	struct cgfs_data *d = hdata;
@@ -2627,6 +2639,8 @@ static struct cgroup_ops cgfs_ops = {
 	.get_cgroup = cgfs_get_cgroup,
 	.canonical_path = cgfs_canonical_path,
 	.escape = cgfs_escape,
+	.num_hierarchies = cgfs_num_hierarchies,
+	.get_hierarchies = cgfs_get_hierarchies,
 	.get = lxc_cgroupfs_get,
 	.set = lxc_cgroupfs_set,
 	.unfreeze = cgfs_unfreeze,
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 95f29ca..5b61554 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1457,6 +1457,31 @@ static bool cgfsng_escape()
 	return ret;
 }
 
+static int cgfsng_num_hierarchies(void)
+{
+	int i;
+
+	for (i = 0; hierarchies[i]; i++)
+		;
+
+	return i;
+}
+
+static bool cgfsng_get_hierarchies(int n, char ***out)
+{
+	int i;
+
+	/* sanity check n */
+	for (i = 0; i < n; i++) {
+		if (!hierarchies[i])
+			return false;
+	}
+
+	*out = hierarchies[i]->controllers;
+
+	return true;
+}
+
 #define THAWED "THAWED"
 #define THAWED_LEN (strlen(THAWED))
 
@@ -1674,6 +1699,8 @@ static struct cgroup_ops cgfsng_ops = {
 	.enter = cgfsng_enter,
 	.canonical_path = cgfsng_canonical_path,
 	.escape = cgfsng_escape,
+	.num_hierarchies = cgfsng_num_hierarchies,
+	.get_hierarchies = cgfsng_get_hierarchies,
 	.get_cgroup = cgfsng_get_cgroup,
 	.get = cgfsng_get,
 	.set = cgfsng_set,
diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
index 4da891d..f14eb17 100644
--- a/src/lxc/cgroups/cgmanager.c
+++ b/src/lxc/cgroups/cgmanager.c
@@ -337,6 +337,18 @@ static bool cgm_escape(void *hdata)
 	return ret;
 }
 
+static int cgm_num_hierarchies(void)
+{
+	/* not implemented */
+	return -1;
+}
+
+static bool cgm_get_hierarchies(int i, char ***out)
+{
+	/* not implemented */
+	return false;
+}
+
 struct chown_data {
 	const char *cgroup_path;
 	uid_t origuid;
@@ -1657,6 +1669,8 @@ static struct cgroup_ops cgmanager_ops = {
 	.get_cgroup = cgm_get_cgroup,
 	.canonical_path = cgm_canonical_path,
 	.escape = cgm_escape,
+	.num_hierarchies = cgm_num_hierarchies,
+	.get_hierarchies = cgm_get_hierarchies,
 	.get = cgm_get,
 	.set = cgm_set,
 	.unfreeze = cgm_unfreeze,
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index 91ef359..48cd403 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -132,6 +132,22 @@ const char *cgroup_canonical_path(struct lxc_handler *handler)
 	return NULL;
 }
 
+int cgroup_num_hierarchies(void)
+{
+	if (!ops)
+		return -1;
+
+	return ops->num_hierarchies();
+}
+
+bool cgroup_get_hierarchies(int n, char ***out)
+{
+	if (!ops)
+		return false;
+
+	return ops->get_hierarchies(n, out);
+}
+
 bool cgroup_unfreeze(struct lxc_handler *handler)
 {
 	if (ops)
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index e56a115..f65cbfe 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -49,6 +49,8 @@ struct cgroup_ops {
 	const char *(*get_cgroup)(void *hdata, const char *subsystem);
 	const char *(*canonical_path)(void *hdata);
 	bool (*escape)();
+	int (*num_hierarchies)();
+	bool (*get_hierarchies)(int n, char ***out);
 	int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath);
 	int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
 	bool (*unfreeze)(void *hdata);
@@ -74,6 +76,8 @@ extern bool cgroup_create_legacy(struct lxc_handler *handler);
 extern int cgroup_nrtasks(struct lxc_handler *handler);
 extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
 extern bool cgroup_escape();
+extern int cgroup_num_hierarchies();
+extern bool cgroup_get_hierarchies(int i, char ***out);
 
 /*
  * Currently, this call  only makes sense for privileged containers.

From 8c41d0fc711ec8afdafd361e5ca0fce06ab38f5a Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:46:47 +0000
Subject: [PATCH 149/334] utils: add lxc_deslashify

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/utils.c | 18 ++++++++++++++++++
 src/lxc/utils.h |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 27362da..9a6ef4b 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -716,6 +716,24 @@ char **lxc_normalize_path(const char *path)
 	return components;
 }
 
+bool lxc_deslashify(char *path)
+{
+	char **parts = NULL, *path2;
+
+	parts = lxc_normalize_path(path);
+	if (!parts)
+		return false;
+
+	path2 = lxc_string_join("/", (const char **) parts, *path == '/');
+	lxc_free_array((void **) parts, free);
+	if (!path2)
+		return false;
+
+	strncpy(path, path2, strlen(path));
+	free(path2);
+	return true;
+}
+
 char *lxc_append_paths(const char *first, const char *second)
 {
 	size_t len = strlen(first) + strlen(second) + 1;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 98b4e13..c2eef50 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -248,6 +248,8 @@ extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_pr
  *     foo//bar     ->   { foo, bar, NULL }
  */
 extern char **lxc_normalize_path(const char *path);
+/* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */
+extern bool lxc_deslashify(char *path);
 extern char *lxc_append_paths(const char *first, const char *second);
 /* Note: the following two functions use strtok(), so they will never
  *       consider an empty element, even if two delimiters are next to

From 02f2cba67279e56e602bf01f882a7af25b37c5bf Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:47:38 +0000
Subject: [PATCH 150/334] c/r: pass --cgroup-roots on checkpoint

CRIU has added support for passing --cgroup-root on dump, which we should
use (see the criu commit 07d259f365f224b32914de26ea0fd59fc6db0001 for
details). Note that we don't have to do any version checking or anything,
because CRIU just ignored --cgroup-root on checkpoint before, so passing it
is safe, and will result in correct behavior when a sufficient version of
CRIU is present.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 73 insertions(+), 6 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 2799102..0702ad2 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -69,7 +69,7 @@ struct criu_opts {
 	char tty_id[32]; /* the criu tty id for /dev/console, i.e. "tty[${rdev}:${dev}]" */
 
 	/* restore: the file to write the init process' pid into */
-	const char *cgroup_path;
+	struct lxc_handler *handler;
 	int console_fd;
 	/* The path that is bind mounted from /dev/console, if any. We don't
 	 * want to use `--ext-mount-map auto`'s result here because the pts
@@ -175,10 +175,10 @@ static void exec_criu(struct criu_opts *opts)
 			static_args += 2;
 	} else if (strcmp(opts->action, "restore") == 0) {
 		/* --root $(lxc_mount_point) --restore-detached
-		 * --restore-sibling --cgroup-root $foo
+		 * --restore-sibling
 		 * --lsm-profile apparmor:whatever
 		 */
-		static_args += 8;
+		static_args += 6;
 
 		tty_info[0] = 0;
 		if (load_tty_major_minor(opts->user->directory, tty_info, sizeof(tty_info)))
@@ -191,6 +191,8 @@ static void exec_criu(struct criu_opts *opts)
 		return;
 	}
 
+	static_args += 2 * cgroup_num_hierarchies();
+
 	if (opts->user->verbose)
 		static_args++;
 
@@ -244,6 +246,66 @@ static void exec_criu(struct criu_opts *opts)
 	DECLARE_ARG("-o");
 	DECLARE_ARG(log);
 
+	for (i = 0; i < cgroup_num_hierarchies(); i++) {
+		char **controllers = NULL, *fullname;
+		char *path;
+
+		if (!cgroup_get_hierarchies(i, &controllers)) {
+			ERROR("failed to get hierarchy %d", i);
+			goto err;
+		}
+
+		/* if we are in a dump, we have to ask the monitor process what
+		 * the right cgroup is. if this is a restore, we can just use
+		 * the handler the restore task created.
+		 */
+		if (!strcmp(opts->action, "dump") || !strcmp(opts->action, "pre-dump")) {
+			path = lxc_cmd_get_cgroup_path(opts->c->name, opts->c->config_path, controllers[0]);
+			if (!path) {
+				ERROR("failed to get cgroup path for %s", controllers[0]);
+				goto err;
+			}
+		} else {
+			const char *p;
+
+			p = cgroup_get_cgroup(opts->handler, controllers[0]);
+			if (!p) {
+				ERROR("failed to get cgroup path for %s", controllers[0]);
+				goto err;
+			}
+
+			path = strdup(p);
+			if (!path) {
+				ERROR("strdup failed");
+				goto err;
+			}
+		}
+
+		if (!lxc_deslashify(path)) {
+			ERROR("failed to deslashify %s", path);
+			free(path);
+			goto err;
+		}
+
+		fullname = lxc_string_join(",", (const char **) controllers, false);
+		if (!fullname) {
+			ERROR("failed to join controllers");
+			free(path);
+			goto err;
+		}
+
+		ret = sprintf(buf, "%s:%s", fullname, path);
+		free(path);
+		free(fullname);
+		if (ret < 0 || ret >= sizeof(buf)) {
+			ERROR("sprintf of cgroup root arg failed");
+			goto err;
+		}
+
+		DECLARE_ARG("--cgroup-root");
+		DECLARE_ARG(buf);
+	}
+
 	if (opts->user->verbose)
 		DECLARE_ARG("-vvvvvv");
 
@@ -329,8 +391,6 @@ static void exec_criu(struct criu_opts *opts)
 		DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
 		DECLARE_ARG("--restore-detached");
 		DECLARE_ARG("--restore-sibling");
-		DECLARE_ARG("--cgroup-root");
-		DECLARE_ARG(opts->cgroup_path);
 
 		if (tty_info[0]) {
 			if (opts->console_fd < 0) {
@@ -682,9 +742,9 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 		os.action = "restore";
 		os.user = opts;
 		os.c = c;
-		os.cgroup_path = cgroup_canonical_path(handler);
 		os.console_fd = c->lxc_conf->console.slave;
 		os.criu_version = criu_version;
+		os.handler = handler;
 
 		if (os.console_fd >= 0) {
 			/* Twiddle the FD_CLOEXEC bit. We want to pass this FD to criu
@@ -891,6 +951,13 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 
 	if (pid == 0) {
 		struct criu_opts os;
+		struct lxc_handler h;
+
+		h.name = c->name;
+		if (!cgroup_init(&h)) {
+			ERROR("failed to cgroup_init()");
+			exit(1);
+		}
 
 		os.action = mode;
 		os.user = opts;

From a6f6d4682496eabc9b4b91a278fbf948a3ecdb5a Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:53:21 +0000
Subject: [PATCH 151/334] cgroup: get rid of weird hack in cgfsng_escape

We initialized cgfsng in a strange way inside of its implementation of
escape so we could use it during checkpoint. Instead, the previous patch
does a hacky initialization in criu.c, and we can get rid of the hacks
elsewhere :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 5b61554..0777bf3 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1426,19 +1426,11 @@ static int cgfsng_nrtasks(void *hdata) {
 /* Only root needs to escape to the cgroup of its init */
 static bool cgfsng_escape()
 {
-	struct cgfsng_handler_data *d;
 	int i;
-	bool ret = false;
 
 	if (geteuid())
 		return true;
 
-	d = cgfsng_init("criu-temp-cgfsng");
-	if (!d) {
-		ERROR("cgfsng_init failed");
-		return false;
-	}
-
 	for (i = 0; hierarchies[i]; i++) {
 		char *fullpath = must_make_path(hierarchies[i]->mountpoint,
 						hierarchies[i]->base_cgroup,
@@ -1446,15 +1438,12 @@ static bool cgfsng_escape()
 		if (lxc_write_to_file(fullpath, "0", 2, false) != 0) {
 			SYSERROR("Failed to escape to %s", fullpath);
 			free(fullpath);
-			goto out;
+			return false;
 		}
 		free(fullpath);
 	}
 
-	ret = true;
-out:
-	free_handler_data(d);
-	return ret;
+	return true;
 }
 
 static int cgfsng_num_hierarchies(void)

From d7e0fb8092151782f07952b45e05609e02f4386d Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 14 Sep 2016 14:58:38 +0000
Subject: [PATCH 152/334] cgroup: drop cgroup_canonical_path

This is almost never the right thing to use, and we don't use it any more
anyway.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/cgroups/cgfs.c      | 23 -----------------------
 src/lxc/cgroups/cgfsng.c    |  8 --------
 src/lxc/cgroups/cgmanager.c | 10 ----------
 src/lxc/cgroups/cgroup.c    | 13 -------------
 src/lxc/cgroups/cgroup.h    |  6 ------
 5 files changed, 60 deletions(-)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 80a336d..c5ba765 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -2363,28 +2363,6 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
 	return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
 }
 
-static const char *cgfs_canonical_path(void *hdata)
-{
-	struct cgfs_data *d = hdata;
-	struct cgroup_process_info *info_ptr;
-	char *path = NULL;
-
-	if (!d)
-		return NULL;
-
-	for (info_ptr = d->info; info_ptr; info_ptr = info_ptr->next) {
-		if (!path)
-			path = info_ptr->cgroup_path;
-		else if (strcmp(path, info_ptr->cgroup_path) != 0) {
-			ERROR("not all paths match %s, %s has path %s", path,
-				info_ptr->hierarchy->subsystems[0], info_ptr->cgroup_path);
-			return NULL;
-		}
-	}
-
-	return path;
-}
-
 static bool cgfs_escape(void *hdata)
 {
 	struct cgroup_meta_data *md;
@@ -2637,7 +2615,6 @@ static struct cgroup_ops cgfs_ops = {
 	.enter = cgfs_enter,
 	.create_legacy = cgfs_create_legacy,
 	.get_cgroup = cgfs_get_cgroup,
-	.canonical_path = cgfs_canonical_path,
 	.escape = cgfs_escape,
 	.num_hierarchies = cgfs_num_hierarchies,
 	.get_hierarchies = cgfs_get_hierarchies,
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 0777bf3..ec94099 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1087,13 +1087,6 @@ static inline bool cgfsng_create(void *hdata)
 	return false;
 }
 
-static const char *cgfsng_canonical_path(void *hdata)
-{
-	struct cgfsng_handler_data *d = hdata;
-
-	return d->container_cgroup;
-}
-
 static bool cgfsng_enter(void *hdata, pid_t pid)
 {
 	char pidstr[25];
@@ -1686,7 +1679,6 @@ static struct cgroup_ops cgfsng_ops = {
 	.destroy = cgfsng_destroy,
 	.create = cgfsng_create,
 	.enter = cgfsng_enter,
-	.canonical_path = cgfsng_canonical_path,
 	.escape = cgfsng_escape,
 	.num_hierarchies = cgfsng_num_hierarchies,
 	.get_hierarchies = cgfsng_get_hierarchies,
diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
index f14eb17..f2756b0 100644
--- a/src/lxc/cgroups/cgmanager.c
+++ b/src/lxc/cgroups/cgmanager.c
@@ -746,15 +746,6 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
 	return d->cgroup_path;
 }
 
-static const char *cgm_canonical_path(void *hdata)
-{
-	struct cgm_data *d = hdata;
-
-	if (!d || !d->cgroup_path)
-		return NULL;
-	return d->cgroup_path;
-}
-
 #if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
 static inline bool abs_cgroup_supported(void) {
 	return api_version >= CGM_SUPPORTS_GET_ABS;
@@ -1667,7 +1658,6 @@ static struct cgroup_ops cgmanager_ops = {
 	.enter = cgm_enter,
 	.create_legacy = NULL,
 	.get_cgroup = cgm_get_cgroup,
-	.canonical_path = cgm_canonical_path,
 	.escape = cgm_escape,
 	.num_hierarchies = cgm_num_hierarchies,
 	.get_hierarchies = cgm_get_hierarchies,
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index 48cd403..78472d4 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -119,19 +119,6 @@ bool cgroup_escape(struct lxc_handler *handler)
 	return false;
 }
 
-const char *cgroup_canonical_path(struct lxc_handler *handler)
-{
-	if (geteuid()) {
-		WARN("cgroup_canonical_path only makes sense for privileged containers.\n");
-		return NULL;
-	}
-
-	if (ops)
-		return ops->canonical_path(handler->cgroup_data);
-
-	return NULL;
-}
-
 int cgroup_num_hierarchies(void)
 {
 	if (!ops)
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index f65cbfe..11b251e 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -47,7 +47,6 @@ struct cgroup_ops {
 	bool (*enter)(void *hdata, pid_t pid);
 	bool (*create_legacy)(void *hdata, pid_t pid);
 	const char *(*get_cgroup)(void *hdata, const char *subsystem);
-	const char *(*canonical_path)(void *hdata);
 	bool (*escape)();
 	int (*num_hierarchies)();
 	bool (*get_hierarchies)(int n, char ***out);
@@ -78,11 +77,6 @@ extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *su
 extern bool cgroup_escape();
 extern int cgroup_num_hierarchies();
 extern bool cgroup_get_hierarchies(int i, char ***out);
-
-/*
- * Currently, this call  only makes sense for privileged containers.
- */
-extern const char *cgroup_canonical_path(struct lxc_handler *handler);
 extern bool cgroup_unfreeze(struct lxc_handler *handler);
 extern void cgroup_disconnect(void);
 extern cgroup_driver_t cgroup_driver(void);

From 8b4e6d69a63611913d59431cc5d6a60ec6d509c2 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 16 Sep 2016 20:26:31 -0600
Subject: [PATCH 153/334] c/r: check that cgroup_num_hierarchies > 0

Otherwise in the error case, we end up subtracting two from the
static_args, which would lead to a segfault :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 0702ad2..3e586b9 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -191,7 +191,8 @@ static void exec_criu(struct criu_opts *opts)
 		return;
 	}
 
-	static_args += 2 * cgroup_num_hierarchies();
+	if (cgroup_num_hierarchies() > 0)
+		static_args += 2 * cgroup_num_hierarchies();
 
 	if (opts->user->verbose)
 		static_args++;

From 8d74bafd2ce3a09dbcd5c3bb7ce8be3b171afcd4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 21 Sep 2016 09:15:14 +0200
Subject: [PATCH 154/334] tools: do not add trailing spaces on lxc-ls -1

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_ls.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index e22c715..8e7cbef 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -144,7 +144,7 @@ static void ls_print_fancy_format(struct ls *l, struct lengths *lht,
  * Only print names of containers.
  */
 static void ls_print_names(struct ls *l, struct lengths *lht,
-		size_t ls_arr, size_t termwidth);
+		size_t ls_arr, size_t termwidth, bool list);
 
 /*
  * Print default fancy format.
@@ -264,7 +264,7 @@ int main(int argc, char *argv[])
 		unsigned int cols = 0;
 		if (!my_args.ls_line)
 			cols = ls_get_term_width();
-		ls_print_names(ls_arr, &max_len, ls_size, cols);
+		ls_print_names(ls_arr, &max_len, ls_size, cols, my_args.ls_line);
 	}
 
 	ret = EXIT_SUCCESS;
@@ -743,7 +743,7 @@ static struct ls *ls_new(struct ls **ls, size_t *size)
 }
 
 static void ls_print_names(struct ls *l, struct lengths *lht,
-		size_t size, size_t termwidth)
+		size_t size, size_t termwidth, bool list)
 {
 	/* If list is empty do nothing. */
 	if (size == 0)
@@ -752,14 +752,18 @@ static void ls_print_names(struct ls *l, struct lengths *lht,
 	size_t i, len = 0;
 	struct ls *m = NULL;
 	for (i = 0, m = l; i < size; i++, m++) {
-		printf("%-*s", lht->name_length, m->name ? m->name : "-");
-		len += lht->name_length;
-		if ((len + lht->name_length) >= termwidth) {
-			printf("\n");
-			len = 0;
+		if (list) {
+			printf("%s\n", m->name ? m->name : "-");
 		} else {
-			printf(" ");
-			len++;
+			printf("%-*s", lht->name_length, m->name ? m->name : "-");
+			len += lht->name_length;
+			if ((len + lht->name_length) >= termwidth) {
+				printf("\n");
+				len = 0;
+			} else {
+				printf(" ");
+				len++;
+			}
 		}
 	}
 	if (len > 0)

From 8d9e6d770539e73663675ae3af82bdac3f0d402f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 21 Sep 2016 20:56:03 +0200
Subject: [PATCH 155/334] conf: retrieve mtu from netdev->link

When mtu is not set, try to retrieve mtu from netdev->link.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 4ece410..a4a4a6f 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2521,7 +2521,7 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 {
 	char veth1buf[IFNAMSIZ], *veth1;
 	char veth2buf[IFNAMSIZ], *veth2;
-	int err, mtu = 0;
+	int bridge_index, err, mtu = 0;
 
 	if (netdev->priv.veth_attr.pair) {
 		veth1 = netdev->priv.veth_attr.pair;
@@ -2574,8 +2574,13 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 
 	if (netdev->mtu) {
 		mtu = atoi(netdev->mtu);
+		INFO("Retrieved mtu %d", mtu);
 	} else if (netdev->link) {
-		mtu = netdev_get_mtu(netdev->ifindex);
+		bridge_index = if_nametoindex(netdev->link);
+		if (!bridge_index)
+			INFO("Could not retrieve mtu from %s", netdev->link);
+		mtu = netdev_get_mtu(bridge_index);
+		INFO("Retrieved mtu %d from %s", mtu, netdev->link);
 	}
 
 	if (mtu) {

From eb39afe5986b5fa447f340520b52ffe6050409a8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 21 Sep 2016 21:07:24 +0200
Subject: [PATCH 156/334] conf: try to retrieve mtu from veth

When the mtu cannot be retrieved from netdev->link try from veth device.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index a4a4a6f..bac560d 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2577,10 +2577,13 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 		INFO("Retrieved mtu %d", mtu);
 	} else if (netdev->link) {
 		bridge_index = if_nametoindex(netdev->link);
-		if (!bridge_index)
-			INFO("Could not retrieve mtu from %s", netdev->link);
-		mtu = netdev_get_mtu(bridge_index);
-		INFO("Retrieved mtu %d from %s", mtu, netdev->link);
+		if (bridge_index) {
+			mtu = netdev_get_mtu(bridge_index);
+			INFO("Retrieved mtu %d from %s", mtu, netdev->link);
+		} else {
+			mtu = netdev_get_mtu(netdev->ifindex);
+			INFO("Retrieved mtu %d from %s", mtu, veth2);
+		}
 	}
 
 	if (mtu) {

From a6013704b04143086e52e6b885cab3028903495d Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 21 Sep 2016 21:45:49 +0000
Subject: [PATCH 157/334] c/r: detatch from controlling tty on restore

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 3e586b9..67d6fdc 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -662,9 +662,22 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 {
 	pid_t pid;
 	struct lxc_handler *handler;
-	int status;
+	int status, fd;
 	int pipes[2] = {-1, -1};
 
+	/* Try to detach from the current controlling tty if it exists.
+	 * Othwerise, lxc_init (via lxc_console) will attach the container's
+	 * console output to the current tty, which is probably not what any
+	 * library user wants, and if they do, they can just manually configure
+	 * it :)
+	 */
+	fd = open("/dev/tty", O_RDWR);
+	if (fd >= 0) {
+		if (ioctl(fd, TIOCNOTTY, NULL) < 0)
+			SYSERROR("couldn't detach from tty");
+		close(fd);
+	}
+
 	handler = lxc_init(c->name, c->lxc_conf, c->config_path);
 	if (!handler)
 		goto out;

From 07d112757ecdff193335ec0ce285837af78d7f91 Mon Sep 17 00:00:00 2001
From: Oliver Matthews <oliver at codersoffortune.net>
Date: Sun, 25 Sep 2016 09:37:43 +0100
Subject: [PATCH 158/334] Fix null derefence if attach is called without access
 to any tty

Signed-off-by: Oliver Matthews <oliver at codersoffortune.net>
---
 src/lxc/tools/lxc_attach.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 9d71388..23d63a2 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -321,7 +321,7 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
 err3:
 	lxc_mainloop_close(&descr);
 err2:
-	if (ts->sigfd != -1)
+	if (ts && ts->sigfd != -1)
 		lxc_console_sigwinch_fini(ts);
 err1:
 	lxc_console_delete(&conf->console);

From 304b20df12bdd45b177cb9197fcb233c2e2b9ee8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 25 Sep 2016 16:51:24 +0200
Subject: [PATCH 159/334] utils: fix lxc_string_split()

Make sure we don't return uninitialized memory.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 9a6ef4b..c72c26a 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -774,8 +774,8 @@ bool lxc_string_in_list(const char *needle, const char *haystack, char _sep)
 char **lxc_string_split(const char *string, char _sep)
 {
 	char *token, *str, *saveptr = NULL;
-	char sep[2] = { _sep, '\0' };
-	char **result = NULL;
+	char sep[2] = {_sep, '\0'};
+	char **tmp = NULL, **result = NULL;
 	size_t result_capacity = 0;
 	size_t result_count = 0;
 	int r, saved_errno;
@@ -783,7 +783,7 @@ char **lxc_string_split(const char *string, char _sep)
 	if (!string)
 		return calloc(1, sizeof(char *));
 
-	str = alloca(strlen(string)+1);
+	str = alloca(strlen(string) + 1);
 	strcpy(str, string);
 	for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
 		r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16);
@@ -796,7 +796,14 @@ char **lxc_string_split(const char *string, char _sep)
 	}
 
 	/* if we allocated too much, reduce it */
-	return realloc(result, (result_count + 1) * sizeof(char *));
+	tmp = realloc(result, (result_count + 1) * sizeof(char *));
+	if (!tmp)
+		goto error_out;
+	result = tmp;
+	/* Make sure we don't return uninitialized memory. */
+	if (result_count == 0)
+		*result = NULL;
+	return result;
 error_out:
 	saved_errno = errno;
 	lxc_free_array((void **)result, free);

From 0f0bf49732c1e15b959ddb1d8af465c1ad4d0a83 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 25 Sep 2016 23:57:13 +0200
Subject: [PATCH 160/334] tools: lxc_deslashify() handle special cases

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/criu.c  |  2 +-
 src/lxc/utils.c | 35 +++++++++++++++++++++++++++--------
 src/lxc/utils.h |  2 +-
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 67d6fdc..f228736 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -282,7 +282,7 @@ static void exec_criu(struct criu_opts *opts)
 			}
 		}
 
-		if (!lxc_deslashify(path)) {
+		if (!lxc_deslashify(&path)) {
 			ERROR("failed to deslashify %s", path);
 			free(path);
 			goto err;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index c72c26a..ebf3ad9 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -716,21 +716,40 @@ char **lxc_normalize_path(const char *path)
 	return components;
 }
 
-bool lxc_deslashify(char *path)
+bool lxc_deslashify(char **path)
 {
-	char **parts = NULL, *path2;
+	char *p;
+	char **parts = NULL;
+	size_t n, len;
 
-	parts = lxc_normalize_path(path);
+	parts = lxc_normalize_path(*path);
 	if (!parts)
 		return false;
 
-	path2 = lxc_string_join("/", (const char **) parts, *path == '/');
-	lxc_free_array((void **) parts, free);
-	if (!path2)
+	/* We'll end up here if path == "///" or path == "". */
+	if (!*parts) {
+		len = strlen(*path);
+		if (!len)
+			return true;
+		n = strcspn(*path, "/");
+		if (n == len) {
+			p = strdup("/");
+			if (!p)
+				return false;
+			free(*path);
+			*path = p;
+			return true;
+		}
+	}
+
+	p = lxc_string_join("/", (const char **)parts, **path == '/');
+	lxc_free_array((void **)parts, free);
+	if (!p)
 		return false;
 
-	strncpy(path, path2, strlen(path));
-	free(path2);
+	free(*path);
+	*path = p;
+
 	return true;
 }
 
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index c2eef50..88719a0 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -249,7 +249,7 @@ extern char *lxc_string_join(const char *sep, const char **parts, bool use_as_pr
  */
 extern char **lxc_normalize_path(const char *path);
 /* remove multiple slashes from the path, e.g. ///foo//bar -> /foo/bar */
-extern bool lxc_deslashify(char *path);
+extern bool lxc_deslashify(char **path);
 extern char *lxc_append_paths(const char *first, const char *second);
 /* Note: the following two functions use strtok(), so they will never
  *       consider an empty element, even if two delimiters are next to

From 29cbbb02c5b2889f47b4ceb314371d63132ba2c6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 25 Sep 2016 23:57:43 +0200
Subject: [PATCH 161/334] tests: add unit tests for lxc_deslashify()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxc-test-utils.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 4c1c373..5b213c8 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -21,6 +21,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,6 +29,37 @@
 #include "lxctest.h"
 #include "utils.h"
 
+void test_lxc_deslashify(void)
+{
+	char *s = strdup("/A///B//C/D/E/");
+	if (!s)
+		exit(EXIT_FAILURE);
+	lxc_test_assert_abort(lxc_deslashify(&s));
+	lxc_test_assert_abort(strcmp(s, "/A/B/C/D/E") == 0);
+	free(s);
+
+	s = strdup("/A");
+	if (!s)
+		exit(EXIT_FAILURE);
+	lxc_test_assert_abort(lxc_deslashify(&s));
+	lxc_test_assert_abort(strcmp(s, "/A") == 0);
+	free(s);
+
+	s = strdup("");
+	if (!s)
+		exit(EXIT_FAILURE);
+	lxc_test_assert_abort(lxc_deslashify(&s));
+	lxc_test_assert_abort(strcmp(s, "") == 0);
+	free(s);
+
+	s = strdup("//");
+	if (!s)
+		exit(EXIT_FAILURE);
+	lxc_test_assert_abort(lxc_deslashify(&s));
+	lxc_test_assert_abort(strcmp(s, "/") == 0);
+	free(s);
+}
+
 void test_lxc_string_replace(void)
 {
 	char *s;
@@ -84,6 +116,7 @@ int main(int argc, char *argv[])
 {
 	test_lxc_string_replace();
 	test_lxc_string_in_array();
+	test_lxc_deslashify();
 
 	exit(EXIT_SUCCESS);
 }

From 3d5658d167db8866d5cd3b4b89f0e4becc735719 Mon Sep 17 00:00:00 2001
From: Denis Pynkin <denis_pynkin at epam.com>
Date: Mon, 26 Sep 2016 20:49:47 +0300
Subject: [PATCH 162/334] Fix for ALTLinux container creation in all branches

Use 'apt-conf' virtual package for ALTLinux default packages set

Signed-off-by: Denis Pynkin <denis_pynkin at epam.com>
---
 templates/lxc-altlinux.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-altlinux.in b/templates/lxc-altlinux.in
index 57c6274..69c18d4 100644
--- a/templates/lxc-altlinux.in
+++ b/templates/lxc-altlinux.in
@@ -178,7 +178,7 @@ download_altlinux()
     APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y"
     PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")"
     # if no configuration file $profile -- fall back to default list of packages
-    [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt apt-conf-sisyphus etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon"
+    [ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt apt-conf etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon"
 
     mkdir -p $INSTALL_ROOT/var/lib/rpm
     rpm --root $INSTALL_ROOT  --initdb

From f9f676d7dce657e7945ac3c27400b7f64ab75699 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Mon, 26 Sep 2016 22:05:54 +0200
Subject: [PATCH 163/334] utils: lxc_deslashify() free memory

Make sure we always free any memory that was allocated by the call to
lxc_normalize_path().

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index ebf3ad9..2029e33 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -718,6 +718,7 @@ char **lxc_normalize_path(const char *path)
 
 bool lxc_deslashify(char **path)
 {
+	bool ret = false;
 	char *p;
 	char **parts = NULL;
 	size_t n, len;
@@ -729,28 +730,33 @@ bool lxc_deslashify(char **path)
 	/* We'll end up here if path == "///" or path == "". */
 	if (!*parts) {
 		len = strlen(*path);
-		if (!len)
-			return true;
+		if (!len) {
+			ret = true;
+			goto out;
+		}
 		n = strcspn(*path, "/");
 		if (n == len) {
 			p = strdup("/");
 			if (!p)
-				return false;
+				goto out;
 			free(*path);
 			*path = p;
-			return true;
+			ret = true;
+			goto out;
 		}
 	}
 
 	p = lxc_string_join("/", (const char **)parts, **path == '/');
-	lxc_free_array((void **)parts, free);
 	if (!p)
-		return false;
+		goto out;
 
 	free(*path);
 	*path = p;
+	ret = true;
 
-	return true;
+out:
+	lxc_free_array((void **)parts, free);
+	return ret;
 }
 
 char *lxc_append_paths(const char *first, const char *second)

From fbe7891bd38e5db9d2cb97f5779f546c9d0bf959 Mon Sep 17 00:00:00 2001
From: Roman Mueller <roman.mueller at gmail.com>
Date: Wed, 28 Sep 2016 10:03:39 +0200
Subject: [PATCH 164/334] Fix spelling of CentOS in the templates

Signed-off-by: Roman Mueller <roman.mueller at gmail.com>
---
 templates/lxc-centos.in   | 26 +++++++++++++-------------
 templates/lxc-download.in |  2 +-
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in
index 051faef..2c444e4 100644
--- a/templates/lxc-centos.in
+++ b/templates/lxc-centos.in
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 #
-# template script for generating centos container for LXC
+# template script for generating CentOS container for LXC
 
 #
 # lxc: linux Container library
@@ -71,7 +71,7 @@ default_path=@LXCPATH@
 lxc_network_type=veth
 lxc_network_link=lxcbr0
 
-# is this centos?
+# is this CentOS?
 # Alow for weird remixes like the Raspberry Pi
 #
 # Use the Mitre standard CPE identifier for the release ID if possible...
@@ -161,7 +161,7 @@ force_mknod()
 configure_centos()
 {
 
-    # disable selinux in centos
+    # disable selinux in CentOS
     mkdir -p $rootfs_path/selinux
     echo 0 > $rootfs_path/selinux/enforce
 
@@ -404,7 +404,7 @@ EOF
 download_centos()
 {
 
-    # check the mini centos was not already downloaded
+    # check the mini CentOS was not already downloaded
     INSTALL_ROOT=$cache/partial
     mkdir -p $INSTALL_ROOT
     if [ $? -ne 0 ]; then
@@ -412,8 +412,8 @@ download_centos()
     return 1
     fi
 
-    # download a mini centos into a cache
-    echo "Downloading centos minimal ..."
+    # download a mini CentOS into a cache
+    echo "Downloading CentOS minimal ..."
     YUM0="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
 
     if yum -h | grep -q 'releasever=RELEASEVER'; then
@@ -508,7 +508,7 @@ EOF
 copy_centos()
 {
 
-    # make a local copy of the mini centos
+    # make a local copy of the mini CentOS
     echo -n "Copying rootfs to $rootfs_path ..."
     #cp -a $cache/rootfs-$arch $rootfs_path || return 1
     # i prefer rsync (no reason really)
@@ -542,14 +542,14 @@ install_centos()
     if [ ! -e "$cache/rootfs" ]; then
         download_centos
         if [ $? -ne 0 ]; then
-            echo "Failed to download 'centos base'"
+            echo "Failed to download 'CentOS base'"
             return 1
         fi
     else
         echo "Cache found. Updating..."
         update_centos
         if [ $? -ne 0 ]; then
-            echo "Failed to update 'centos base', continuing with last known good cache"
+            echo "Failed to update 'CentOS base', continuing with last known good cache"
         else
             echo "Update finished"
         fi
@@ -663,7 +663,7 @@ clean()
             exit 1
         fi
 
-        echo -n "Purging the download cache for centos-$release..."
+        echo -n "Purging the download cache for CentOS-$release..."
         rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
         exit 0
 
@@ -682,7 +682,7 @@ Mandatory args:
 Optional args:
   -p,--path         path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
   -c,--clean        clean the cache
-  -R,--release      Centos release for the new container. if the host is Centos, then it will defaultto the host's release.
+  -R,--release      CentOS release for the new container. If the host is CentOS, then it will default to the host's release.
      --fqdn         fully qualified domain name (FQDN) for DNS and system naming
      --repo         repository to use (url)
   -a,--arch         Define what arch the container will be [i686,x86_64]
@@ -870,13 +870,13 @@ fi
 
 install_centos
 if [ $? -ne 0 ]; then
-    echo "failed to install centos"
+    echo "failed to install CentOS"
     exit 1
 fi
 
 configure_centos
 if [ $? -ne 0 ]; then
-    echo "failed to configure centos for a container"
+    echo "failed to configure CentOS for a container"
     exit 1
 fi
 
diff --git a/templates/lxc-download.in b/templates/lxc-download.in
index 4a67a7c..e0ffdb2 100644
--- a/templates/lxc-download.in
+++ b/templates/lxc-download.in
@@ -577,7 +577,7 @@ for file in $TEMPLATE_FILES; do
     sed -i "s#LXC_HOOK_DIR#$LXC_HOOK_DIR#g" $file
 done
 
-# prevent mingetty from calling vhangup(2) since it fails with userns on Centos / Oracle
+# prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle
 if [ -f ${LXC_ROOTFS}/etc/init/tty.conf ]; then
     sed -i 's|mingetty|mingetty --nohangup|' ${LXC_ROOTFS}/etc/init/tty.conf
 fi

From 51a43951e0bb20aacc35cba749fe948fa11d1b2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 4 Oct 2016 18:31:29 +0200
Subject: [PATCH 165/334] Define LXC_DEVEL to detect development releases
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This can be used by downstreams to improve their "feature" checks.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac         | 2 ++
 src/lxc/version.h.in | 1 +
 2 files changed, 3 insertions(+)

diff --git a/configure.ac b/configure.ac
index 6c512c0..39dec02 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,7 @@
 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
 
+m4_define([lxc_devel], 0)
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
 m4_define([lxc_version_micro], 4)
@@ -24,6 +25,7 @@ AC_SUBST([LXC_VERSION_MINOR], [lxc_version_minor])
 AC_SUBST([LXC_VERSION_MICRO], [lxc_version_micro])
 AC_SUBST([LXC_VERSION_ABI], [lxc_version_abi])
 AC_SUBST([LXC_VERSION], [lxc_version])
+AC_SUBST([LXC_DEVEL], [lxc_devel])
 
 AC_CONFIG_SRCDIR([configure.ac])
 AC_CONFIG_AUX_DIR([config])
diff --git a/src/lxc/version.h.in b/src/lxc/version.h.in
index cd1b6eb..5a78f22 100644
--- a/src/lxc/version.h.in
+++ b/src/lxc/version.h.in
@@ -23,6 +23,7 @@
 #ifndef __LXC_VERSION_H
 #define __LXC_VERSION_H
 
+#define LXC_DEVEL @LXC_DEVEL@
 #define LXC_VERSION_MAJOR @LXC_VERSION_MAJOR@
 #define LXC_VERSION_MINOR @LXC_VERSION_MINOR@
 #define LXC_VERSION_MICRO @LXC_VERSION_MICRO@

From 3a61be8ed23912c07bacf34069b7475c5dcf0b28 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 29 Sep 2016 10:44:09 +0200
Subject: [PATCH 166/334] tools: lxc-checkconfig conditionalize devpts check

Only check for DEVPTS_MULTIPLE_INSTANCES on kernels < 4.7.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc-checkconfig.in | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/lxc/tools/lxc-checkconfig.in b/src/lxc/tools/lxc-checkconfig.in
index 29586f8..61627e0 100644
--- a/src/lxc/tools/lxc-checkconfig.in
+++ b/src/lxc/tools/lxc-checkconfig.in
@@ -72,6 +72,16 @@ if gunzip -tq < $CONFIG 2>/dev/null; then
     CAT="zcat"
 fi
 
+KVER_MAJOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
+    sed -r 's/.* ([0-9])\.[0-9]{1,2}\.[0-9]{1,3}.*/\1/')
+if [ "$KVER_MAJOR" = "2" ]; then
+KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
+    sed -r 's/.* 2.6.([0-9]{2}).*/\1/')
+else
+KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
+    sed -r 's/.* [0-9]\.([0-9]{1,3})\.[0-9]{1,3}.*/\1/')
+fi
+
 echo "--- Namespaces ---"
 echo -n "Namespaces: " && is_enabled CONFIG_NAMESPACES yes
 echo -n "Utsname namespace: " && is_enabled CONFIG_UTS_NS
@@ -79,7 +89,9 @@ echo -n "Ipc namespace: " && is_enabled CONFIG_IPC_NS yes
 echo -n "Pid namespace: " && is_enabled CONFIG_PID_NS yes
 echo -n "User namespace: " && is_enabled CONFIG_USER_NS
 echo -n "Network namespace: " && is_enabled CONFIG_NET_NS
-echo -n "Multiple /dev/pts instances: " && is_enabled DEVPTS_MULTIPLE_INSTANCES
+if ([ $KVER_MAJOR -lt 4 ]) || ([ $KVER_MAJOR -eq 4 ] && [ $KVER_MINOR -lt 7 ]); then
+	echo -n "Multiple /dev/pts instances: " && is_enabled DEVPTS_MULTIPLE_INSTANCES
+fi
 echo
 echo "--- Control groups ---"
 
@@ -89,15 +101,6 @@ print_cgroups() {
 }
 
 CGROUP_MNT_PATH=`print_cgroups cgroup /proc/self/mounts | head -n 1`
-KVER_MAJOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
-    sed -r 's/.* ([0-9])\.[0-9]{1,2}\.[0-9]{1,3}.*/\1/')
-if [ "$KVER_MAJOR" = "2" ]; then
-KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
-    sed -r 's/.* 2.6.([0-9]{2}).*/\1/')
-else
-KVER_MINOR=$($CAT $CONFIG | grep '^# Linux.*Kernel Configuration' | \
-    sed -r 's/.* [0-9]\.([0-9]{1,3})\.[0-9]{1,3}.*/\1/')
-fi
 
 echo -n "Cgroup: " && is_enabled CONFIG_CGROUPS yes
 

From 357e023b493b4c4fd27d852ba6eda9a73e5cdd7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 5 Oct 2016 11:45:37 +0200
Subject: [PATCH 167/334] change version to 2.0.5 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 39dec02..0c0a211 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 m4_define([lxc_devel], 0)
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 4)
+m4_define([lxc_version_micro], 5)
 m4_define([lxc_version_beta], [])
 m4_define([lxc_version_abi], 1.2.0)
 

From 32a2ca497302137b25d02b734c63cd8513b4870d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 13:49:13 +0200
Subject: [PATCH 168/334] utils: make detect_ramfs_rootfs() return bool

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 28 ++++++++++++++++------------
 src/lxc/utils.h |  2 +-
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 2029e33..c912fe8 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1158,36 +1158,40 @@ bool switch_to_ns(pid_t pid, const char *ns) {
  * IIUC, so long as we've chrooted so that rootfs is not our root,
  * the rootfs entry should always be skipped in mountinfo contents.
  */
-int detect_ramfs_rootfs(void)
+bool detect_ramfs_rootfs(void)
 {
-	char buf[LINELEN], *p;
 	FILE *f;
+	char *p, *p2;
+	char *line = NULL;
+	size_t len = 0;
 	int i;
-	char *p2;
 
 	f = fopen("/proc/self/mountinfo", "r");
 	if (!f)
-		return 0;
-	while (fgets(buf, LINELEN, f)) {
-		for (p = buf, i=0; p && i < 4; i++)
-			p = strchr(p+1, ' ');
+		return false;
+
+	while (getline(&line, &len, f) != -1) {
+		for (p = line, i = 0; p && i < 4; i++)
+			p = strchr(p + 1, ' ');
 		if (!p)
 			continue;
-		p2 = strchr(p+1, ' ');
+		p2 = strchr(p + 1, ' ');
 		if (!p2)
 			continue;
 		*p2 = '\0';
-		if (strcmp(p+1, "/") == 0) {
+		if (strcmp(p + 1, "/") == 0) {
 			// this is '/'.  is it the ramfs?
-			p = strchr(p2+1, '-');
+			p = strchr(p2 + 1, '-');
 			if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) {
+				free(line);
 				fclose(f);
-				return 1;
+				return true;
 			}
 		}
 	}
+	free(line);
 	fclose(f);
-	return 0;
+	return false;
 }
 
 char *on_path(char *cmd, const char *rootfs) {
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 88719a0..a0fa0e2 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -293,7 +293,7 @@ extern bool dir_exists(const char *path);
 uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
 
 int detect_shared_rootfs(void);
-int detect_ramfs_rootfs(void);
+bool detect_ramfs_rootfs(void);
 char *on_path(char *cmd, const char *rootfs);
 bool file_exists(const char *f);
 bool cgns_supported(void);

From ac920ef6d37f6d741353adf2e78702546a1a1237 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 14:51:01 +0200
Subject: [PATCH 169/334] tests: add test for detect_ramfs_rootfs()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 .gitignore                 |   2 +-
 src/tests/Makefile.am      |   3 +
 src/tests/lxc-test-utils.c | 163 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 67a8692..5c4618e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,7 +92,7 @@ src/tests/lxc-test-shutdowntest
 src/tests/lxc-test-snapshot
 src/tests/lxc-test-startone
 src/tests/lxc-test-usernic
-src/tests/lxc-test-utils
+src/tests/lxc-test-utils*
 src/tests/lxc-usernic-test
 
 config/compile
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index cffc742..cbc0418 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -101,3 +101,6 @@ EXTRA_DIST = \
 	shutdowntest.c \
 	snapshot.c \
 	startone.c
+
+clean-local:
+	rm -f lxc-test-utils-*
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 5b213c8..081ed4b 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -22,9 +22,16 @@
  */
 
 #define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include "lxctest.h"
 #include "utils.h"
@@ -60,6 +67,161 @@ void test_lxc_deslashify(void)
 	free(s);
 }
 
+void test_detect_ramfs_rootfs(void)
+{
+	size_t i;
+	int ret;
+	int fret = EXIT_FAILURE;
+	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 7 /* /ns/mnt */ + 1 /* \0 */;
+	char path[len];
+	int init_ns = -1;
+	char tmpf1[] = "lxc-test-utils-XXXXXX";
+	char tmpf2[] = "lxc-test-utils-XXXXXX";
+	int fd1 = -1, fd2 = -1;
+	FILE *fp1 = NULL, *fp2 = NULL;
+	char *mountinfo[] = {
+		"18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw",
+		"19 24 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:13 - proc proc rw",
+		"20 24 0:6 / /dev rw,nosuid,relatime shared:2 - devtmpfs udev rw,size=4019884k,nr_inodes=1004971,mode=755",
+		"21 20 0:14 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000",
+		"22 24 0:18 / /run rw,nosuid,noexec,relatime shared:5 - tmpfs tmpfs rw,size=807912k,mode=755",
+
+		/* This is what we care about. */
+		"24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099",
+
+		"25 18 0:12 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw",
+		"26 20 0:20 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw",
+		"27 22 0:21 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k",
+		"28 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755",
+		"29 28 0:23 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd",
+		"30 18 0:24 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:11 - pstore pstore rw",
+		"31 18 0:25 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:12 - efivarfs efivarfs rw",
+		"32 28 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,cpu,cpuacct",
+		"33 28 0:27 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,net_cls,net_prio",
+		"34 28 0:28 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,blkio",
+		"35 28 0:29 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,freezer",
+		"36 28 0:30 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,memory",
+		"37 28 0:31 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb",
+		"38 28 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,cpuset",
+		"39 28 0:33 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,devices",
+		"40 28 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,pids",
+		"41 28 0:35 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,perf_event",
+		"42 19 0:36 / /proc/sys/fs/binfmt_misc rw,relatime shared:24 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct",
+		"43 18 0:7 / /sys/kernel/debug rw,relatime shared:25 - debugfs debugfs rw",
+		"44 20 0:37 / /dev/hugepages rw,relatime shared:26 - hugetlbfs hugetlbfs rw",
+		"45 20 0:16 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw",
+		"46 43 0:9 / /sys/kernel/debug/tracing rw,relatime shared:28 - tracefs tracefs rw",
+		"76 18 0:38 / /sys/fs/fuse/connections rw,relatime shared:29 - fusectl fusectl rw",
+		"78 24 8:1 / /boot/efi rw,relatime shared:30 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro",
+	};
+
+	ret = snprintf(path, len, "/proc/self/ns/mnt");
+	if (ret < 0 || (size_t)ret >= len) {
+		lxc_error("%s\n", "Failed to create path with snprintf().");
+		goto non_test_error;
+	}
+
+	init_ns = open(path, O_RDONLY | O_CLOEXEC);
+	if (init_ns < 0) {
+		lxc_error("%s\n", "Failed to open initial mount namespace.");
+		goto non_test_error;
+	}
+
+	if (unshare(CLONE_NEWNS) < 0) {
+		lxc_error("%s\n", "Could not unshare mount namespace.");
+		close(init_ns);
+		init_ns = -1;
+		goto non_test_error;
+	}
+
+	if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
+		lxc_error("Failed to remount / private: %s.\n", strerror(errno));
+		goto non_test_error;
+	}
+
+	fd1 = mkstemp(tmpf1);
+	if (fd1 < 0) {
+		lxc_error("%s\n", "Could not create temporary file.");
+		goto non_test_error;
+	}
+
+	fd2 = mkstemp(tmpf2);
+	if (fd2 < 0) {
+		lxc_error("%s\n", "Could not create temporary file.");
+		goto non_test_error;
+	}
+
+	fp1 = fdopen(fd1, "r+");
+	if (!fp1) {
+		lxc_error("%s\n", "Could not fdopen() temporary file.");
+		goto non_test_error;
+	}
+
+	fp2 = fdopen(fd2, "r+");
+	if (!fp2) {
+		lxc_error("%s\n", "Could not fdopen() temporary file.");
+		goto non_test_error;
+	}
+
+	/* Test if it correctly detects - rootfs rootfs */
+	for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) {
+		if (fprintf(fp1, "%s\n", mountinfo[i]) < 0) {
+			lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]);
+			goto non_test_error;
+		}
+	}
+	fclose(fp1);
+	fp1 = NULL;
+
+	/* Test if it correctly fails to detect when no - rootfs rootfs */
+	for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) {
+		if (strcmp(mountinfo[i], "24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099") == 0)
+			continue;
+		if (fprintf(fp2, "%s\n", mountinfo[i]) < 0) {
+			lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]);
+			goto non_test_error;
+		}
+	}
+	fclose(fp2);
+	fp2 = NULL;
+
+	if (mount(tmpf1, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) {
+		lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\".");
+		goto non_test_error;
+	}
+
+	lxc_test_assert_abort(detect_ramfs_rootfs());
+
+	if (mount(tmpf2, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) {
+		lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\".");
+		goto non_test_error;
+	}
+
+	lxc_test_assert_abort(!detect_ramfs_rootfs());
+	fret = EXIT_SUCCESS;
+
+non_test_error:
+	if (fp1)
+		fclose(fp1);
+	else if (fd1 > 0)
+		close(fd1);
+	if (fp2)
+		fclose(fp2);
+	else if (fd2 > 0)
+		close(fd2);
+
+	if (init_ns > 0) {
+		if (setns(init_ns, 0) < 0) {
+			lxc_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno));
+			fret = EXIT_FAILURE;
+		}
+		close(init_ns);
+	}
+	if (fret == EXIT_SUCCESS)
+		return;
+	exit(fret);
+}
+
 void test_lxc_string_replace(void)
 {
 	char *s;
@@ -117,6 +279,7 @@ int main(int argc, char *argv[])
 	test_lxc_string_replace();
 	test_lxc_string_in_array();
 	test_lxc_deslashify();
+	test_detect_ramfs_rootfs();
 
 	exit(EXIT_SUCCESS);
 }

From 8d45c62cde0efc54a4159a51752c42baf6cf5f28 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 8 Oct 2016 14:08:21 +0200
Subject: [PATCH 170/334] add Documentation entries to lxc and lxc@ units

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/systemd/lxc.service.in  | 1 +
 config/init/systemd/lxc at .service.in | 1 +
 2 files changed, 2 insertions(+)

diff --git a/config/init/systemd/lxc.service.in b/config/init/systemd/lxc.service.in
index 9876155..cd61996 100644
--- a/config/init/systemd/lxc.service.in
+++ b/config/init/systemd/lxc.service.in
@@ -2,6 +2,7 @@
 Description=LXC Container Initialization and Autoboot Code
 After=network.target lxc-net.service
 Wants=lxc-net.service
+Documentation=man:lxc-autostart man:lxc
 
 [Service]
 Type=oneshot
diff --git a/config/init/systemd/lxc at .service.in b/config/init/systemd/lxc at .service.in
index ba8cc1b..44d11e8 100644
--- a/config/init/systemd/lxc at .service.in
+++ b/config/init/systemd/lxc at .service.in
@@ -3,6 +3,7 @@ Description=LXC Container: %i
 # This pulls in apparmor, dev-setup, lxc-net
 After=lxc.service
 Wants=lxc.service
+Documentation=man:lxc-start man:lxc
 
 [Service]
 Type=simple

From 51ee3c5891d7e95247adb6b605a2e3ab591dc449 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 8 Oct 2016 18:29:30 +0200
Subject: [PATCH 171/334] mark the python examples as having utf-8 encoding
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

this allows running them also under Python2, which otherwise
would choke on Stéphane's name and error out with
 SyntaxError: Non-ASCII character '\xc3' in file …

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 src/python-lxc/examples/api_test.py      | 1 +
 src/python-lxc/examples/pyconsole-vte.py | 1 +
 src/python-lxc/examples/pyconsole.py     | 1 +
 3 files changed, 3 insertions(+)

diff --git a/src/python-lxc/examples/api_test.py b/src/python-lxc/examples/api_test.py
index eab4f46..b8b5ee6 100755
--- a/src/python-lxc/examples/api_test.py
+++ b/src/python-lxc/examples/api_test.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 # api_test.py: Test/demo of the python3-lxc API
 #
diff --git a/src/python-lxc/examples/pyconsole-vte.py b/src/python-lxc/examples/pyconsole-vte.py
index 8e07f15..8a98359 100755
--- a/src/python-lxc/examples/pyconsole-vte.py
+++ b/src/python-lxc/examples/pyconsole-vte.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 # pyconsole-vte: Example program showing use of console functions
 #                in the lxc python binding
diff --git a/src/python-lxc/examples/pyconsole.py b/src/python-lxc/examples/pyconsole.py
index a9238a0..2b0cd14 100755
--- a/src/python-lxc/examples/pyconsole.py
+++ b/src/python-lxc/examples/pyconsole.py
@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 # pyconsole: Example program showing use of console functions
 #            in the lxc python binding

From 934ecd08fc4ecc116f6ec16f14a63cd740b392d0 Mon Sep 17 00:00:00 2001
From: Lans Zhang <jia.zhang at windriver.com>
Date: Mon, 10 Oct 2016 21:49:55 +0800
Subject: [PATCH 172/334] log: sanity check the returned value from snprintf()

The returned value from snprintf() should be checked carefully.

This bug can be leveraged to execute arbitrary code through carefully
constructing the payload, e.g,

lxc-freeze -n `python -c "print 'AAAAAAAA' + 'B'*959"` -P PADPAD -o /tmp/log

This command running on Ubuntu 14.04 (x86-64) can cause a segment fault.

Signed-off-by: Lans Zhang <jia.zhang at windriver.com>
---
 src/lxc/log.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 11d4bbf..525e4f0 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -101,10 +101,13 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 		     event->locinfo->file, event->locinfo->func,
 		     event->locinfo->line);
 
-	n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
-		       *event->vap);
+	if (n < 0)
+		return n;
 
-	if (n >= sizeof(buffer) - 1) {
+	if (n < sizeof(buffer) - 1)
+		n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
+			       *event->vap);
+	else {
 		WARN("truncated next event from %d to %zd bytes", n,
 		     sizeof(buffer));
 		n = sizeof(buffer) - 1;

From 51ee5e0cec79793575ee8c64909b965a132a064d Mon Sep 17 00:00:00 2001
From: Jakub Jirutka <jakub at jirutka.cz>
Date: Wed, 12 Oct 2016 13:32:18 +0200
Subject: [PATCH 173/334] lxc-alpine: mount /dev/shm as tmpfs

Signed-off-by: Jakub Jirutka <jakub at jirutka.cz>
---
 config/templates/alpine.common.conf.in | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/config/templates/alpine.common.conf.in b/config/templates/alpine.common.conf.in
index 55ea3d2..1be61f7 100644
--- a/config/templates/alpine.common.conf.in
+++ b/config/templates/alpine.common.conf.in
@@ -19,5 +19,8 @@ lxc.cap.drop = sys_tty_config
 lxc.cap.drop = syslog
 lxc.cap.drop = wake_alarm
 
-# Mount tmpfs under /run.
+# Mount /run as tmpfs.
 lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0
+
+# Mount /dev/shm as tmpfs; needed for building python and possibly other packages.
+lxc.mount.entry=shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0

From 2b67aaee94926d07dba6c6fea97d8ed138afa9d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 13 Oct 2016 14:32:03 -0400
Subject: [PATCH 174/334] archlinux: Do DHCP on eth0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 templates/lxc-archlinux.in | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/templates/lxc-archlinux.in b/templates/lxc-archlinux.in
index 8aa1d8d..9d4326e 100644
--- a/templates/lxc-archlinux.in
+++ b/templates/lxc-archlinux.in
@@ -91,6 +91,15 @@ configure_arch() {
        [ "${r#nameserver}" = "$r" ] || echo "$r"
     done < /etc/resolv.conf > "${rootfs_path}/etc/resolv.conf"
 
+    # network configuration
+    cat > "${rootfs_path}/etc/systemd/network/eth0.network" << EOF
+[Match]
+Name=eth0
+
+[Network]
+DHCP=ipv4
+EOF
+
     # chroot and configure system
     arch-chroot "${rootfs_path}" /bin/bash -s << EOF
 mkdir /run/lock
@@ -110,6 +119,9 @@ sed -e 's/^ConditionPathIsReadWrite=\/proc\/sys\/$/ConditionPathIsReadWrite=\/pr
 # initialize pacman keyring
 pacman-key --init
 pacman-key --populate archlinux
+
+# enable networkd
+systemctl enable systemd-networkd
 EOF
     # enable getty on active ttys
     local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty" | head -n1 | cut -d= -f2 | tr -d "[:blank:]")

From b91f0faeaa847774b7645b9172cc9a58277d1ed0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 13 Oct 2016 15:02:56 -0400
Subject: [PATCH 175/334] archlinux: Fix resolving
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 templates/lxc-archlinux.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/templates/lxc-archlinux.in b/templates/lxc-archlinux.in
index 9d4326e..c52459d 100644
--- a/templates/lxc-archlinux.in
+++ b/templates/lxc-archlinux.in
@@ -122,6 +122,8 @@ pacman-key --populate archlinux
 
 # enable networkd
 systemctl enable systemd-networkd
+systemctl enable systemd-resolved
+ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
 EOF
     # enable getty on active ttys
     local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty" | head -n1 | cut -d= -f2 | tr -d "[:blank:]")

From 3180209096685d2bc25886cb538a5be8ce372f9d Mon Sep 17 00:00:00 2001
From: Jafar Al-Gharaibeh <to.jafar at gmail.com>
Date: Thu, 13 Oct 2016 18:35:29 -0500
Subject: [PATCH 176/334] Drop leftover references to lxc_strerror().

lxc_strerror() was dropped long time ago, in 2009 to be exact.

Related commit:
https://github.com/lxc/lxc/commit/7cee8789514fb42d6a48d50b904e24284f5526e3

Signed-off-by: Jafar Al-Gharaibeh <to.jafar at gmail.com>
---
 src/lxc/arguments.h | 2 --
 src/lxc/lxc.h       | 8 --------
 2 files changed, 10 deletions(-)

diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
index 956cb37..4e7591f 100644
--- a/src/lxc/arguments.h
+++ b/src/lxc/arguments.h
@@ -161,8 +161,6 @@ extern int lxc_arguments_parse(struct lxc_arguments *args,
 
 extern int lxc_arguments_str_to_int(struct lxc_arguments *args, const char *str);
 
-extern const char *lxc_strerror(int errnum);
-
 #define lxc_error(arg, fmt, args...) if (!(arg)->quiet)			\
 	fprintf(stderr, "%s: " fmt "\n", (arg)->progname,  ## args)
 
diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
index a9fa80e..c6182d4 100644
--- a/src/lxc/lxc.h
+++ b/src/lxc/lxc.h
@@ -119,14 +119,6 @@ extern int lxc_cgroup_set(const char *filename, const char *value, const char *n
 extern int lxc_cgroup_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
 
 /*
- * Retrieve the error string associated with the error returned by
- * the function.
- * @error : the value of the error
- * Returns a string on success or NULL otherwise.
- */
-extern const char *lxc_strerror(int error);
-
-/*
  * Create and return a new lxccontainer struct.
  */
 extern struct lxc_container *lxc_container_new(const char *name, const char *configpath);

From 01c05c821093dc854def146d4bab62885d8eb664 Mon Sep 17 00:00:00 2001
From: Po-Hsu Lin <po-hsu.lin at canonical.com>
Date: Fri, 14 Oct 2016 16:17:30 +0800
Subject: [PATCH 177/334] tests: fix image download for s390x

Make release selection more flexible.
Update the KNOWN_RELEAES list, add yakkety and remove vivid.

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 src/tests/lxc-test-apparmor-mount | 14 +++++++++++++-
 src/tests/lxc-test-autostart      | 15 ++++++++++++++-
 src/tests/lxc-test-unpriv         | 14 +++++++++++++-
 src/tests/lxc-test-usernic.in     | 14 +++++++++++++-
 templates/lxc-ubuntu-cloud.in     |  2 +-
 5 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/src/tests/lxc-test-apparmor-mount b/src/tests/lxc-test-apparmor-mount
index 3fd3f5a..7ec5aad 100755
--- a/src/tests/lxc-test-apparmor-mount
+++ b/src/tests/lxc-test-apparmor-mount
@@ -42,6 +42,7 @@ run_cmd() {
 }
 
 DONE=0
+KNOWN_RELEASES="precise trusty wily xenial yakkety"
 MOUNTSR=/sys/kernel/security/apparmor/features/mount
 dnam=`mktemp -d`
 cname=`basename $dnam`
@@ -144,7 +145,18 @@ run_cmd mkdir -p $HDIR/.cache/lxc
     cp -R /var/cache/lxc/download $HDIR/.cache/lxc && \
     chown -R $TUSER: $HDIR/.cache/lxc
 
-run_cmd lxc-create -t download -n $cname -- -d ubuntu -r trusty -a $ARCH
+# default release is trusty, or the systems release if recognized
+release=trusty
+if [ -f /etc/lsb-release ]; then
+    . /etc/lsb-release
+    rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
+        rels="$KNOWN_RELEASES"
+    for r in $rels; do
+        [ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
+    done
+fi
+
+run_cmd lxc-create -t download -n $cname -- -d ubuntu -r $release -a $ARCH
 
 echo "test default confined container"
 run_cmd lxc-start -n $cname -d
diff --git a/src/tests/lxc-test-autostart b/src/tests/lxc-test-autostart
index 5b606f5..76de54b 100755
--- a/src/tests/lxc-test-autostart
+++ b/src/tests/lxc-test-autostart
@@ -22,6 +22,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 DONE=0
+KNOWN_RELEASES="precise trusty wily xenial yakkety"
 cleanup() {
 	lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true
 
@@ -42,7 +43,19 @@ set -eu
 
 # Create a container
 CONTAINER_NAME=lxc-test-auto
-lxc-create -t download -n $CONTAINER_NAME -- -d ubuntu -r trusty -a $ARCH
+
+# default release is trusty, or the systems release if recognized
+release=trusty
+if [ -f /etc/lsb-release ]; then
+    . /etc/lsb-release
+    rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
+        rels="$KNOWN_RELEASES"
+    for r in $rels; do
+        [ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
+    done
+fi
+
+lxc-create -t download -n $CONTAINER_NAME -- -d ubuntu -r $release -a $ARCH
 CONTAINER_PATH=$(dirname $(lxc-info -n $CONTAINER_NAME -c lxc.rootfs -H))
 cp $CONTAINER_PATH/config $CONTAINER_PATH/config.bak
 
diff --git a/src/tests/lxc-test-unpriv b/src/tests/lxc-test-unpriv
index f3a7910..eddfd55 100755
--- a/src/tests/lxc-test-unpriv
+++ b/src/tests/lxc-test-unpriv
@@ -30,6 +30,7 @@ fi
 which newuidmap >/dev/null 2>&1 || { echo "'newuidmap' command is missing" >&2; exit 1; }
 
 DONE=0
+KNOWN_RELEASES="precise trusty wily xenial yakkety"
 cleanup() {
 	cd /
 
@@ -119,13 +120,24 @@ else
 	done
 fi
 
+# default release is trusty, or the systems release if recognized
+release=trusty
+if [ -f /etc/lsb-release ]; then
+    . /etc/lsb-release
+    rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
+        rels="$KNOWN_RELEASES"
+    for r in $rels; do
+        [ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
+    done
+fi
+
 # Copy the download template cache if available
 run_cmd mkdir -p $HDIR/.cache/lxc
 [ -d /var/cache/lxc/download ] && \
     cp -R /var/cache/lxc/download $HDIR/.cache/lxc && \
     chown -R $TUSER: $HDIR/.cache/lxc
 
-run_cmd lxc-create -t download -n c1 -- -d ubuntu -r trusty -a $ARCH
+run_cmd lxc-create -t download -n c1 -- -d ubuntu -r $release -a $ARCH
 
 # Make sure we can start it - twice
 
diff --git a/src/tests/lxc-test-usernic.in b/src/tests/lxc-test-usernic.in
index 6a5650d..d63b6bb 100755
--- a/src/tests/lxc-test-usernic.in
+++ b/src/tests/lxc-test-usernic.in
@@ -24,6 +24,7 @@
 # This test assumes an Ubuntu host
 
 DONE=0
+KNOWN_RELEASES="precise trusty wily xenial yakkety"
 LXC_USER_NIC="@LIBEXECDIR@/lxc/lxc-user-nic"
 
 cleanup() {
@@ -132,8 +133,19 @@ if type dpkg >/dev/null 2>&1; then
 	ARCH=$(dpkg --print-architecture)
 fi
 
+# default release is trusty, or the systems release if recognized
+release=trusty
+if [ -f /etc/lsb-release ]; then
+    . /etc/lsb-release
+    rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
+        rels="$KNOWN_RELEASES"
+    for r in $rels; do
+        [ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
+    done
+fi
+
 # Create three containers
-run_cmd "lxc-create -t download -n b1 -- -d ubuntu -r trusty -a $ARCH"
+run_cmd "lxc-create -t download -n b1 -- -d ubuntu -r $release -a $ARCH"
 run_cmd "lxc-start -n b1 -d"
 p1=$(run_cmd "lxc-info -n b1 -p -H")
 
diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in
index 0b53cb1..7ae10c8 100644
--- a/templates/lxc-ubuntu-cloud.in
+++ b/templates/lxc-ubuntu-cloud.in
@@ -25,7 +25,7 @@ STATE_DIR="@LOCALSTATEDIR@"
 HOOK_DIR="@LXCHOOKDIR@"
 CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep"
 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
-KNOWN_RELEASES="precise trusty vivid wily xenial"
+KNOWN_RELEASES="precise trusty wily xenial yakkety"
 skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0}
 
 # Make sure the usual locations are in PATH

From 1c8df1386f7a397e9f7b3ea78956ad300be95064 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 14 Oct 2016 14:20:16 +0200
Subject: [PATCH 178/334] tools: fix coding style in lxc_attach

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_attach.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 23d63a2..51fd536 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -154,7 +154,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
 	case 'L':
 		args->console_log = arg;
 		break;
-	case 'f': args->rcfile = arg; break;
+	case 'f':
+		args->rcfile = arg;
+		break;
 	}
 
 	return 0;

From f42cf2dfc5a854a4ab110a36b7e7bb5f4f32f391 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 14 Oct 2016 14:20:41 +0200
Subject: [PATCH 179/334] tools: make overlay valid backend

So far, users could only create overlay snapshots by specifying -B overlayfs
and not with -B overlay. This adds support for -B overlay.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_copy.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 5a6ced2..1c64cd5 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -587,6 +587,8 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
 			return -1;
 		break;
 	case 'B':
+		if (strcmp(arg, "overlay") == 0)
+			arg = "overlayfs";
 		args->bdevtype = arg;
 		break;
 	case 'L':

From 359467743d707d08fda029fa6e957a93bc8dc7ef Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 14 Oct 2016 15:27:24 +0200
Subject: [PATCH 180/334] tools: better error reporting for lxc-start

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_start.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 25d8f19..eaa8da4 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -86,7 +86,7 @@ static int ensure_path(char **confpath, const char *path)
 			goto err;
 		}
 	}
-	err = 0;
+	err = EXIT_SUCCESS;
 
 err:
 	free(fullpath);
@@ -231,6 +231,12 @@ int main(int argc, char *argv[])
 		exit(err);
 	lxc_log_options_no_override();
 
+	if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+		if (!my_args.quiet)
+			fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
+		exit(err);
+	}
+
 	const char *lxcpath = my_args.lxcpath[0];
 
 	/*
@@ -275,9 +281,19 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	if (!c->is_defined(c)) {
+		fprintf(stderr, "Error: container %s is not defined\n", c->name);
+		goto out;
+	}
+
+	if (!c->may_control(c)) {
+		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
+		goto out;
+	}
+
 	if (c->is_running(c)) {
 		ERROR("Container is already running.");
-		err = 0;
+		err = EXIT_SUCCESS;
 		goto out;
 	}
 	/*

From d8953e37edd4128fb0edc3165f98b61e78d245f4 Mon Sep 17 00:00:00 2001
From: roedie <github at roedie.nl>
Date: Tue, 18 Oct 2016 16:55:16 +0200
Subject: [PATCH 181/334] alpine: Fix installing extra packages Signed-off-by:
 Sander Klein <github at roedie.nl>

---
 templates/lxc-alpine.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-alpine.in b/templates/lxc-alpine.in
index a6b3363..06616b3 100644
--- a/templates/lxc-alpine.in
+++ b/templates/lxc-alpine.in
@@ -251,7 +251,7 @@ install() {
 	ln -s "$apk_cache" etc/apk/cache
 	echo "$repo_url" > etc/apk/repositories
 
-	install_packages "$arch" alpine-base $extra_packages
+	install_packages "$arch" "alpine-base $extra_packages"
 	make_dev_nodes
 	setup_inittab
 	setup_hosts

From 2b6a98305e36becc1c6a867d8e48cfd45302ffc3 Mon Sep 17 00:00:00 2001
From: Jakub Jirutka <jakub at jirutka.cz>
Date: Tue, 18 Oct 2016 18:09:42 +0200
Subject: [PATCH 182/334] lxc-alpine: do not drop setfcap

Signed-off-by: Jakub Jirutka <jakub at jirutka.cz>
---
 config/templates/alpine.common.conf.in | 1 -
 1 file changed, 1 deletion(-)

diff --git a/config/templates/alpine.common.conf.in b/config/templates/alpine.common.conf.in
index 1be61f7..b344426 100644
--- a/config/templates/alpine.common.conf.in
+++ b/config/templates/alpine.common.conf.in
@@ -8,7 +8,6 @@ lxc.devttydir =
 lxc.cap.drop = audit_write
 lxc.cap.drop = ipc_owner
 lxc.cap.drop = mknod
-lxc.cap.drop = setfcap
 lxc.cap.drop = setpcap
 lxc.cap.drop = sys_nice
 lxc.cap.drop = sys_pacct

From 99f252a8bf4110da7a810cb0a5fa01aebfa02bdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 20 Oct 2016 16:35:36 -0400
Subject: [PATCH 183/334] s390x: Fix seccomp handling of personalities
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

There are no personalities for s390x, so don't list itself as one.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/lxc/seccomp.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 5069730..83b1cb4 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -378,15 +378,6 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 		if (!compat_ctx[0] || !compat_ctx[1])
 			goto bad;
 #endif
-#ifdef SCMP_ARCH_S390X
-	} else if (native_arch == lxc_seccomp_arch_s390x) {
-		cur_rule_arch = lxc_seccomp_arch_all;
-		compat_arch[0] = SCMP_ARCH_S390X;
-		compat_ctx[0] = get_new_ctx(lxc_seccomp_arch_s390x,
-				default_policy_action);
-		if (!compat_ctx[0])
-			goto bad;
-#endif
 	}
 
 	if (default_policy_action != SCMP_ACT_KILL) {

From 0a93fd77a20411cee6f5f8168051d98f30bed72e Mon Sep 17 00:00:00 2001
From: Po-Hsu Lin <po-hsu.lin at canonical.com>
Date: Fri, 21 Oct 2016 18:32:18 +0800
Subject: [PATCH 184/334] tools: correct the argument typo in lxc_copy

Correct the backingstorage typo in lxc_copy.

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 src/lxc/tools/lxc_copy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 1c64cd5..7427cd4 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -82,7 +82,7 @@ static const struct option my_longopts[] = {
 	{ "daemon", no_argument, 0, 'd'},
 	{ "ephemeral", no_argument, 0, 'e'},
 	{ "mount", required_argument, 0, 'm'},
-	{ "backingstore", required_argument, 0, 'B'},
+	{ "backingstorage", required_argument, 0, 'B'},
 	{ "fssize", required_argument, 0, 'L'},
 	{ "keepdata", no_argument, 0, 'D'},
 	{ "keepname", no_argument, 0, 'K'},

From 4082d0deb030b1b93ab8c0054c3f638252649084 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 21 Oct 2016 14:07:29 -0400
Subject: [PATCH 185/334] Use libtool for liblxc.so
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This should allow proper filtering of build flags for libraries and make
it easier to use PIE/PIC.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 Makefile.am                |  4 ++++
 autogen.sh                 |  1 +
 configure.ac               | 16 ++++++++++++++--
 src/lua-lxc/Makefile.am    | 19 +++++++++++++------
 src/lxc/Makefile.am        | 37 +++++++++++++++++++------------------
 src/lxc/version.h.in       |  2 +-
 src/python-lxc/setup.py.in | 19 ++++++++++++++++++-
 src/tests/Makefile.am      |  2 +-
 8 files changed, 71 insertions(+), 29 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 83714cb..4071ec9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,6 +2,7 @@
 
 ACLOCAL_AMFLAGS = -I config
 
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
 SUBDIRS = config src templates doc hooks
 DIST_SUBDIRS = config src templates doc hooks
 EXTRA_DIST = \
@@ -23,6 +24,9 @@ endif
 pcdatadir = $(libdir)/pkgconfig
 pcdata_DATA = lxc.pc
 
+libtool: $(LIBTOOL_DEPS)
+	$(SHELL) ./config.status libtool
+
 install-data-local:
 	$(MKDIR_P) $(DESTDIR)$(LXCPATH)
 	$(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/lxc
diff --git a/autogen.sh b/autogen.sh
index ca71ac5..4e9f1d8 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -24,6 +24,7 @@
 set -x
 
 test -d autom4te.cache && rm -rf autom4te.cache
+libtoolize || exit 1
 aclocal -I config || exit 1
 autoheader || exit 1
 autoconf || exit 1
diff --git a/configure.ac b/configure.ac
index 0c0a211..287e5d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,11 @@ m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
 m4_define([lxc_version_micro], 5)
 m4_define([lxc_version_beta], [])
-m4_define([lxc_version_abi], 1.2.0)
+
+m4_define([lxc_abi_major], 1)
+m4_define([lxc_abi_minor], 2)
+m4_define([lxc_abi_micro], 0)
+m4_define([lxc_abi], [lxc_abi_major.lxc_abi_minor.lxc_abi_micro])
 
 m4_define([lxc_version_base], [lxc_version_major.lxc_version_minor.lxc_version_micro])
 m4_define([lxc_version],
@@ -23,10 +27,14 @@ AC_SUBST(LXC_VERSION_BETA, lxc_version_beta)
 AC_SUBST([LXC_VERSION_MAJOR], [lxc_version_major])
 AC_SUBST([LXC_VERSION_MINOR], [lxc_version_minor])
 AC_SUBST([LXC_VERSION_MICRO], [lxc_version_micro])
-AC_SUBST([LXC_VERSION_ABI], [lxc_version_abi])
 AC_SUBST([LXC_VERSION], [lxc_version])
 AC_SUBST([LXC_DEVEL], [lxc_devel])
 
+AC_SUBST([LXC_ABI_MAJOR], [lxc_abi_major])
+AC_SUBST([LXC_ABI_MINOR], [lxc_abi_minor])
+AC_SUBST([LXC_ABI_MICRO], [lxc_abi_micro])
+AC_SUBST([LXC_ABI], [lxc_abi])
+
 AC_CONFIG_SRCDIR([configure.ac])
 AC_CONFIG_AUX_DIR([config])
 AC_CONFIG_HEADERS([src/config.h])
@@ -35,6 +43,10 @@ AC_CANONICAL_HOST
 AM_PROG_CC_C_O
 AC_GNU_SOURCE
 
+# libtool
+LT_INIT
+AC_SUBST([LIBTOOL_DEPS])
+
 # Detect the distribution. This is used for the default configuration and
 # for some distro-specific build options.
 AC_MSG_CHECKING([host distribution])
diff --git a/src/lua-lxc/Makefile.am b/src/lua-lxc/Makefile.am
index 9b73df1..348de8d 100644
--- a/src/lua-lxc/Makefile.am
+++ b/src/lua-lxc/Makefile.am
@@ -7,20 +7,27 @@ sodir=$(lualibdir)/lxc
 
 lua_DATA=lxc.lua
 
-so_PROGRAMS = core.so
-
-core_so_SOURCES = core.c
+lib_LTLIBRARIES = libcore.la
+libcore_la_SOURCES = core.c
 
 AM_CFLAGS=-I$(top_builddir)/src -I$(top_srcdir)/src $(LUA_CFLAGS) -DVERSION=\"$(VERSION)\" -DLXCPATH=\"$(LXCPATH)\"
 
-core_so_CFLAGS = -fPIC -DPIC $(AM_CFLAGS)
+libcore_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS)
 
-core_so_LDFLAGS = \
+libcore_la_LDFLAGS = \
 	-shared \
 	-L$(top_builddir)/src/lxc \
 	-Wl,-soname,core.so.$(firstword $(subst ., ,$(VERSION)))
 
-core_so_LDADD = -llxc
+libcore_la_LIBADD = -llxc
+
+install-exec-local: install-libLTLIBRARIES
+	mkdir -p $(DESTDIR)$(lualibdir)/lxc/
+	mv $(DESTDIR)$(libdir)/libcore.so.0.0.0 $(DESTDIR)$(lualibdir)/lxc/core.so
+	rm $(DESTDIR)$(libdir)/libcore.*
+
+uninstall-local:
+	$(RM) $(DESTDIR)$(lualibdir)/lxc/core.so*
 
 lxc.lua:
 
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index c38320f..8138a56 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -53,8 +53,6 @@ noinst_HEADERS += ../include/getsubopt.h
 endif
 
 sodir=$(libdir)
-# use PROGRAMS to avoid complains from automake
-so_PROGRAMS = liblxc.so
 
 LSM_SOURCES = \
 	lsm/nop.c \
@@ -68,7 +66,8 @@ if ENABLE_SELINUX
 LSM_SOURCES += lsm/selinux.c
 endif
 
-liblxc_so_SOURCES = \
+lib_LTLIBRARIES = liblxc.la
+liblxc_la_SOURCES = \
 	arguments.c arguments.h \
 	bdev/bdev.c bdev/bdev.h \
 	bdev/lxcaufs.c bdev/lxcaufs.h \
@@ -123,11 +122,11 @@ liblxc_so_SOURCES = \
 	$(LSM_SOURCES)
 
 if ENABLE_CGMANAGER
-liblxc_so_SOURCES += cgroups/cgmanager.c
+liblxc_la_SOURCES += cgroups/cgmanager.c
 endif
 
 if IS_BIONIC
-liblxc_so_SOURCES += \
+liblxc_la_SOURCES += \
 	../include/ifaddrs.c ../include/ifaddrs.h \
 	../include/openpty.c ../include/openpty.h \
 	../include/lxcmntent.c ../include/lxcmntent.h
@@ -135,7 +134,7 @@ endif
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
-liblxc_so_SOURCES += ../include/getline.c ../include/getline.h
+liblxc_la_SOURCES += ../include/getline.c ../include/getline.h
 endif
 endif
 
@@ -176,21 +175,22 @@ endif
 
 if ENABLE_SECCOMP
 AM_CFLAGS += -DHAVE_SECCOMP $(SECCOMP_CFLAGS)
-liblxc_so_SOURCES += seccomp.c
+liblxc_la_SOURCES += seccomp.c
 endif
 
-liblxc_so_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) -pthread
+liblxc_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS) -pthread
 
-liblxc_so_LDFLAGS = \
+liblxc_la_LDFLAGS = \
 	-pthread \
 	-shared \
-	-Wl,-soname,liblxc.so.$(firstword $(subst ., , at LXC_VERSION_ABI@))
+	-Wl,-soname,liblxc.so.$(firstword $(subst ., , at LXC_ABI@)) \
+	-version-info @LXC_ABI_MAJOR@
 
-liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS)
+liblxc_la_LIBADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS)
 
 if ENABLE_CGMANAGER
-liblxc_so_LDADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
-liblxc_so_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS)
+liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
+liblxc_la_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) $(NIH_DBUS_CFLAGS)
 endif
 
 bin_SCRIPTS = tools/lxc-checkconfig
@@ -242,7 +242,7 @@ AM_LDFLAGS = -Wl,-E
 if ENABLE_RPATH
 AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
 endif
-LDADD=liblxc.so @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
+LDADD=liblxc.la @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@
 
 lxc_attach_SOURCES = tools/lxc_attach.c
 lxc_autostart_SOURCES = tools/lxc_autostart.c
@@ -295,13 +295,14 @@ init_lxc_static_LDADD = @CAP_LIBS@
 init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF
 endif
 
-install-exec-local: install-soPROGRAMS
+install-exec-local: install-libLTLIBRARIES
 	mkdir -p $(DESTDIR)$(datadir)/lxc
 	install -c -m 644 lxc.functions $(DESTDIR)$(datadir)/lxc
-	mv $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so. at LXC_VERSION_ABI@
+	rm $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.1
+	mv $(DESTDIR)$(libdir)/liblxc.so.1.0.0 $(DESTDIR)$(libdir)/liblxc.so. at LXC_ABI@
 	cd $(DESTDIR)$(libdir); \
-	ln -sf liblxc.so. at LXC_VERSION_ABI@ liblxc.so.$(firstword $(subst ., , at LXC_VERSION_ABI@)); \
-	ln -sf liblxc.so.$(firstword $(subst ., , at LXC_VERSION_ABI@)) liblxc.so
+	ln -sf liblxc.so. at LXC_ABI@ liblxc.so.$(firstword $(subst ., , at LXC_ABI@)); \
+	ln -sf liblxc.so.$(firstword $(subst ., , at LXC_ABI@)) liblxc.so
 
 install-exec-hook:
 	chmod u+s $(DESTDIR)$(libexecdir)/lxc/lxc-user-nic
diff --git a/src/lxc/version.h.in b/src/lxc/version.h.in
index 5a78f22..7dba0f9 100644
--- a/src/lxc/version.h.in
+++ b/src/lxc/version.h.in
@@ -27,7 +27,7 @@
 #define LXC_VERSION_MAJOR @LXC_VERSION_MAJOR@
 #define LXC_VERSION_MINOR @LXC_VERSION_MINOR@
 #define LXC_VERSION_MICRO @LXC_VERSION_MICRO@
-#define LXC_VERSION_ABI "@LXC_VERSION_ABI@"
+#define LXC_VERSION_ABI "@LXC_ABI@"
 #define LXC_VERSION "@LXC_VERSION@"
 
 #endif
diff --git a/src/python-lxc/setup.py.in b/src/python-lxc/setup.py.in
index fcb676e..ef6d78b 100644
--- a/src/python-lxc/setup.py.in
+++ b/src/python-lxc/setup.py.in
@@ -23,6 +23,23 @@
 # USA
 
 import os, os.path
+
+# Fix build when PIE is enabled
+for var in ("LDFLAGS", "CFLAGS"):
+    current = os.environ.get(var, None)
+    if not current:
+        continue
+
+    new = []
+    for flag in current.split(" "):
+        if flag.lower() in ("-pie", "-fpie"):
+            if "-fPIC" not in new:
+                new.append("-fPIC")
+            continue
+        new.append(flag)
+
+    os.environ[var] = " ".join(new)
+
 from distutils.core import setup, Extension
 
 # Distutils doesn't cope well with source files that have relative paths going
@@ -44,7 +61,7 @@ os.chdir(srcdir)
 module = Extension('_lxc', sources=['lxc.c'],
                    include_dirs=[os.path.join(top_srcdir, 'src'),
                                  os.path.join(top_builddir, 'src')],
-                   library_dirs=[os.path.join(top_builddir, 'src/lxc')],
+                   library_dirs=[os.path.join(top_builddir, 'src/lxc/.libs/')],
                    libraries=['lxc'])
 
 
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index cbc0418..ccac81b 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -1,6 +1,6 @@
 if ENABLE_TESTS
 
-LDADD = ../lxc/liblxc.so
+LDADD = ../lxc/liblxc.la
 
 lxc_test_containertests_SOURCES = containertests.c
 lxc_test_locktests_SOURCES = locktests.c

From 841635f4de93560c17f9a97315fa0352f66d38e2 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 12 Oct 2016 22:46:09 +0000
Subject: [PATCH 186/334] c/r: use --external instead of --veth-pair

--veth-pair has been deprecated as of 2.6, let's use the new --external
instead.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index f228736..0b5fc09 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -452,13 +452,13 @@ static void exec_criu(struct criu_opts *opts)
 			veth = n->priv.veth_attr.pair;
 
 			if (n->link)
-				ret = snprintf(buf, sizeof(buf), "%s=%s@%s", eth, veth, n->link);
+				ret = snprintf(buf, sizeof(buf), "veth[%s]:%s@%s", eth, veth, n->link);
 			else
-				ret = snprintf(buf, sizeof(buf), "%s=%s", eth, veth);
+				ret = snprintf(buf, sizeof(buf), "veth[%s]:%s", eth, veth);
 			if (ret < 0 || ret >= sizeof(buf))
 				goto err;
 
-			DECLARE_ARG("--veth-pair");
+			DECLARE_ARG("--external");
 			DECLARE_ARG(buf);
 		}
 

From 1bcf81d78bd4cb2254ff15fd20d458c88f61575f Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 12 Oct 2016 23:18:02 +0000
Subject: [PATCH 187/334] c/r: remember to increment netnr

We need this for calculating the name of unnamed interfaces in the config.
But we also need to remember to increment it :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 0b5fc09..84d4209 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -460,6 +460,7 @@ static void exec_criu(struct criu_opts *opts)
 
 			DECLARE_ARG("--external");
 			DECLARE_ARG(buf);
+			netnr++;
 		}
 
 	}

From ed19e98afb6fb70f851707b5470222aa1b687a50 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Thu, 22 Sep 2016 23:13:42 +0000
Subject: [PATCH 188/334] c/r: add checkpoint/restore support for macvlan
 interfaces

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 46 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 10 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 84d4209..c998fe4 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -439,9 +439,6 @@ static void exec_criu(struct criu_opts *opts)
 			char eth[128], *veth;
 			struct lxc_netdev *n = it->elem;
 
-			if (n->type != LXC_NET_VETH)
-				continue;
-
 			if (n->name) {
 				if (strlen(n->name) >= sizeof(eth))
 					goto err;
@@ -449,14 +446,42 @@ static void exec_criu(struct criu_opts *opts)
 			} else
 				sprintf(eth, "eth%d", netnr);
 
-			veth = n->priv.veth_attr.pair;
+			switch (n->type) {
+			case LXC_NET_VETH:
+				veth = n->priv.veth_attr.pair;
 
-			if (n->link)
-				ret = snprintf(buf, sizeof(buf), "veth[%s]:%s@%s", eth, veth, n->link);
-			else
-				ret = snprintf(buf, sizeof(buf), "veth[%s]:%s", eth, veth);
-			if (ret < 0 || ret >= sizeof(buf))
+				if (n->link)
+					ret = snprintf(buf, sizeof(buf), "veth[%s]:%s@%s", eth, veth, n->link);
+				else
+					ret = snprintf(buf, sizeof(buf), "veth[%s]:%s", eth, veth);
+				if (ret < 0 || ret >= sizeof(buf))
+					goto err;
+				break;
+			case LXC_NET_MACVLAN:
+				if (n->name) {
+					if (strlen(n->name) >= sizeof(eth))
+						goto err;
+					strncpy(eth, n->name, sizeof(eth));
+				} else
+					sprintf(eth, "eth%d", netnr);
+
+				if (!n->link) {
+					ERROR("no host interface for macvlan %s\n", n->name);
+					goto err;
+				}
+
+				ret = snprintf(buf, sizeof(buf), "macvlan[%s]:%s", eth, n->link);
+				if (ret < 0 || ret >= sizeof(buf))
+					goto err;
+				break;
+			case LXC_NET_NONE:
+			case LXC_NET_EMPTY:
+				break;
+			default:
+				/* we have screened for this earlier... */
+				ERROR("unexpected network type %d\n", n->type);
 				goto err;
+			}
 
 			DECLARE_ARG("--external");
 			DECLARE_ARG(buf);
@@ -616,9 +641,10 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
 		case LXC_NET_VETH:
 		case LXC_NET_NONE:
 		case LXC_NET_EMPTY:
+		case LXC_NET_MACVLAN:
 			break;
 		default:
-			ERROR("Found network that is not VETH or NONE\n");
+			ERROR("Found un-dumpable network: %s (%s)\n", lxc_net_type_to_str(n->type), n->name);
 			return false;
 		}
 	}

From 9e747ddb9f532c366ecc5a2109aa6147f3ec8013 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 24 Oct 2016 17:38:13 -0400
Subject: [PATCH 189/334] ubuntu: Fix package upgrades requiring proc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 templates/lxc-ubuntu.in | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/templates/lxc-ubuntu.in b/templates/lxc-ubuntu.in
index 92be563..8320993 100644
--- a/templates/lxc-ubuntu.in
+++ b/templates/lxc-ubuntu.in
@@ -403,7 +403,13 @@ exit 101
 EOF
     chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
 
-    lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y || { suggest_flush; false; }
+    (
+        cat << EOF
+        mount -t proc proc "${1}/partial-${arch}/proc"
+        chroot "${1}/partial-${arch}" apt-get dist-upgrade -y
+EOF
+    ) | lxc-unshare -s MOUNT -- sh -eu || (suggest_flush; false)
+
     rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
 
     chroot "$1/partial-${arch}" apt-get clean

From 4d411134016133dcd31fba55282f4fd41d76b015 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 24 Oct 2016 16:55:27 -0600
Subject: [PATCH 190/334] c/r: drop duplicate hunk from macvlan case

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index c998fe4..16d439a 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -458,13 +458,6 @@ static void exec_criu(struct criu_opts *opts)
 					goto err;
 				break;
 			case LXC_NET_MACVLAN:
-				if (n->name) {
-					if (strlen(n->name) >= sizeof(eth))
-						goto err;
-					strncpy(eth, n->name, sizeof(eth));
-				} else
-					sprintf(eth, "eth%d", netnr);
-
 				if (!n->link) {
 					ERROR("no host interface for macvlan %s\n", n->name);
 					goto err;

From f28b1f683df968570942e302b40b3367f9240d83 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 24 Oct 2016 16:55:49 -0600
Subject: [PATCH 191/334] c/r: use snprintf to compute device name

This will never actually overflow, because %d is 32 bits and eth is 128
bytes long, but safety first :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 16d439a..0940967 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -443,8 +443,11 @@ static void exec_criu(struct criu_opts *opts)
 				if (strlen(n->name) >= sizeof(eth))
 					goto err;
 				strncpy(eth, n->name, sizeof(eth));
-			} else
-				sprintf(eth, "eth%d", netnr);
+			} else {
+				ret = snprintf(eth, sizeof(eth), "eth%d", netnr);
+				if (ret < 0 || ret >= sizeof(eth))
+					goto err;
+			}
 
 			switch (n->type) {
 			case LXC_NET_VETH:

From 0a98f3dfaf62e1e3d6a817874b8530ca3e9632f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 25 Oct 2016 16:39:56 -0400
Subject: [PATCH 192/334] Tweak libtool handling to work with Android
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/lxc/Makefile.am | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 8138a56..6bcb6da 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -298,8 +298,8 @@ endif
 install-exec-local: install-libLTLIBRARIES
 	mkdir -p $(DESTDIR)$(datadir)/lxc
 	install -c -m 644 lxc.functions $(DESTDIR)$(datadir)/lxc
-	rm $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.1
-	mv $(DESTDIR)$(libdir)/liblxc.so.1.0.0 $(DESTDIR)$(libdir)/liblxc.so. at LXC_ABI@
+	mv $(shell readlink -f $(DESTDIR)$(libdir)/liblxc.so) $(DESTDIR)$(libdir)/liblxc.so. at LXC_ABI@
+	rm -f $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.1
 	cd $(DESTDIR)$(libdir); \
 	ln -sf liblxc.so. at LXC_ABI@ liblxc.so.$(firstword $(subst ., , at LXC_ABI@)); \
 	ln -sf liblxc.so.$(firstword $(subst ., , at LXC_ABI@)) liblxc.so

From 8511da278af54cd754ca774c35869541bc7d8126 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 26 Oct 2016 22:52:12 +0200
Subject: [PATCH 193/334] tests: add lxc_error() and lxc_debug()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxctest.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/tests/lxctest.h b/src/tests/lxctest.h
index 2793ca2..c28d9c2 100644
--- a/src/tests/lxctest.h
+++ b/src/tests/lxctest.h
@@ -28,6 +28,15 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#define lxc_debug_stream(stream, format, ...)                                  \
+	do {                                                                   \
+		fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__,     \
+			__func__, __VA_ARGS__);                                \
+	} while (false)
+
+#define lxc_error(format, ...) lxc_debug_stream(stderr, format, __VA_ARGS__)
+#define lxc_debug(format, ...) lxc_debug_stream(stdout, format, __VA_ARGS__)
+
 #define lxc_test_assert_stringify(expression, stringify_expression)            \
 	do {                                                                   \
 		if (!(expression)) {                                           \

From ff074c81940cd6c81533d50aed84c86210db69cf Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge at hallyn.com>
Date: Sat, 25 Jun 2016 00:05:08 -0500
Subject: [PATCH 194/334] container start: clone newcgroup immediately

rather than waiting and later unsharing.

This "makes the creation of a new cgroup early enough that the existing
cgroup mounts are visible.  Which means any fancy permission checks
I dream will work on a future version of liblxc."

This also includes what should be a tiny improvement regarding netns,
though it's conceivable it'll break something.  Remember that with new
kernels we need to unshare netns after we've become the root user in the
new userns, so that netns files are owned by that root.  But we were
passing the unfiltered handler->clone_flags to the original clone().
This just resulted in a temporary extra netns generation, but still
worked since our target netns, which we passed our devices into, was
created late enough.

Signed-off-by: Serge Hallyn <serge at hallyn.com>
Signed-off-by: "Eric W. Biederman" <ebiederm at xmission.com>
---
 src/lxc/start.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 78c9ed0..ca4968b 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -909,11 +909,6 @@ static int do_start(void *data)
 		devnull_fd = -1;
 	}
 
-	if (cgns_supported() && unshare(CLONE_NEWCGROUP) != 0) {
-		SYSERROR("Failed to unshare cgroup namespace");
-		goto out_warn_father;
-	}
-
 	setsid();
 
 	/* after this call, we are in error because this
@@ -1136,7 +1131,11 @@ static int lxc_spawn(struct lxc_handler *handler)
 	flags = handler->clone_flags;
 	if (handler->clone_flags & CLONE_NEWUSER)
 		flags &= ~CLONE_NEWNET;
-	handler->pid = lxc_clone(do_start, handler, handler->clone_flags);
+	if (cgns_supported()) {
+		handler->clone_flags |= CLONE_NEWCGROUP;
+		flags |= CLONE_NEWCGROUP;
+	}
+	handler->pid = lxc_clone(do_start, handler, flags);
 	if (handler->pid < 0) {
 		SYSERROR("failed to fork into a new namespace");
 		goto out_delete_net;

From ff88c8155031929e677a6212a46410a42a7241cc Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 29 Oct 2016 20:29:08 +0200
Subject: [PATCH 195/334] use python3_sitearch for including the python code

Closes: #502
Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 lxc.spec.in | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lxc.spec.in b/lxc.spec.in
index 099b595..66b0f04 100644
--- a/lxc.spec.in
+++ b/lxc.spec.in
@@ -268,9 +268,6 @@ fi
 %{_sbindir}/*
 %{_libdir}/*.so.*
 %{_libdir}/%{name}
-%if %{with_python}
-%{_libdir}/python*
-%endif
 %{_localstatedir}/*
 %{_libexecdir}/%{name}
 %attr(4111,root,root) %{_libexecdir}/%{name}/lxc-user-nic
@@ -280,8 +277,7 @@ fi
 %endif
 
 %if %{with_python}
-%{_libdir}/python3.3/site-packages/_lxc*
-%{_libdir}/python3.3/site-packages/lxc/*
+%{python3_sitearch}/*
 %endif
 
 %if %{with_lua}

From 727b60d603fd32cb0ba822141925085ff28bbf15 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 29 Oct 2016 20:29:18 +0200
Subject: [PATCH 196/334] fix rpm build, include all built files, but only once

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 lxc.spec.in | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lxc.spec.in b/lxc.spec.in
index 66b0f04..dadd739 100644
--- a/lxc.spec.in
+++ b/lxc.spec.in
@@ -251,13 +251,13 @@ fi
 %{_datadir}/doc/*
 %{_datadir}/lxc/*
 %{_sysconfdir}/bash_completion.d
-%{_sysconfdir}/sysconfig/*
 %config(noreplace) %{_sysconfdir}/lxc/*
 %config(noreplace) %{_sysconfdir}/sysconfig/*
 
 %if %{with_systemd}
 %{_unitdir}/lxc-net.service
 %{_unitdir}/lxc.service
+%{_unitdir}/lxc at .service
 %else
 %{_sysconfdir}/rc.d/init.d/lxc
 %{_sysconfdir}/rc.d/init.d/lxc-net
@@ -269,7 +269,9 @@ fi
 %{_libdir}/*.so.*
 %{_libdir}/%{name}
 %{_localstatedir}/*
-%{_libexecdir}/%{name}
+%{_libexecdir}/%{name}/hooks/unmount-namespace
+%{_libexecdir}/%{name}/lxc-apparmor-load
+%{_libexecdir}/%{name}/lxc-monitord
 %attr(4111,root,root) %{_libexecdir}/%{name}/lxc-user-nic
 %if %{with_systemd}
 %attr(555,root,root) %{_libexecdir}/%{name}/lxc-net

From 125736f22c32877b87fdfe72520a8535a2dcab36 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 22:47:51 +0200
Subject: [PATCH 197/334] cgfs: fix invalid free()

And let's be on the safe side by NULLing free()ed variables.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfs.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index c5ba765..26cccad 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -632,10 +632,10 @@ static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *met
 	if (--meta_data->ref > 0)
 		return meta_data;
 	lxc_free_array((void **)meta_data->mount_points, (lxc_free_fn)lxc_cgroup_mount_point_free);
-	if (meta_data->hierarchies) {
+	if (meta_data->hierarchies)
 		for (i = 0; i <= meta_data->maximum_hierarchy; i++)
-			lxc_cgroup_hierarchy_free(meta_data->hierarchies[i]);
-	}
+			if (meta_data->hierarchies[i])
+				lxc_cgroup_hierarchy_free(meta_data->hierarchies[i]);
 	free(meta_data->hierarchies);
 	free(meta_data);
 	return NULL;
@@ -1798,9 +1798,16 @@ static void lxc_cgroup_hierarchy_free(struct cgroup_hierarchy *h)
 {
 	if (!h)
 		return;
-	lxc_free_array((void **)h->subsystems, free);
-	free(h->all_mount_points);
+	if (h->subsystems) {
+		lxc_free_array((void **)h->subsystems, free);
+		h->subsystems = NULL;
+	}
+	if (h->all_mount_points) {
+		free(h->all_mount_points);
+		h->all_mount_points = NULL;
+	}
 	free(h);
+	h = NULL;
 }
 
 static bool is_valid_cgroup(const char *name)

From a3ed64707fb71b6f2fcf603e755c5da07ab3aec5 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sun, 30 Oct 2016 13:32:59 +0100
Subject: [PATCH 198/334] find OpenSUSE's build also as obs-build

this is how it is shipped in Debian and Ubuntu

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 templates/lxc-opensuse.in | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index 6044d89..ad75e10 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -40,6 +40,14 @@ done
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
+if [ -x /usr/bin/obs-build ]; then
+    BUILD=/usr/bin/obs-build
+    export BUILD_DIR=/usr/lib/obs-build
+else
+    BUILD=/usr/bin/build
+    export BUILD_DIR=/usr/lib/build
+fi
+
 configure_opensuse()
 {
     rootfs=$1
@@ -118,7 +126,7 @@ download_opensuse()
     cache=$1
     arch=$2
 
-    if [ ! -x /usr/bin/build ]; then
+    if [ ! -x ${BUILD} ]; then
        echo "Could not create openSUSE template :"
        echo "you need to install \"build\" package"
        return 1
@@ -200,7 +208,7 @@ EOF
     # openSUSE 13.2 has no noarch directory in update
     [ -d $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch ] || mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch
 
-    CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:/usr/lib/build" /usr/lib/build/init_buildsystem  --clean --configdir /usr/lib/build/configs --cachedir $cache/partial-$arch-cache --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch || return 1
+    CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem  --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch || return 1
     chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss repo-oss || return 1
     if [ $DISTRO == "leap/42.1" ]; then
         chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/oss update || return 1

From 8c4c5641930fcf132ff8562b0558e40f9801dd39 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sun, 30 Oct 2016 14:16:38 +0100
Subject: [PATCH 199/334] improve help text for --fancy and --fancy-format

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 src/lxc/tools/lxc_ls.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index 8e7cbef..5e2cb4a 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -185,8 +185,10 @@ lxc-ls list containers\n\
 \n\
 Options :\n\
   -1, --line         show one entry per line\n\
-  -f, --fancy        column-based output\n\
-  -F, --fancy-format column-based output\n\
+  -f, --fancy        use a fancy, column-based output\n\
+  -F, --fancy-format comma separated list of columns to show in the fancy output\n\
+                     valid columns are: NAME, STATE, PID, RAM, SWAP, AUTOSTART,\n\
+                     GROUPS, INTERFACE, IPV4 and IPV6\n\
   --active           list only active containers\n\
   --running          list only running containers\n\
   --frozen           list only frozen containers\n\

From e5a8e4e15b7da892884cb62d17c181c6e18f1d4b Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sun, 30 Oct 2016 14:17:55 +0100
Subject: [PATCH 200/334] improve wording of the help page for lxc-ls

it's "list of columns", not "list of column"

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 doc/ja/lxc-ls.sgml.in | 2 +-
 doc/ko/lxc-ls.sgml.in | 2 +-
 doc/lxc-ls.sgml.in    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/ja/lxc-ls.sgml.in b/doc/ja/lxc-ls.sgml.in
index a3c0c61..9189926 100644
--- a/doc/ja/lxc-ls.sgml.in
+++ b/doc/ja/lxc-ls.sgml.in
@@ -173,7 +173,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
         <listitem>
           <para>
             <!--
-            Comma separate list of column to show in the fancy output.
+            Comma separated list of columns to show in the fancy output.
             The list of accepted and default fields is listed in \-\-help.
             -->
             装飾付き出力で表示するカラムのコンマ区切りのリスト。デフォルトで表示される項目と指定可能な項目名は --help オプションで確認してください。
diff --git a/doc/ko/lxc-ls.sgml.in b/doc/ko/lxc-ls.sgml.in
index d7c354a..368528c 100644
--- a/doc/ko/lxc-ls.sgml.in
+++ b/doc/ko/lxc-ls.sgml.in
@@ -173,7 +173,7 @@ by Sungbae Yoo <sungbae.yoo at samsung.com>
         <listitem>
           <para>
             <!--
-            Comma separate list of column to show in the fancy output.
+            Comma separated list of columns to show in the fancy output.
             The list of accepted and default fields is listed in \-\-help.
             -->
             --fancy로 출력할때 어떤 컬럼을 보여줄지 쉼표(,)로 구분된 리스트.
diff --git a/doc/lxc-ls.sgml.in b/doc/lxc-ls.sgml.in
index d2850f2..2b28237 100644
--- a/doc/lxc-ls.sgml.in
+++ b/doc/lxc-ls.sgml.in
@@ -146,7 +146,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
         </term>
         <listitem>
           <para>
-            Comma separated list of column to show in the fancy output.
+            Comma separated list of columns to show in the fancy output.
             The list of accepted and default fields is listed in --help.
           </para>
         </listitem>

From f43e73609fa70b5eeb89d6565800c2e19195467c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 30 Oct 2016 10:45:13 +0100
Subject: [PATCH 201/334] cgfs: add print_cgfs_init_debuginfo()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfs.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index 26cccad..c10253b 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -2270,6 +2270,33 @@ static bool init_cpuset_if_needed(struct cgroup_mount_point *mp,
 		do_init_cpuset_file(mp, path, "/cpuset.mems") );
 }
 
+static void print_cgfs_init_debuginfo(struct cgfs_data *d)
+{
+	int i;
+
+	if (!getenv("LXC_DEBUG_CGFS"))
+		return;
+
+	DEBUG("Cgroup information:");
+	DEBUG("  container name: %s", d->name);
+	if (!d->meta || !d->meta->hierarchies) {
+		DEBUG("  No hierarchies found.");
+		return;
+	}
+	DEBUG("  Controllers:");
+	for (i = 0; i <= d->meta->maximum_hierarchy; i++) {
+		char **p;
+		struct cgroup_hierarchy *h = d->meta->hierarchies[i];
+		if (!h) {
+			DEBUG("     Empty hierarchy number %d.", i);
+			continue;
+		}
+		for (p = h->subsystems; p && *p; p++) {
+			DEBUG("     %2d: %s", i, *p);
+		}
+	}
+}
+
 struct cgroup_ops *cgfs_ops_init(void)
 {
 	return &cgfs_ops;
@@ -2295,6 +2322,9 @@ static void *cgfs_init(const char *name)
 		ERROR("cgroupfs failed to detect cgroup metadata");
 		goto err2;
 	}
+
+	print_cgfs_init_debuginfo(d);
+
 	return d;
 
 err2:

From 613fe8e9cc71cfa757f7daad22de81e015ec84fb Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 30 Oct 2016 13:42:37 +0100
Subject: [PATCH 202/334] cgfs: skip empty entries under /proc/self/cgroup

If cgroupv2 is enabled either alone or together with legacy hierarchies
/proc/self/cgroup can contain entries of the form:

        0::/

These entries need to be skipped.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfs.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index c10253b..a30ad91 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -364,6 +364,14 @@ static bool find_cgroup_hierarchies(struct cgroup_meta_data *meta_data,
 		*colon2 = '\0';
 
 		colon2 = NULL;
+
+		/* With cgroupv2 /proc/self/cgroup can contain entries of the
+		 * form: 0::/
+		 * These entries need to be skipped.
+		 */
+		if (!strcmp(colon1, ""))
+			continue;
+
 		hierarchy_number = strtoul(line, &colon2, 10);
 		if (!colon2 || *colon2)
 			continue;
@@ -1685,6 +1693,14 @@ lxc_cgroup_process_info_getx(const char *proc_pid_cgroup_str,
 		*colon2++ = '\0';
 
 		endptr = NULL;
+
+		/* With cgroupv2 /proc/self/cgroup can contain entries of the
+		 * form: 0::/
+		 * These entries need to be skipped.
+		 */
+		if (!strcmp(colon1, ""))
+			continue;
+
 		hierarchy_number = strtoul(line, &endptr, 10);
 		if (!endptr || *endptr)
 			continue;

From 45aec6a1e3ea6450bfcdc83bf71d5ba9c2910fa3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 30 Oct 2016 14:44:33 +0100
Subject: [PATCH 203/334] cgfs: explicitly check for NULL

Somehow this implementation of a cgroupfs backend decided to use the hierarchy
numbers it detects in /proc/cgroups and /proc/self/cgroups as indices for
the hierarchy struct. Controller numbering usually starts at 1 but may start at
0 if:

    a) the controller is not mounted on a cgroups v1 hierarchy;
    b) the controller is bound to the cgroups v2 single unified hierarchy; or
    c) the controller is disabled

To avoid having to rework our fallback backend significantly, we should
explicitly check for each controller if hierarchy[i] != NULL.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfs.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
index a30ad91..8499200 100644
--- a/src/lxc/cgroups/cgfs.c
+++ b/src/lxc/cgroups/cgfs.c
@@ -512,7 +512,7 @@ static bool find_hierarchy_mountpts( struct cgroup_meta_data *meta_data, char **
 			goto out;
 
 		h = NULL;
-		for (k = 1; k <= meta_data->maximum_hierarchy; k++) {
+		for (k = 0; k <= meta_data->maximum_hierarchy; k++) {
 			if (meta_data->hierarchies[k] &&
 			    meta_data->hierarchies[k]->subsystems[0] &&
 			    lxc_string_in_array(meta_data->hierarchies[k]->subsystems[0], (const char **)subsystems)) {
@@ -654,6 +654,8 @@ static struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_dat
 	size_t i;
 	for (i = 0; i <= meta_data->maximum_hierarchy; i++) {
 		struct cgroup_hierarchy *h = meta_data->hierarchies[i];
+		if (!h)
+			continue;
 		if (h && lxc_string_in_array(subsystem, (const char **)h->subsystems))
 			return h;
 	}
@@ -892,6 +894,8 @@ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const c
 	/* find mount points we can use */
 	for (info_ptr = base_info; info_ptr; info_ptr = info_ptr->next) {
 		h = info_ptr->hierarchy;
+		if (!h)
+			continue;
 		mp = lxc_cgroup_find_mount_point(h, info_ptr->cgroup_path, true);
 		if (!mp) {
 			ERROR("Could not find writable mount point for cgroup hierarchy %d while trying to create cgroup.", h->index);
@@ -981,6 +985,9 @@ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const c
 		for (i = 0, info_ptr = base_info; info_ptr; info_ptr = info_ptr->next, i++) {
 			char *parts2[3];
 
+			if (!info_ptr->hierarchy)
+				continue;
+
 			if (lxc_string_in_array("ns", (const char **)info_ptr->hierarchy->subsystems))
 				continue;
 			current_entire_path = NULL;
@@ -1079,6 +1086,8 @@ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const c
 
 	/* we're done, now update the paths */
 	for (i = 0, info_ptr = base_info; info_ptr; info_ptr = info_ptr->next, i++) {
+		if (!info_ptr->hierarchy)
+			continue;
 		/* ignore legacy 'ns' subsystem here, lxc_cgroup_create_legacy
 		 * will take care of it
 		 * Since we do a continue in above loop, new_cgroup_paths[i] is
@@ -1116,6 +1125,9 @@ static int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const
 	int r;
 
 	for (info_ptr = base_info; info_ptr; info_ptr = info_ptr->next) {
+		if (!info_ptr->hierarchy)
+			continue;
+
 		if (!lxc_string_in_array("ns", (const char **)info_ptr->hierarchy->subsystems))
 			continue;
 		/*
@@ -1200,6 +1212,9 @@ static int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, bool
 
 	snprintf(pid_buf, 32, "%lu", (unsigned long)pid);
 	for (info_ptr = info; info_ptr; info_ptr = info_ptr->next) {
+		if (!info_ptr->hierarchy)
+			continue;
+
 		char *cgroup_path = (enter_sub && info_ptr->cgroup_path_sub) ?
 			info_ptr->cgroup_path_sub :
 			info_ptr->cgroup_path;
@@ -1444,6 +1459,10 @@ static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type)
 	for (info = base_info; info; info = info->next) {
 		size_t subsystem_count, i;
 		struct cgroup_mount_point *mp = info->designated_mount_point;
+
+		if (!info->hierarchy)
+			continue;
+
 		if (!mountpoint_is_accessible(mp))
 			mp = lxc_cgroup_find_mount_point(info->hierarchy, info->cgroup_path, true);
 
@@ -1930,6 +1949,8 @@ find_info_for_subsystem(struct cgroup_process_info *info, const char *subsystem)
 	struct cgroup_process_info *info_ptr;
 	for (info_ptr = info; info_ptr; info_ptr = info_ptr->next) {
 		struct cgroup_hierarchy *h = info_ptr->hierarchy;
+		if (!h)
+			continue;
 		if (lxc_string_in_array(subsystem, (const char **)h->subsystems))
 			return info_ptr;
 	}
@@ -2426,7 +2447,7 @@ static bool cgfs_escape(void *hdata)
 	if (!md)
 		return false;
 
-	for (i = 1; i <= md->maximum_hierarchy; i++) {
+	for (i = 0; i <= md->maximum_hierarchy; i++) {
 		struct cgroup_hierarchy *h = md->hierarchies[i];
 		struct cgroup_mount_point *mp;
 		char *tasks;
@@ -2636,6 +2657,9 @@ static bool cgfs_chown(void *hdata, struct lxc_conf *conf)
 		return false;
 
 	for (info_ptr = d->info; info_ptr; info_ptr = info_ptr->next) {
+		if (!info_ptr->hierarchy)
+			continue;
+
 		if (!info_ptr->designated_mount_point) {
 			info_ptr->designated_mount_point = lxc_cgroup_find_mount_point(info_ptr->hierarchy, info_ptr->cgroup_path, true);
 			if (!info_ptr->designated_mount_point) {

From 037f33c494499b62404f330df5e1f4f7fe70cf9e Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 30 Oct 2016 18:24:15 +0100
Subject: [PATCH 204/334] tools: use correct exit code for lxc-stop

When the container is already running our manpage promises to exit with 2.
Let's make it so.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_stop.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index 498aac1..d87ed16 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -226,7 +226,10 @@ int main(int argc, char *argv[])
 
 	if (!c->is_running(c)) {
 		fprintf(stderr, "%s is not running\n", c->name);
-		ret = EXIT_FAILURE;
+		/* Per our manpage we need to exit with exit code:
+		 * 2: The specified container exists but was not running.
+		 */
+		ret = 2;
 		goto out;
 	}
 

From 1fe2570ec0edf1bef45efbc1cfde4578122add8e Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 31 Oct 2016 10:07:25 -0600
Subject: [PATCH 205/334] c/r: explicitly emit bind mounts as criu arguments

We switched to --ext-mount-map auto because of "system" (liblxc) added
mounts like the cgmanager socket that weren't in the config file. This had
the added advantage that we could drop all the mount processing code,
because we no longer needed an --ext-mount-map argument.

The problem here is that mounts can move between hosts. While
--ext-mount-map auto does its best to detect this situation, it explicitly
disallows moves that change the path name. In LXD, we bind mount
/var/lib/lxd/shmounts/$container to /dev/.lxd-mounts for each container,
and so when a container is renamed in a migration, the name changes.
--ext-mount-map auto won't detect this, and so the migration fails.

We *could* implement mount rewriting in CRIU, but my experience with cgroup
and apparmor rewriting is that this is painful and error prone. Instead, it
is much easier to go back to explicitly listing --ext-mount-map arguments
from the config file, and allow the source of the bind to change. We leave
--ext-mount-map auto to catch any stragling (or future) system added
mounts.

I believe this should fix Launchpad Bug 1580765

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 0940967..867139b 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -46,6 +46,12 @@
 #include "network.h"
 #include "utils.h"
 
+#if IS_BIONIC
+#include <../include/lxcmntent.h>
+#else
+#include <mntent.h>
+#endif
+
 #define CRIU_VERSION		"2.0"
 
 #define CRIU_GITID_VERSION	"2.0"
@@ -123,6 +129,8 @@ static void exec_criu(struct criu_opts *opts)
 	int static_args = 23, argc = 0, i, ret;
 	int netnr = 0;
 	struct lxc_list *it;
+	FILE *mnts;
+	struct mntent mntent;
 
 	char buf[4096], tty_info[32];
 	size_t pos;
@@ -200,6 +208,8 @@ static void exec_criu(struct criu_opts *opts)
 	if (opts->user->action_script)
 		static_args += 2;
 
+	static_args += 2 * lxc_list_len(&opts->c->lxc_conf->mount_list);
+
 	ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action);
 	if (ret < 0 || ret >= PATH_MAX) {
 		ERROR("logfile name too long\n");
@@ -315,6 +325,36 @@ static void exec_criu(struct criu_opts *opts)
 		DECLARE_ARG(opts->user->action_script);
 	}
 
+	mnts = write_mount_file(&opts->c->lxc_conf->mount_list);
+	if (!mnts)
+		goto err;
+
+	while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) {
+		char *fmt, *key, *val;
+		char arg[2 * PATH_MAX + 2];
+
+		if (strcmp(opts->action, "dump") == 0) {
+			fmt = "/%s:%s";
+			key = mntent.mnt_dir;
+			val = mntent.mnt_dir;
+		} else {
+			fmt = "%s:%s";
+			key = mntent.mnt_dir;
+			val = mntent.mnt_fsname;
+		}
+
+		ret = snprintf(arg, sizeof(arg), fmt, key, val);
+		if (ret < 0 || ret >= sizeof(arg)) {
+			fclose(mnts);
+			ERROR("snprintf failed");
+			goto err;
+		}
+
+		DECLARE_ARG("--ext-mount-map");
+		DECLARE_ARG(arg);
+	}
+	fclose(mnts);
+
 	if (strcmp(opts->action, "dump") == 0 || strcmp(opts->action, "pre-dump") == 0) {
 		char pid[32], *freezer_relative;
 

From bc2250ffe8138fc62f9bf264d675424407b97ceb Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Mon, 31 Oct 2016 19:48:38 +0000
Subject: [PATCH 206/334] log: bump LXC_LOG_BUFFER_SIZE to 4096

We need to log longer lines due to CRIU arguments.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/log.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/log.h b/src/lxc/log.h
index eb330d0..a1df3c9 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -44,7 +44,7 @@
 #endif
 
 #define LXC_LOG_PREFIX_SIZE	32
-#define LXC_LOG_BUFFER_SIZE	1024
+#define LXC_LOG_BUFFER_SIZE	4096
 
 /* This attribute is required to silence clang warnings */
 #if defined(__GNUC__)

From 27866a41a3b217cd81ed8cbc8fa5d2413e94a3c1 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Wed, 17 Aug 2016 11:36:39 +0200
Subject: [PATCH 207/334] conf: merge network namespace move & rename on
 shutdown

On shutdown we move physical network interfaces back to the
host namespace and rename them afterwards as well as in the
later lxc_network_delete() step. However, if the device had
a name which already exists in the host namespace then the
moving fails and so do the subsequent rename attempts. When
the namespace ceases to exist the devices finally end up
in the host namespace named 'dev<ID>' by the kernel.

In order to avoid this, we do the moving and renaming in a
single step (lxc_netdev_move_by_*()'s move & rename happen
in a single netlink transaction).

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/conf.c  | 29 ++++++++---------------------
 src/lxc/conf.h  |  2 +-
 src/lxc/start.c |  2 +-
 3 files changed, 10 insertions(+), 23 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index bac560d..7e0336f 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2397,15 +2397,17 @@ static int setup_network(struct lxc_list *network)
 }
 
 /* try to move physical nics to the init netns */
-void restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
+void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
 {
 	int i, ret, oldfd;
 	char path[MAXPATHLEN];
 	char ifname[IFNAMSIZ];
 
-	if (netnsfd < 0)
+	if (netnsfd < 0 || conf->num_savednics == 0)
 		return;
 
+	INFO("running to reset %d nic names", conf->num_savednics);
+
 	ret = snprintf(path, MAXPATHLEN, "/proc/self/ns/net");
 	if (ret < 0 || ret >= MAXPATHLEN) {
 		WARN("Failed to open monitor netns fd");
@@ -2427,32 +2429,17 @@ void restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
 			WARN("no interface corresponding to index '%d'", s->ifindex);
 			continue;
 		}
-		if (lxc_netdev_move_by_name(ifname, 1, NULL))
+		if (lxc_netdev_move_by_name(ifname, 1, s->orig_name))
 			WARN("Error moving nic name:%s back to host netns", ifname);
+		free(s->orig_name);
 	}
+	conf->num_savednics = 0;
+
 	if (setns(oldfd, 0) != 0)
 		SYSERROR("Failed to re-enter monitor's netns");
 	close(oldfd);
 }
 
-void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf)
-{
-	int i;
-
-	if (conf->num_savednics == 0)
-		return;
-
-	INFO("running to reset %d nic names", conf->num_savednics);
-	restore_phys_nics_to_netns(netnsfd, conf);
-	for (i=0; i<conf->num_savednics; i++) {
-		struct saved_nic *s = &conf->saved_nics[i];
-		INFO("resetting nic %d to %s", s->ifindex, s->orig_name);
-		lxc_netdev_rename_by_index(s->ifindex, s->orig_name);
-		free(s->orig_name);
-	}
-	conf->num_savednics = 0;
-}
-
 static char *default_rootfs_mount = LXCROOTFSMOUNT;
 
 struct lxc_conf *lxc_conf_init(void)
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 2593ce5..10d78e5 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -433,7 +433,7 @@ extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
 struct cgroup_process_info;
 extern int lxc_setup(struct lxc_handler *handler);
 
-extern void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf);
+extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf);
 
 extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype);
 extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index ca4968b..376c57a 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1394,7 +1394,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	}
 
 	DEBUG("Pushing physical nics back to host namespace");
-	lxc_rename_phys_nics_on_shutdown(netnsfd, handler->conf);
+	lxc_restore_phys_nics_to_netns(netnsfd, handler->conf);
 
 	DEBUG("Tearing down virtual network devices used by container");
 	lxc_delete_network(handler);

From 31348e680474d2280ba6c294f6270c0954f96d5b Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Tue, 1 Nov 2016 17:07:26 -0600
Subject: [PATCH 208/334] c/r: save criu's stdout during dump too

This also allows us to commonize some bits of the dup2 code.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 76 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 60 insertions(+), 16 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 867139b..f49968b 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -62,6 +62,9 @@
 lxc_log_define(lxc_criu, lxc);
 
 struct criu_opts {
+	/* the thing to hook to stdout and stderr for logging */
+	int pipefd;
+
 	/* The type of criu invocation, one of "dump" or "restore" */
 	char *action;
 
@@ -134,6 +137,7 @@ static void exec_criu(struct criu_opts *opts)
 
 	char buf[4096], tty_info[32];
 	size_t pos;
+
 	/* If we are currently in a cgroup /foo/bar, and the container is in a
 	 * cgroup /lxc/foo, lxcfs will give us an ENOENT if some task in the
 	 * container has an open fd that points to one of the cgroup files
@@ -541,6 +545,21 @@ static void exec_criu(struct criu_opts *opts)
 
 	INFO("execing: %s", buf);
 
+	/* before criu inits its log, it sometimes prints things to stdout/err;
+	 * let's be sure we capture that.
+	 */
+	if (dup2(opts->pipefd, STDOUT_FILENO) < 0) {
+		SYSERROR("dup2 stdout failed");
+		goto err;
+	}
+
+	if (dup2(opts->pipefd, STDERR_FILENO) < 0) {
+		SYSERROR("dup2 stderr failed");
+		goto err;
+	}
+
+	close(opts->pipefd);
+
 #undef DECLARE_ARG
 	execv(argv[0], argv);
 err:
@@ -781,15 +800,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 
 		close(pipes[0]);
 		pipes[0] = -1;
-		if (dup2(pipes[1], STDERR_FILENO) < 0) {
-			SYSERROR("dup2 failed");
-			goto out_fini_handler;
-		}
-
-		if (dup2(pipes[1], STDOUT_FILENO) < 0) {
-			SYSERROR("dup2 failed");
-			goto out_fini_handler;
-		}
 
 		if (unshare(CLONE_NEWNS))
 			goto out_fini_handler;
@@ -816,6 +826,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 			}
 		}
 
+		os.pipefd = pipes[1];
 		os.action = "restore";
 		os.user = opts;
 		os.c = c;
@@ -1013,29 +1024,38 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 {
 	pid_t pid;
 	char *criu_version = NULL;
+	int criuout[2];
 
 	if (!criu_ok(c, &criu_version))
 		return false;
 
-	if (mkdir_p(opts->directory, 0700) < 0)
+	if (pipe(criuout) < 0) {
+		SYSERROR("pipe() failed");
 		return false;
+	}
+
+	if (mkdir_p(opts->directory, 0700) < 0)
+		goto fail;
 
 	pid = fork();
 	if (pid < 0) {
 		SYSERROR("fork failed");
-		return false;
+		goto fail;
 	}
 
 	if (pid == 0) {
 		struct criu_opts os;
 		struct lxc_handler h;
 
+		close(criuout[0]);
+
 		h.name = c->name;
 		if (!cgroup_init(&h)) {
 			ERROR("failed to cgroup_init()");
 			exit(1);
 		}
 
+		os.pipefd = criuout[1];
 		os.action = mode;
 		os.user = opts;
 		os.c = c;
@@ -1050,27 +1070,51 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 		exit(1);
 	} else {
 		int status;
+		ssize_t n;
+		char buf[4096];
+		bool ret;
+
+		close(criuout[1]);
+
 		pid_t w = waitpid(pid, &status, 0);
 		if (w == -1) {
 			SYSERROR("waitpid");
+			close(criuout[0]);
 			return false;
 		}
 
+		n = read(criuout[0], buf, sizeof(buf));
+		close(criuout[0]);
+		if (n < 0) {
+			SYSERROR("read");
+			n = 0;
+		}
+		buf[n] = 0;
+
 		if (WIFEXITED(status)) {
 			if (WEXITSTATUS(status)) {
 				ERROR("dump failed with %d\n", WEXITSTATUS(status));
-				return false;
+				ret = false;
+			} else {
+				ret = true;
 			}
-
-			return true;
 		} else if (WIFSIGNALED(status)) {
 			ERROR("dump signaled with %d\n", WTERMSIG(status));
-			return false;
+			ret = false;
 		} else {
 			ERROR("unknown dump exit %d\n", status);
-			return false;
+			ret = false;
 		}
+
+		if (!ret)
+			ERROR("criu output: %s", buf);
+		return ret;
 	}
+fail:
+	close(criuout[0]);
+	close(criuout[1]);
+	rmdir(opts->directory);
+	return false;
 }
 
 bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts)

From d0a4b88cdb144497df94497bf05179f0a3ac7b0f Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 2 Nov 2016 15:10:13 +0000
Subject: [PATCH 209/334] c/r: remove extra \ns from logs

The macros put a \n in for us, so let's not put another one in.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index f49968b..3588b00 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -216,7 +216,7 @@ static void exec_criu(struct criu_opts *opts)
 
 	ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action);
 	if (ret < 0 || ret >= PATH_MAX) {
-		ERROR("logfile name too long\n");
+		ERROR("logfile name too long");
 		return;
 	}
 
@@ -239,7 +239,7 @@ static void exec_criu(struct criu_opts *opts)
 
 	argv[argc++] = on_path("criu", NULL);
 	if (!argv[argc-1]) {
-		ERROR("Couldn't find criu binary\n");
+		ERROR("Couldn't find criu binary");
 		goto err;
 	}
 
@@ -506,7 +506,7 @@ static void exec_criu(struct criu_opts *opts)
 				break;
 			case LXC_NET_MACVLAN:
 				if (!n->link) {
-					ERROR("no host interface for macvlan %s\n", n->name);
+					ERROR("no host interface for macvlan %s", n->name);
 					goto err;
 				}
 
@@ -519,7 +519,7 @@ static void exec_criu(struct criu_opts *opts)
 				break;
 			default:
 				/* we have screened for this earlier... */
-				ERROR("unexpected network type %d\n", n->type);
+				ERROR("unexpected network type %d", n->type);
 				goto err;
 			}
 
@@ -670,7 +670,7 @@ static bool criu_version_ok(char **version)
 version_error:
 		fclose(f);
 		free(tmp);
-		ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore\n");
+		ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore");
 		return false;
 	}
 }
@@ -685,7 +685,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
 		return false;
 
 	if (geteuid()) {
-		ERROR("Must be root to checkpoint\n");
+		ERROR("Must be root to checkpoint");
 		return false;
 	}
 
@@ -699,7 +699,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version)
 		case LXC_NET_MACVLAN:
 			break;
 		default:
-			ERROR("Found un-dumpable network: %s (%s)\n", lxc_net_type_to_str(n->type), n->name);
+			ERROR("Found un-dumpable network: %s (%s)", lxc_net_type_to_str(n->type), n->name);
 			return false;
 		}
 	}
@@ -885,7 +885,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 
 				buf[n] = 0;
 
-				ERROR("criu process exited %d, output:\n%s\n", WEXITSTATUS(status), buf);
+				ERROR("criu process exited %d, output:\n%s", WEXITSTATUS(status), buf);
 				goto out_fini_handler;
 			} else {
 				ret = snprintf(buf, sizeof(buf), "/proc/self/task/%lu/children", (unsigned long)syscall(__NR_gettid));
@@ -896,7 +896,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 
 				FILE *f = fopen(buf, "r");
 				if (!f) {
-					SYSERROR("couldn't read restore's children file %s\n", buf);
+					SYSERROR("couldn't read restore's children file %s", buf);
 					goto out_fini_handler;
 				}
 
@@ -913,7 +913,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 				}
 			}
 		} else {
-			ERROR("CRIU was killed with signal %d\n", WTERMSIG(status));
+			ERROR("CRIU was killed with signal %d", WTERMSIG(status));
 			goto out_fini_handler;
 		}
 
@@ -1093,16 +1093,16 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 
 		if (WIFEXITED(status)) {
 			if (WEXITSTATUS(status)) {
-				ERROR("dump failed with %d\n", WEXITSTATUS(status));
+				ERROR("dump failed with %d", WEXITSTATUS(status));
 				ret = false;
 			} else {
 				ret = true;
 			}
 		} else if (WIFSIGNALED(status)) {
-			ERROR("dump signaled with %d\n", WTERMSIG(status));
+			ERROR("dump signaled with %d", WTERMSIG(status));
 			ret = false;
 		} else {
-			ERROR("unknown dump exit %d\n", status);
+			ERROR("unknown dump exit %d", status);
 			ret = false;
 		}
 
@@ -1132,7 +1132,7 @@ bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts)
 		return false;
 
 	if (access(path, F_OK) == 0) {
-		ERROR("please use a fresh directory for the dump directory\n");
+		ERROR("please use a fresh directory for the dump directory");
 		return false;
 	}
 
@@ -1150,7 +1150,7 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts)
 		return false;
 
 	if (geteuid()) {
-		ERROR("Must be root to restore\n");
+		ERROR("Must be root to restore");
 		return false;
 	}
 

From 87a06d9d1e88e93e2902caefce69b37bd75c1a63 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Wed, 2 Nov 2016 15:59:00 +0000
Subject: [PATCH 210/334] c/r: fix off-by-one error

When we read sizeof(buf) bytes here, we'd write off the end of the array,
which is bad :)

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/criu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 3588b00..5456cc1 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -883,6 +883,8 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 					goto out_fini_handler;
 				}
 
+				if (n == sizeof(buf))
+					n--;
 				buf[n] = 0;
 
 				ERROR("criu process exited %d, output:\n%s", WEXITSTATUS(status), buf);

From 5048abad35f582e6d63567840a49b8f1ef429391 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Thu, 3 Nov 2016 12:01:09 -0600
Subject: [PATCH 211/334] c/r: check state before doing a checkpoint/restore

This would already fail, but with a not-as-good error message. Let's make
the error better.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 src/lxc/lxccontainer.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index a1c94a1..3a9e1e3 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -3994,12 +3994,24 @@ static int do_lxcapi_migrate(struct lxc_container *c, unsigned int cmd,
 
 	switch (cmd) {
 	case MIGRATE_PRE_DUMP:
+		if (!do_lxcapi_is_running(c)) {
+			ERROR("container is not running");
+			return false;
+		}
 		ret = !__criu_pre_dump(c, valid_opts);
 		break;
 	case MIGRATE_DUMP:
+		if (!do_lxcapi_is_running(c)) {
+			ERROR("container is not running");
+			return false;
+		}
 		ret = !__criu_dump(c, valid_opts);
 		break;
 	case MIGRATE_RESTORE:
+		if (do_lxcapi_is_running(c)) {
+			ERROR("container is already running");
+			return false;
+		}
 		ret = !__criu_restore(c, valid_opts);
 		break;
 	default:

From 20c16a76f136ada196c234d3bad8723ffdb76904 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 3 Nov 2016 21:24:31 +0100
Subject: [PATCH 212/334] start: CLONE_NEWCGROUP after we have setup cgroups

If we do it earlier we end up with a wrong view of /proc/self/cgroup. For
example, assume we unshare(CLONE_NEWCGROUP) first, and then create the cgroup
for the container, say /sys/fs/cgroup/cpuset/lxc/c, then /proc/self/cgroup
would show us:

     8:cpuset:/lxc/c

whereas it should actually show

     8:cpuset:/

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/start.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 376c57a..dcee6f3 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -839,6 +839,26 @@ static int do_start(void *data)
 	if (lxc_sync_barrier_parent(handler, LXC_SYNC_CGROUP))
 		goto out_error;
 
+	/* Unshare cgroup namespace after we have setup our cgroups. If we do it
+	 * earlier we end up with a wrong view of /proc/self/cgroup. For
+	 * example, assume we unshare(CLONE_NEWCGROUP) first, and then create
+	 * the cgroup for the container, say /sys/fs/cgroup/cpuset/lxc/c, then
+	 * /proc/self/cgroup would show us:
+	 *
+	 *	8:cpuset:/lxc/c
+	 *
+	 * whereas it should actually show
+	 *
+	 *	8:cpuset:/
+	 */
+	if (cgns_supported()) {
+		if (unshare(CLONE_NEWCGROUP) < 0) {
+			INFO("Failed to unshare CLONE_NEWCGROUP.");
+			goto out_warn_father;
+		}
+		INFO("Unshared CLONE_NEWCGROUP.");
+	}
+
 	/* Set the label to change to when we exec(2) the container's init */
 	if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0)
 		goto out_warn_father;
@@ -1131,10 +1151,6 @@ static int lxc_spawn(struct lxc_handler *handler)
 	flags = handler->clone_flags;
 	if (handler->clone_flags & CLONE_NEWUSER)
 		flags &= ~CLONE_NEWNET;
-	if (cgns_supported()) {
-		handler->clone_flags |= CLONE_NEWCGROUP;
-		flags |= CLONE_NEWCGROUP;
-	}
 	handler->pid = lxc_clone(do_start, handler, flags);
 	if (handler->pid < 0) {
 		SYSERROR("failed to fork into a new namespace");

From 57af0c7ac52bd1880c394124bc2424246f0faa5f Mon Sep 17 00:00:00 2001
From: mgariepy <mgariepy at users.noreply.github.com>
Date: Tue, 8 Nov 2016 11:42:34 -0500
Subject: [PATCH 213/334] create symlink for /var/run

this patch create /var/run link to point to /run.

This will fix various issue present when /var/run is persistent.

Signed-off-by: Marc Gariepy <gariepy.marc at gmail.com>
---
 templates/lxc-centos.in | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/templates/lxc-centos.in b/templates/lxc-centos.in
index 2c444e4..8bd85a2 100644
--- a/templates/lxc-centos.in
+++ b/templates/lxc-centos.in
@@ -451,6 +451,13 @@ EOF
 
     $YUM install $PKG_LIST
 
+    # create symlink for /var/run -> ../run 
+    if [ "$release" = "7" ]; then
+        mv $INSTALL_ROOT/var/run/* $INSTALL_ROOT/run/
+        rmdir $INSTALL_ROOT/var/run
+        ln -sf ../run $INSTALL_ROOT/var/run
+    fi
+
     if [ $? -ne 0 ]; then
         echo "Failed to download the rootfs, aborting."
         return 1

From 798ee9ba238385965c308fa8682d35cbdaeceb35 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 6 Nov 2016 19:48:58 +0100
Subject: [PATCH 214/334] utils: add lxc_append_string()

lxc_append_string() appends strings without separator. This is mostly useful
for reading in whole files line-by-line.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 34 ++++++++++++++++++++++++++++++++++
 src/lxc/utils.h |  2 ++
 2 files changed, 36 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index c912fe8..d6f8ecf 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1930,3 +1930,37 @@ bool task_blocking_signal(pid_t pid, int signal)
 	fclose(f);
 	return bret;
 }
+
+static int lxc_append_null_to_list(void ***list)
+{
+	int newentry = 0;
+	void **tmp;
+
+	if (*list)
+		for (; (*list)[newentry]; newentry++) {
+			;
+		}
+
+	tmp = realloc(*list, (newentry + 2) * sizeof(void **));
+	if (!tmp)
+		return -1;
+
+	*list = tmp;
+	(*list)[newentry + 1] = NULL;
+
+	return newentry;
+}
+
+int lxc_append_string(char ***list, char *entry)
+{
+	int newentry = lxc_append_null_to_list((void ***)list);
+	char *copy;
+
+	copy = strdup(entry);
+	if (!copy)
+		return -1;
+
+	(*list)[newentry] = copy;
+
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index a0fa0e2..50e1847 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -258,6 +258,8 @@ extern char *lxc_append_paths(const char *first, const char *second);
 extern bool lxc_string_in_list(const char *needle, const char *haystack, char sep);
 extern char **lxc_string_split(const char *string, char sep);
 extern char **lxc_string_split_and_trim(const char *string, char sep);
+/* Append string to NULL-terminated string array. */
+extern int lxc_append_string(char ***list, char *entry);
 
 /* some simple array manipulation utilities */
 typedef void (*lxc_free_fn)(void *);

From b50cf4ac51462c56f1a35c4312075b07c72e7f5f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 6 Nov 2016 19:50:54 +0100
Subject: [PATCH 215/334] cgroups: remove isolated cpus from cpuset.cpus

In case the system was booted with

    isolcpus=n_i-n_j,n_k,n_m

we cannot simply copy the cpuset.cpus file from our parent cgroup. For example,
in the root cgroup cpuset.cpus will contain all of the cpus including the
isolated cpus. Copying the values of the root cgroup into a child cgroup will
lead to a wrong view in /proc/self/status: For the root cgroup
/sys/fs/cgroup/cpuset /proc/self/status will correctly show

    Cpus_allowed_list:      0-1,3

even though cpuset.cpus will show

    0-3

However, initializing a subcgroup in the cpuset controller by copying the
cpuset.cpus setting from the root cgroup will cause /proc/self/status to
incorrectly show

    Cpus_allowed_list:      0-3

Hence, we need to make sure to remove the isolated cpus from cpuset.cpus. Seth
has argued that this is not a kernel bug but by design. So let us be the smart
guys and fix this in liblxc.

The solution is straightforward: To avoid having to work with raw cpulist
strings we create cpumasks based on uint32_t bit arrays.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 325 +++++++++++++++++++++++++++++++++++++++--------
 src/lxc/utils.c          |   6 +-
 2 files changed, 280 insertions(+), 51 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index ec94099..9406ae1 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -33,21 +33,25 @@
  * under /sys/fs/cgroup/clist where clist is either the controller, or
  * a comman-separated list of controllers.
  */
+
 #include "config.h"
-#include <stdio.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <grp.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
+#include <string.h>
 #include <unistd.h>
-#include <dirent.h>
-#include <grp.h>
+#include <sys/types.h>
 
 #include "bdev.h"
-#include "log.h"
 #include "cgroup.h"
-#include "utils.h"
 #include "commands.h"
+#include "log.h"
+#include "utils.h"
 
 lxc_log_define(lxc_cgfsng, lxc);
 
@@ -251,6 +255,264 @@ struct hierarchy *get_hierarchy(const char *c)
 
 static char *must_make_path(const char *first, ...) __attribute__((sentinel));
 
+#define BATCH_SIZE 50
+static void batch_realloc(char **mem, size_t oldlen, size_t newlen)
+{
+	int newbatches = (newlen / BATCH_SIZE) + 1;
+	int oldbatches = (oldlen / BATCH_SIZE) + 1;
+
+	if (!*mem || newbatches > oldbatches) {
+		*mem = must_realloc(*mem, newbatches * BATCH_SIZE);
+	}
+}
+
+static void append_line(char **dest, size_t oldlen, char *new, size_t newlen)
+{
+	size_t full = oldlen + newlen;
+
+	batch_realloc(dest, oldlen, full + 1);
+
+	memcpy(*dest + oldlen, new, newlen + 1);
+}
+
+/* Slurp in a whole file */
+static char *read_file(char *fnam)
+{
+	FILE *f;
+	char *line = NULL, *buf = NULL;
+	size_t len = 0, fulllen = 0;
+	int linelen;
+
+	f = fopen(fnam, "r");
+	if (!f)
+		return NULL;
+	while ((linelen = getline(&line, &len, f)) != -1) {
+		append_line(&buf, fulllen, line, linelen);
+		fulllen += linelen;
+	}
+	fclose(f);
+	free(line);
+	return buf;
+}
+
+/* Taken over modified from the kernel sources. */
+#define NBITS 32 /* bits in uint32_t */
+#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, NBITS)
+
+static void set_bit(unsigned bit, uint32_t *bitarr)
+{
+	bitarr[bit / NBITS] |= (1 << (bit % NBITS));
+}
+
+static void clear_bit(unsigned bit, uint32_t *bitarr)
+{
+	bitarr[bit / NBITS] &= ~(1 << (bit % NBITS));
+}
+
+static bool is_set(unsigned bit, uint32_t *bitarr)
+{
+	return (bitarr[bit / NBITS] & (1 << (bit % NBITS))) != 0;
+}
+
+/* Create cpumask from cpulist aka turn:
+ *
+ *	0,2-3
+ *
+ *  into bit array
+ *
+ *	1 0 1 1
+ */
+static uint32_t *lxc_cpumask(char *buf, size_t nbits)
+{
+	char *token;
+	char *saveptr = NULL;
+	size_t arrlen = BITS_TO_LONGS(nbits);
+	uint32_t *bitarr = calloc(arrlen, sizeof(uint32_t));
+	if (!bitarr)
+		return NULL;
+
+	for (; (token = strtok_r(buf, ",", &saveptr)); buf = NULL) {
+		errno = 0;
+		unsigned start = strtoul(token, NULL, 0);
+		unsigned end = start;
+
+		char *range = strchr(token, '-');
+		if (range)
+			end = strtoul(range + 1, NULL, 0);
+		if (!(start <= end)) {
+			free(bitarr);
+			return NULL;
+		}
+
+		if (end >= nbits) {
+			free(bitarr);
+			return NULL;
+		}
+
+		while (start <= end)
+			set_bit(start++, bitarr);
+	}
+
+	return bitarr;
+}
+
+/* The largest integer that can fit into long int is 2^64. This is a
+ * 20-digit number. */
+#define LEN 21
+/* Turn cpumask into simple, comma-separated cpulist. */
+static char *lxc_cpumask_to_cpulist(uint32_t *bitarr, size_t nbits)
+{
+	size_t i;
+	int ret;
+	char numstr[LEN] = {0};
+	char **cpulist = NULL;
+
+	for (i = 0; i <= nbits; i++) {
+		if (is_set(i, bitarr)) {
+			ret = snprintf(numstr, LEN, "%lu", i);
+			if (ret < 0 || (size_t)ret >= LEN) {
+				lxc_free_array((void **)cpulist, free);
+				return NULL;
+			}
+			if (lxc_append_string(&cpulist, numstr) < 0) {
+				lxc_free_array((void **)cpulist, free);
+				return NULL;
+			}
+		}
+	}
+	return lxc_string_join(",", (const char **)cpulist, false);
+}
+
+static ssize_t get_max_cpus(char *cpulist)
+{
+	char *c1, *c2;
+	char *maxcpus = cpulist;
+	size_t cpus = 0;
+
+	c1 = strrchr(maxcpus, ',');
+	if (c1)
+		c1++;
+
+	c2 = strrchr(maxcpus, '-');
+	if (c2)
+		c2++;
+
+	if (!c1 && !c2)
+		c1 = maxcpus;
+	else if (c1 > c2)
+		c2 = c1;
+	else if (c1 < c2)
+		c1 = c2;
+	else if (!c1 && c2) // The reverse case is obvs. not needed.
+		c1 = c2;
+
+	/* If the above logic is correct, c1 should always hold a valid string
+	 * here.
+	 */
+
+	errno = 0;
+	cpus = strtoul(c1, NULL, 0);
+	if (errno != 0)
+		return -1;
+
+	return cpus;
+}
+
+static bool filter_and_set_cpus(char *path, bool am_initialized)
+{
+	char *lastslash, *fpath, oldv;
+	int ret;
+	ssize_t i;
+
+	ssize_t maxposs = 0, maxisol = 0;
+	char *cpulist = NULL, *posscpus = NULL, *isolcpus = NULL;
+	uint32_t *possmask = NULL, *isolmask = NULL;
+	bool bret = false;
+
+	lastslash = strrchr(path, '/');
+	if (!lastslash) { // bug...  this shouldn't be possible
+		ERROR("cgfsng:copy_parent_file: bad path %s", path);
+		return bret;
+	}
+	oldv = *lastslash;
+	*lastslash = '\0';
+	fpath = must_make_path(path, "cpuset.cpus", NULL);
+	posscpus = read_file(fpath);
+	if (!posscpus)
+		goto cleanup;
+
+	/* Get maximum number of cpus found in possible cpuset. */
+	maxposs = get_max_cpus(posscpus);
+	if (maxposs < 0)
+		goto cleanup;
+
+	isolcpus = read_file("/sys/devices/system/cpu/isolated");
+	if (!isolcpus)
+		goto cleanup;
+	if (!isdigit(isolcpus[0])) {
+		cpulist = posscpus;
+		/* No isolated cpus but we weren't already initialized by
+		 * someone. We should simply copy the parents cpuset.cpus
+		 * values.
+		 */
+		if (!am_initialized)
+			goto copy_parent;
+		/* No isolated cpus but we were already initialized by someone.
+		 * Nothing more to do for us.
+		 */
+		bret = true;
+		goto cleanup;
+	}
+
+	/* Get maximum number of cpus found in isolated cpuset. */
+	maxisol = get_max_cpus(isolcpus);
+	if (maxisol < 0)
+		goto cleanup;
+
+	if (maxposs < maxisol)
+		maxposs = maxisol;
+	maxposs++;
+
+	possmask = lxc_cpumask(posscpus, maxposs);
+	if (!possmask)
+		goto cleanup;
+
+	isolmask = lxc_cpumask(isolcpus, maxposs);
+	if (!isolmask)
+		goto cleanup;
+
+	for (i = 0; i <= maxposs; i++) {
+		if (is_set(i, isolmask) && is_set(i, possmask)) {
+			clear_bit(i, possmask);
+		}
+	}
+
+	cpulist = lxc_cpumask_to_cpulist(possmask, maxposs);
+	if (!cpulist) /* Bug */
+		goto cleanup;
+
+copy_parent:
+	*lastslash = oldv;
+	fpath = must_make_path(path, "cpuset.cpus", NULL);
+	ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false);
+	if (!ret)
+		bret = true;
+
+cleanup:
+	free(fpath);
+
+	free(isolcpus);
+	free(isolmask);
+
+	if (posscpus != cpulist)
+		free(posscpus);
+	free(possmask);
+
+	free(cpulist);
+	return bret;
+}
+
 /* Copy contents of parent(@path)/@file to @path/@file */
 static bool copy_parent_file(char *path, char *file)
 {
@@ -295,7 +557,7 @@ static bool copy_parent_file(char *path, char *file)
  * Since the h->base_path is populated by init or ourselves, we know
  * it is already initialized.
  */
-bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
+static bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 {
 	char *cgpath, *clonechildrenpath, v, *slash;
 
@@ -329,6 +591,10 @@ bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 		return false;
 	}
 
+	/* Make sure any isolated cpus are removed from cpuset.cpus. */
+	if (!filter_and_set_cpus(cgpath, v == '1'))
+		return false;
+
 	if (v == '1') {  /* already set for us by someone else */
 		free(clonechildrenpath);
 		free(cgpath);
@@ -336,8 +602,7 @@ bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 	}
 
 	/* copy parent's settings */
-	if (!copy_parent_file(cgpath, "cpuset.cpus") ||
-			!copy_parent_file(cgpath, "cpuset.mems")) {
+	if (!copy_parent_file(cgpath, "cpuset.mems")) {
 		free(cgpath);
 		free(clonechildrenpath);
 		return false;
@@ -605,46 +870,6 @@ static char *get_current_cgroup(char *basecginfo, char *controller)
 	}
 }
 
-#define BATCH_SIZE 50
-static void batch_realloc(char **mem, size_t oldlen, size_t newlen)
-{
-	int newbatches = (newlen / BATCH_SIZE) + 1;
-	int oldbatches = (oldlen / BATCH_SIZE) + 1;
-
-	if (!*mem || newbatches > oldbatches) {
-		*mem = must_realloc(*mem, newbatches * BATCH_SIZE);
-	}
-}
-
-static void append_line(char **dest, size_t oldlen, char *new, size_t newlen)
-{
-	size_t full = oldlen + newlen;
-
-	batch_realloc(dest, oldlen, full + 1);
-
-	memcpy(*dest + oldlen, new, newlen + 1);
-}
-
-/* Slurp in a whole file */
-static char *read_file(char *fnam)
-{
-	FILE *f;
-	char *line = NULL, *buf = NULL;
-	size_t len = 0, fulllen = 0;
-	int linelen;
-
-	f = fopen(fnam, "r");
-	if (!f)
-		return NULL;
-	while ((linelen = getline(&line, &len, f)) != -1) {
-		append_line(&buf, fulllen, line, linelen);
-		fulllen += linelen;
-	}
-	fclose(f);
-	free(line);
-	return buf;
-}
-
 /*
  * Given a hierarchy @mountpoint and base @path, verify that we can create
  * directories underneath it.
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index d6f8ecf..47c21cd 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1953,8 +1953,12 @@ static int lxc_append_null_to_list(void ***list)
 
 int lxc_append_string(char ***list, char *entry)
 {
-	int newentry = lxc_append_null_to_list((void ***)list);
 	char *copy;
+	int newentry;
+
+	newentry = lxc_append_null_to_list((void ***)list);
+	if (newentry < 0)
+		return -1;
 
 	copy = strdup(entry);
 	if (!copy)

From 3a5495cf2f6c1806f5a91d699448b15b510f146e Mon Sep 17 00:00:00 2001
From: Po-Hsu Lin <po-hsu.lin at canonical.com>
Date: Wed, 9 Nov 2016 19:13:28 +0800
Subject: [PATCH 216/334] Update Ubuntu release name: add zesty and remove wily

Add zesty to KNOWN_RELEASES
Remove EOL wily from KNOWN_RELEASES

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 src/tests/lxc-test-apparmor-mount | 2 +-
 src/tests/lxc-test-autostart      | 2 +-
 src/tests/lxc-test-unpriv         | 2 +-
 src/tests/lxc-test-usernic.in     | 2 +-
 templates/lxc-ubuntu-cloud.in     | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/tests/lxc-test-apparmor-mount b/src/tests/lxc-test-apparmor-mount
index 7ec5aad..74fd8c6 100755
--- a/src/tests/lxc-test-apparmor-mount
+++ b/src/tests/lxc-test-apparmor-mount
@@ -42,7 +42,7 @@ run_cmd() {
 }
 
 DONE=0
-KNOWN_RELEASES="precise trusty wily xenial yakkety"
+KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 MOUNTSR=/sys/kernel/security/apparmor/features/mount
 dnam=`mktemp -d`
 cname=`basename $dnam`
diff --git a/src/tests/lxc-test-autostart b/src/tests/lxc-test-autostart
index 76de54b..61dbdf1 100755
--- a/src/tests/lxc-test-autostart
+++ b/src/tests/lxc-test-autostart
@@ -22,7 +22,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 DONE=0
-KNOWN_RELEASES="precise trusty wily xenial yakkety"
+KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 cleanup() {
 	lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true
 
diff --git a/src/tests/lxc-test-unpriv b/src/tests/lxc-test-unpriv
index eddfd55..afe86fa 100755
--- a/src/tests/lxc-test-unpriv
+++ b/src/tests/lxc-test-unpriv
@@ -30,7 +30,7 @@ fi
 which newuidmap >/dev/null 2>&1 || { echo "'newuidmap' command is missing" >&2; exit 1; }
 
 DONE=0
-KNOWN_RELEASES="precise trusty wily xenial yakkety"
+KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 cleanup() {
 	cd /
 
diff --git a/src/tests/lxc-test-usernic.in b/src/tests/lxc-test-usernic.in
index d63b6bb..42a9a21 100755
--- a/src/tests/lxc-test-usernic.in
+++ b/src/tests/lxc-test-usernic.in
@@ -24,7 +24,7 @@
 # This test assumes an Ubuntu host
 
 DONE=0
-KNOWN_RELEASES="precise trusty wily xenial yakkety"
+KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 LXC_USER_NIC="@LIBEXECDIR@/lxc/lxc-user-nic"
 
 cleanup() {
diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in
index 7ae10c8..58642a9 100644
--- a/templates/lxc-ubuntu-cloud.in
+++ b/templates/lxc-ubuntu-cloud.in
@@ -25,7 +25,7 @@ STATE_DIR="@LOCALSTATEDIR@"
 HOOK_DIR="@LXCHOOKDIR@"
 CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep"
 LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
-KNOWN_RELEASES="precise trusty wily xenial yakkety"
+KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0}
 
 # Make sure the usual locations are in PATH

From 26312a76c8a1078976a5b391ece4f650a6f1b000 Mon Sep 17 00:00:00 2001
From: Po-Hsu Lin <po-hsu.lin at canonical.com>
Date: Thu, 10 Nov 2016 16:48:29 +0800
Subject: [PATCH 217/334] templates: add squashfs support to
 lxc-ubuntu-cloud.in

Add squashfs format file support for lxc-ubuntu-cloud.in

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 templates/lxc-ubuntu-cloud.in | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in
index 58642a9..763b15e 100644
--- a/templates/lxc-ubuntu-cloud.in
+++ b/templates/lxc-ubuntu-cloud.in
@@ -297,7 +297,11 @@ else
         [ "$stream" = "daily" ] || echo "You may try with '--stream=daily'"
         exit 1
     fi
-    url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'`
+    if [ "$release" = "precise" ] || [ "$release" = "trusty" ]; then
+        url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'`
+    else
+        url2=`echo $url1 | sed -e 's/.tar.gz/.squashfs/'`
+    fi
 fi
 
 filename=`basename $url2`
@@ -327,11 +331,15 @@ do_extract_rootfs() {
     echo "Extracting container rootfs"
     mkdir -p $rootfs
     cd $rootfs
-    if [ $in_userns -eq 1 ]; then
-        tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename"
-        mkdir -p $rootfs/dev/pts/
+    if [ "${filename##*.}" = "squashfs" ]; then
+        unsquashfs -n -f -d "$rootfs" "$cache/$filename"
     else
-        tar --numeric-owner -xpf "$cache/$filename"
+        if [ $in_userns -eq 1 ]; then
+            tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename"
+            mkdir -p $rootfs/dev/pts/
+        else
+            tar --numeric-owner -xpf "$cache/$filename"
+        fi
     fi
 }
 

From dafe5349cb3fa86b163d56c05231a56b8f0c36b4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 11 Nov 2016 00:29:15 +0100
Subject: [PATCH 218/334] cgroups: skip v2 hierarchy entry

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 9406ae1..1e38335 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -911,6 +911,18 @@ static void get_existing_subsystems(char ***klist, char ***nlist)
 		if (!p2)
 			continue;
 		*p2 = '\0';
+
+		/* If we have a mixture between cgroup v1 and cgroup v2
+		 * hierarchies, then /proc/self/cgroup contains entries of the
+		 * form:
+		 *
+		 *	0::/some/path
+		 *
+		 * We need to skip those.
+		 */
+		if ((p2 - p) == 0)
+			continue;
+
 		for (tok = strtok_r(p, ",", &saveptr); tok;
 				tok = strtok_r(NULL, ",", &saveptr)) {
 			if (strncmp(tok, "name=", 5) == 0)

From d2b51fd10886f9c23c1f237c7ce1abaaa843067e Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 12 Nov 2016 12:29:26 +0100
Subject: [PATCH 219/334] also stop lxc-net in runlevels 0 and 6

there is no reason to not do this :)

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/sysvinit/lxc-net.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/init/sysvinit/lxc-net.in b/config/init/sysvinit/lxc-net.in
index 187feed..7a1e62a 100644
--- a/config/init/sysvinit/lxc-net.in
+++ b/config/init/sysvinit/lxc-net.in
@@ -12,7 +12,7 @@
 # Should-Start:
 # Should-Stop:
 # Default-Start: 2 3 4 5
-# Default-Stop: 1
+# Default-Stop: 0 1 6
 # Short-Description: Bring up/down LXC Network Bridge
 # Description: Bring up/down LXC Network Bridge
 ### END INIT INFO

From 991c1b955ab88047d5915fb58f7e27e9bf3478e8 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 12 Nov 2016 14:47:33 +0100
Subject: [PATCH 220/334] add lxc.egg-info to gitignore

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 5c4618e..205f18e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,7 @@ src/lxc/version.h
 src/python-lxc/setup.py
 src/python-lxc/build/
 src/python-lxc/lxc/__pycache__/
+src/python-lxc/lxc.egg-info/
 
 src/tests/lxc-test-device-add-remove
 src/tests/lxc-test-attach

From 50066905b4aa6cb6df5f62a5f34a2db98dd504a7 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Sat, 12 Nov 2016 14:44:40 +0100
Subject: [PATCH 221/334] install bash completion where pkg-config tells us to

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/bash/Makefile.am | 11 +----------
 configure.ac            |  8 ++++++++
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/config/bash/Makefile.am b/config/bash/Makefile.am
index b1768c9..b97e2a4 100644
--- a/config/bash/Makefile.am
+++ b/config/bash/Makefile.am
@@ -1,14 +1,5 @@
 EXTRA_DIST = lxc
 
 if ENABLE_BASH
-install-bash:
-	$(MKDIR_P) $(DESTDIR)$(sysconfdir)/bash_completion.d/
-	$(INSTALL_DATA) lxc $(DESTDIR)$(sysconfdir)/bash_completion.d/
-
-uninstall-bash:
-	rm -f $(DESTDIR)$(sysconfdir)/bash_completion.d/lxc
-	rmdir $(DESTDIR)$(sysconfdir)/bash_completion.d/ || :
-
-install-data-local: install-bash
-uninstall-local: uninstall-bash
+dist_bashcomp_DATA = lxc
 endif
diff --git a/configure.ac b/configure.ac
index 287e5d6..ad5e16c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -475,6 +475,14 @@ AC_ARG_ENABLE([bash],
 	[], [enable_bash=yes])
 AM_CONDITIONAL([ENABLE_BASH], [test "x$enable_bash" = "xyes"])
 
+AM_COND_IF([ENABLE_BASH],
+	[AC_MSG_CHECKING([bash completion directory])
+	PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
+		bashcompdir="${sysconfdir}/bash_completion.d")
+	AC_MSG_RESULT([$bashcompdir])
+	AC_SUBST(bashcompdir)
+	])
+
 # Optional test binaries
 AC_ARG_ENABLE([tests],
 	[AC_HELP_STRING([--enable-tests], [build test/example binaries [default=no]])],

From 134bceb3cdc23f9459f50ece92be0a6d2c84a211 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 13 Nov 2016 17:10:41 +0100
Subject: [PATCH 222/334] conf: do not use %m format specifier

This is a GNU extension and some libcs might be missing it.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 7e0336f..cb5ac25 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1958,7 +1958,7 @@ FILE *write_mount_file(struct lxc_list *mount)
 
 	file = tmpfile();
 	if (!file) {
-		ERROR("tmpfile error: %m");
+		ERROR("Could not create temporary file: %s.", strerror(errno));
 		return NULL;
 	}
 

From 8da006e44b58824d803fe6586fb5174e8e2ebb6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 14 Nov 2016 11:53:07 -0500
Subject: [PATCH 223/334] debian: Don't depend on libui-dialog-perl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This package doesn't exist in stretch anymore, and it's unclear why we
were depending on a library to begin with (as opposed to having it
brought by whatever needs it).

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 templates/lxc-debian.in | 1 -
 1 file changed, 1 deletion(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index ee4c4f1..55afee1 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -270,7 +270,6 @@ download_debian()
 $init,\
 ifupdown,\
 locales,\
-libui-dialog-perl,\
 dialog,\
 isc-dhcp-client,\
 netbase,\

From bf5174e0b22913f118a7962f3445a8813d0a4163 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 15 Nov 2016 06:19:55 +0100
Subject: [PATCH 224/334] cgroups: use %zu format specifier to print size_t

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 1e38335..57a13dc 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -358,20 +358,21 @@ static uint32_t *lxc_cpumask(char *buf, size_t nbits)
 }
 
 /* The largest integer that can fit into long int is 2^64. This is a
- * 20-digit number. */
-#define LEN 21
+ * 20-digit number.
+ */
+#define __IN_TO_STR_LEN 21
 /* Turn cpumask into simple, comma-separated cpulist. */
 static char *lxc_cpumask_to_cpulist(uint32_t *bitarr, size_t nbits)
 {
 	size_t i;
 	int ret;
-	char numstr[LEN] = {0};
+	char numstr[__IN_TO_STR_LEN] = {0};
 	char **cpulist = NULL;
 
 	for (i = 0; i <= nbits; i++) {
 		if (is_set(i, bitarr)) {
-			ret = snprintf(numstr, LEN, "%lu", i);
-			if (ret < 0 || (size_t)ret >= LEN) {
+			ret = snprintf(numstr, __IN_TO_STR_LEN, "%zu", i);
+			if (ret < 0 || (size_t)ret >= __IN_TO_STR_LEN) {
 				lxc_free_array((void **)cpulist, free);
 				return NULL;
 			}

From 85031ca01bc4b71e2777e31316de73b0d22ed637 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber at redhat.com>
Date: Tue, 15 Nov 2016 15:47:31 +0000
Subject: [PATCH 225/334] lxc-checkpoint: automatically detect if --external or
 --veth-pair

With the criu release 2.8 criu deprecated the --veth-pair command-line
option in favor of --external:

f2037e6 veth: Make --external support --veth-pair

git tag --contains f2037e6d3445fc400
v2.8

With this commit lxc-checkpoint will automatically switch between
the new and old command-line option dependent on the detected
criu version.

For criu version older than 2.8 something like this will be used:

  --veth-pair eth0=vethYOK6RW at lxcbr0

and starting with criu version 2.8 it will look like this:

  --external veth[eth0]:vethCRPEYL at lxcbr0

Signed-off-by: Adrian Reber <areber at redhat.com>
---
 src/lxc/criu.c | 37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 5456cc1..b0a4239 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -58,6 +58,7 @@
 #define CRIU_GITID_PATCHLEVEL	0
 
 #define CRIU_IN_FLIGHT_SUPPORT	"2.4"
+#define CRIU_EXTERNAL_NOT_VETH	"2.8"
 
 lxc_log_define(lxc_criu, lxc);
 
@@ -481,7 +482,19 @@ static void exec_criu(struct criu_opts *opts)
 
 		lxc_list_for_each(it, &opts->c->lxc_conf->network) {
 			char eth[128], *veth;
+			char *fmt;
 			struct lxc_netdev *n = it->elem;
+			bool external_not_veth;
+
+			if (strcmp(opts->criu_version, CRIU_EXTERNAL_NOT_VETH) >= 0) {
+				/* Since criu version 2.8 the usage of --veth-pair
+				 * has been deprecated:
+				 * git tag --contains f2037e6d3445fc400
+				 * v2.8 */
+				external_not_veth = true;
+			} else {
+				external_not_veth = false;
+			}
 
 			if (n->name) {
 				if (strlen(n->name) >= sizeof(eth))
@@ -497,10 +510,21 @@ static void exec_criu(struct criu_opts *opts)
 			case LXC_NET_VETH:
 				veth = n->priv.veth_attr.pair;
 
-				if (n->link)
-					ret = snprintf(buf, sizeof(buf), "veth[%s]:%s@%s", eth, veth, n->link);
-				else
-					ret = snprintf(buf, sizeof(buf), "veth[%s]:%s", eth, veth);
+				if (n->link) {
+					if (external_not_veth)
+						fmt = "veth[%s]:%s@%s";
+					else
+						fmt = "%s=%s@%s";
+
+					ret = snprintf(buf, sizeof(buf), fmt, eth, veth, n->link);
+				} else {
+					if (external_not_veth)
+						fmt = "veth[%s]:%s";
+					else
+						fmt = "%s=%s";
+
+					ret = snprintf(buf, sizeof(buf), fmt, eth, veth);
+				}
 				if (ret < 0 || ret >= sizeof(buf))
 					goto err;
 				break;
@@ -523,7 +547,10 @@ static void exec_criu(struct criu_opts *opts)
 				goto err;
 			}
 
-			DECLARE_ARG("--external");
+			if (external_not_veth)
+				DECLARE_ARG("--external");
+			else
+				DECLARE_ARG("--veth-pair");
 			DECLARE_ARG(buf);
 			netnr++;
 		}

From d3795ab5f0308ee1cb83e47b0ad12e2eb1ffb3a4 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 16 Nov 2016 16:43:20 +0100
Subject: [PATCH 226/334] cgroups: prevent segfault in cgfsng

When we set LXC_DEBUG_CGFSNG=1 we print out info about detected cgroup
hierarchies. When there's no named cgroup mounted we need to make sure that we
don't try to index an unallocated pointer.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 57a13dc..795f326 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -946,44 +946,47 @@ static void trim(char *s)
 
 static void print_init_debuginfo(struct cgfsng_handler_data *d)
 {
+	struct hierarchy **it;
 	int i;
 
 	if (!getenv("LXC_DEBUG_CGFSNG"))
 		return;
 
-	printf("Cgroup information:\n");
-	printf("  container name: %s\n", d->name);
-	printf("  lxc.cgroup.use: %s\n", cgroup_use ? cgroup_use : "(none)");
-	printf("  lxc.cgroup.pattern: %s\n", d->cgroup_pattern);
-	printf("  cgroup: %s\n", d->container_cgroup ? d->container_cgroup : "(none)");
+	DEBUG("Cgroup information:");
+	DEBUG("  container name: %s", d->name ? d->name : "(null)");
+	DEBUG("  lxc.cgroup.use: %s", cgroup_use ? cgroup_use : "(null)");
+	DEBUG("  lxc.cgroup.pattern: %s", d->cgroup_pattern ? d->cgroup_pattern : "(null)");
+	DEBUG("  cgroup: %s", d->container_cgroup ? d->container_cgroup : "(null)");
 	if (!hierarchies) {
-		printf("  No hierarchies found.\n");
+		DEBUG("  No hierarchies found.");
 		return;
 	}
-	printf("  Hierarchies:\n");
-	for (i = 0; hierarchies[i]; i++) {
-		struct hierarchy *h = hierarchies[i];
+	DEBUG("  Hierarchies:");
+	for (i = 0, it = hierarchies; it && *it; it++, i++) {
+		char **cit;
 		int j;
-		printf("  %d: base_cgroup %s\n", i, h->base_cgroup);
-		printf("      mountpoint %s\n", h->mountpoint);
-		printf("      controllers:\n");
-		for (j = 0; h->controllers[j]; j++)
-			printf("     %d: %s\n", j, h->controllers[j]);
+		DEBUG("  %d: base_cgroup %s", i, (*it)->base_cgroup ? (*it)->base_cgroup : "(null)");
+		DEBUG("      mountpoint %s", (*it)->mountpoint ? (*it)->mountpoint : "(null)");
+		DEBUG("      controllers:");
+		for (j = 0, cit = (*it)->controllers; cit && *cit; cit++, j++)
+			DEBUG("      %d: %s", j, *cit);
 	}
 }
 
 static void print_basecg_debuginfo(char *basecginfo, char **klist, char **nlist)
 {
 	int k;
+	char **it;
 	if (!getenv("LXC_DEBUG_CGFSNG"))
 		return;
 
-	printf("basecginfo is %s\n", basecginfo);
+	printf("basecginfo is:\n");
+	printf("%s\n", basecginfo);
 
-	for (k = 0; klist[k]; k++)
-		printf("kernel subsystem %d: %s\n", k, klist[k]);
-	for (k = 0; nlist[k]; k++)
-		printf("named subsystem %d: %s\n", k, nlist[k]);
+	for (k = 0, it = klist; it && *it; it++, k++)
+		printf("kernel subsystem %d: %s\n", k, *it);
+	for (k = 0, it = nlist; it && *it; it++, k++)
+		printf("named subsystem %d: %s\n", k, *it);
 }
 
 /*

From c1ff672f19227257becc434d0280b2920822dd72 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 27 Oct 2016 14:37:24 +0200
Subject: [PATCH 227/334] utils: add lxc_preserve_ns()

This allows to retrieve a file descriptor referring to a namespace.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 13 +++++++++++++
 src/lxc/utils.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 47c21cd..e7b498e 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1968,3 +1968,16 @@ int lxc_append_string(char ***list, char *entry)
 
 	return 0;
 }
+
+int lxc_preserve_ns(const int pid, const char *ns)
+{
+	int ret;
+	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 3 /* /ns */ + 20 /* /NS_NAME */ + 1 /* \0 */;
+	char path[len];
+
+	ret = snprintf(path, len, "/proc/%d/ns/%s", pid, ns);
+	if (ret < 0 || (size_t)ret >= len)
+		return -1;
+
+	return open(path, O_RDONLY | O_CLOEXEC);
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 50e1847..9b92daf 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -312,6 +312,7 @@ int open_devnull(void);
 int set_stdfds(int fd);
 int null_stdfds(void);
 int lxc_count_file_lines(const char *fn);
+int lxc_preserve_ns(const int pid, const char *ns);
 
 /* Check whether a signal is blocked by a process. */
 bool task_blocking_signal(pid_t pid, int signal);

From e9f7729ea6ee7edc17e65638b28671b7d3fbdc64 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 27 Oct 2016 14:35:26 +0200
Subject: [PATCH 228/334] start: add netnsfd to lxc_handler

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c  |  1 +
 src/lxc/start.c | 52 ++++++++++++++++++++--------------------------------
 src/lxc/start.h |  1 +
 3 files changed, 22 insertions(+), 32 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index cb5ac25..70bf08f 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2591,6 +2591,7 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 				      veth1, netdev->link, strerror(-err));
 			goto out_delete;
 		}
+		INFO("Attached '%s': to the bridge '%s': ", veth1, netdev->link);
 	}
 
 	err = lxc_netdev_up(veth1);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index dcee6f3..83fdb35 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -549,6 +549,12 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 			handler->nsfd[i] = -1;
 		}
 	}
+
+	if (handler->netnsfd >= 0) {
+		close(handler->netnsfd);
+		handler->netnsfd = -1;
+	}
+
 	lxc_set_state(name, handler, STOPPED);
 
 	if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) {
@@ -1026,24 +1032,28 @@ void resolve_clone_flags(struct lxc_handler *handler)
 	handler->clone_flags = CLONE_NEWPID | CLONE_NEWNS;
 
 	if (!lxc_list_empty(&handler->conf->id_map)) {
-		INFO("Cloning a new user namespace");
+		INFO("Cloning a new USER namespace");
 		handler->clone_flags |= CLONE_NEWUSER;
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
-		if (!lxc_requests_empty_network(handler))
+		if (!lxc_requests_empty_network(handler)) {
+			INFO("Cloning a new NET namespace");
 			handler->clone_flags |= CLONE_NEWNET;
+		}
 	} else {
-		INFO("Inheriting a net namespace");
+		INFO("Inheriting a NET namespace");
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) {
+		INFO("Cloning a new IPC namespace");
 		handler->clone_flags |= CLONE_NEWIPC;
 	} else {
 		INFO("Inheriting an IPC namespace");
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
+		INFO("Cloning a new UTS namespace");
 		handler->clone_flags |= CLONE_NEWUTS;
 	} else {
 		INFO("Inheriting a UTS namespace");
@@ -1275,6 +1285,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 	}
 
 	lxc_sync_fini(handler);
+	handler->netnsfd = lxc_preserve_ns(handler->pid, "net");
 
 	return 0;
 
@@ -1294,26 +1305,6 @@ static int lxc_spawn(struct lxc_handler *handler)
 	return -1;
 }
 
-int get_netns_fd(int pid)
-{
-	char path[MAXPATHLEN];
-	int ret, fd;
-
-	ret = snprintf(path, MAXPATHLEN, "/proc/%d/ns/net", pid);
-	if (ret < 0 || ret >= MAXPATHLEN) {
-		WARN("Failed to pin netns file for pid %d", pid);
-		return -1;
-	}
-
-	fd = open(path, O_RDONLY);
-	if (fd < 0) {
-		WARN("Failed to pin netns file %s for pid %d: %s",
-				path, pid, strerror(errno));
-		return -1;
-	}
-	return fd;
-}
-
 int __lxc_start(const char *name, struct lxc_conf *conf,
 		struct lxc_operations* ops, void *data, const char *lxcpath,
 		bool backgrounded)
@@ -1321,7 +1312,6 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	struct lxc_handler *handler;
 	int err = -1;
 	int status;
-	int netnsfd = -1;
 
 	handler = lxc_init(name, conf, lxcpath);
 	if (!handler) {
@@ -1331,6 +1321,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	handler->ops = ops;
 	handler->data = data;
 	handler->backgrounded = backgrounded;
+	handler->netnsfd = -1;
 
 	if (must_drop_cap_sys_boot(handler->conf)) {
 		#if HAVE_SYS_CAPABILITY_H
@@ -1372,13 +1363,13 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 
 	handler->conf->reboot = 0;
 
-	netnsfd = get_netns_fd(handler->pid);
-
 	err = lxc_poll(name, handler);
 	if (err) {
 		ERROR("mainloop exited with an error");
-		if (netnsfd >= 0)
-			close(netnsfd);
+		if (handler->netnsfd >= 0) {
+			close(handler->netnsfd);
+			handler->netnsfd = -1;
+		}
 		goto out_abort;
 	}
 
@@ -1410,14 +1401,11 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	}
 
 	DEBUG("Pushing physical nics back to host namespace");
-	lxc_restore_phys_nics_to_netns(netnsfd, handler->conf);
+	lxc_restore_phys_nics_to_netns(handler->netnsfd, handler->conf);
 
 	DEBUG("Tearing down virtual network devices used by container");
 	lxc_delete_network(handler);
 
-	if (netnsfd >= 0)
-		close(netnsfd);
-
 	if (handler->pinfd >= 0) {
 		close(handler->pinfd);
 		handler->pinfd = -1;
diff --git a/src/lxc/start.h b/src/lxc/start.h
index fe47ab9..65d553b 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -77,6 +77,7 @@ struct lxc_handler {
 	int ttysock[2]; // socketpair for child->parent tty fd passing
 	bool backgrounded; // indicates whether should we close std{in,out,err} on start
 	int nsfd[LXC_NS_MAX];
+	int netnsfd;
 };
 
 

From e437b4ba2a78bcdc7e54a4dca3a488b06c0ad15d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 27 Oct 2016 14:39:45 +0200
Subject: [PATCH 229/334] conf: use lxc_preserve_ns()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 70bf08f..db3ef90 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2399,24 +2399,20 @@ static int setup_network(struct lxc_list *network)
 /* try to move physical nics to the init netns */
 void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
 {
-	int i, ret, oldfd;
-	char path[MAXPATHLEN];
+	int i, oldfd;
 	char ifname[IFNAMSIZ];
 
 	if (netnsfd < 0 || conf->num_savednics == 0)
 		return;
 
-	INFO("running to reset %d nic names", conf->num_savednics);
+	INFO("Running to reset %d nic names.", conf->num_savednics);
 
-	ret = snprintf(path, MAXPATHLEN, "/proc/self/ns/net");
-	if (ret < 0 || ret >= MAXPATHLEN) {
-		WARN("Failed to open monitor netns fd");
-		return;
-	}
-	if ((oldfd = open(path, O_RDONLY)) < 0) {
-		SYSERROR("Failed to open monitor netns fd");
+	oldfd = lxc_preserve_ns(getpid(), "net");
+	if (oldfd < 0) {
+		SYSERROR("Failed to open monitor netns fd.");
 		return;
 	}
+
 	if (setns(netnsfd, 0) != 0) {
 		SYSERROR("Failed to enter container netns to reset nics");
 		close(oldfd);

From 377d011937aaf656b4e2b037c73ce72c66e2d21b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 12:33:30 +0200
Subject: [PATCH 230/334] attach: use lxc_preserve_ns()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/attach.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 0d9e3d0..e7e67f4 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -214,7 +214,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 {
 	char path[MAXPATHLEN];
 	/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
-	 * the file for user namepsaces in /proc/$pid/ns will be called
+	 * the file for user namespaces in /proc/$pid/ns will be called
 	 * 'user' once the kernel supports it
 	 */
 	static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup" };
@@ -242,8 +242,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 			continue;
 		}
 
-		snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]);
-		fd[i] = open(path, O_RDONLY | O_CLOEXEC);
+		fd[i] = lxc_preserve_ns(pid, ns[i]);
 		if (fd[i] < 0) {
 			saved_errno = errno;
 

From 671c3c49fef3b4259f1f1b757467c85d095a59f1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 10:48:20 +0200
Subject: [PATCH 231/334] lxc_user_nic: use lxc_preserve_ns()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/lxc_user_nic.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
index 0cb38ba..409a53a 100644
--- a/src/lxc/lxc_user_nic.c
+++ b/src/lxc/lxc_user_nic.c
@@ -673,25 +673,21 @@ static bool create_db_dir(char *fnam)
 
 static int rename_in_ns(int pid, char *oldname, char **newnamep)
 {
-	char nspath[MAXPATHLEN];
 	int fd = -1, ofd = -1, ret, ifindex = -1;
 	bool grab_newname = false;
 
-	ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/net", getpid());
-	if (ret < 0 || ret >= MAXPATHLEN)
-		return -1;
-	if ((ofd = open(nspath, O_RDONLY)) < 0) {
-		fprintf(stderr, "Opening %s\n", nspath);
+	ofd = lxc_preserve_ns(getpid(), "net");
+	if (ofd < 0) {
+		fprintf(stderr, "Failed opening network namespace path for '%d'.", getpid());
 		return -1;
 	}
-	ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/net", pid);
-	if (ret < 0 || ret >= MAXPATHLEN)
-		goto out_err;
 
-	if ((fd = open(nspath, O_RDONLY)) < 0) {
-		fprintf(stderr, "Opening %s\n", nspath);
-		goto out_err;
+	fd = lxc_preserve_ns(pid, "net");
+	if (fd < 0) {
+		fprintf(stderr, "Failed opening network namespace path for '%d'.", pid);
+		return -1;
 	}
+
 	if (setns(fd, 0) < 0) {
 		fprintf(stderr, "setns to container network namespace\n");
 		goto out_err;

From ed8e8611813c85c5dea49291f3432a23ead1726d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 27 Oct 2016 21:09:27 +0200
Subject: [PATCH 232/334] conf, start: improve log output

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c  |  2 +-
 src/lxc/start.c | 26 +++++++++++++++++---------
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index db3ef90..f217d82 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3047,7 +3047,7 @@ int lxc_assign_network(const char *lxcpath, char *lxcname,
 			return -1;
 		}
 
-		DEBUG("move '%s' to '%d'", netdev->name, pid);
+		DEBUG("move '%s'/'%s' to '%d': .", ifname, netdev->name, pid);
 	}
 
 	return 0;
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 83fdb35..7d4517e 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -754,6 +754,8 @@ static int do_start(void *data)
 		if (ret < 0) {
 			SYSERROR("Error unsharing network namespace");
 			goto out_warn_father;
+		} else {
+			INFO("Unshared NET namespace.");
 		}
 	}
 
@@ -1030,33 +1032,35 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
 void resolve_clone_flags(struct lxc_handler *handler)
 {
 	handler->clone_flags = CLONE_NEWPID | CLONE_NEWNS;
+	INFO("Adding CLONE_NEWPID to clone flags.");
+	INFO("Adding CLONE_NEWNS to clone flags.");
 
 	if (!lxc_list_empty(&handler->conf->id_map)) {
-		INFO("Cloning a new USER namespace");
+		INFO("Adding CLONE_NEWUSER to clone flags.");
 		handler->clone_flags |= CLONE_NEWUSER;
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
 		if (!lxc_requests_empty_network(handler)) {
-			INFO("Cloning a new NET namespace");
+			INFO("Adding CLONE_NEWNET to clone flags.");
 			handler->clone_flags |= CLONE_NEWNET;
 		}
 	} else {
-		INFO("Inheriting a NET namespace");
+		INFO("Inheriting a NET namespace.");
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) {
-		INFO("Cloning a new IPC namespace");
+		INFO("Adding CLONE_NEWIPC to clone flags.");
 		handler->clone_flags |= CLONE_NEWIPC;
 	} else {
-		INFO("Inheriting an IPC namespace");
+		INFO("Inheriting an IPC namespace.");
 	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
-		INFO("Cloning a new UTS namespace");
+		INFO("Adding CLONE_NEWUTS to clone flags.");
 		handler->clone_flags |= CLONE_NEWUTS;
 	} else {
-		INFO("Inheriting a UTS namespace");
+		INFO("Inheriting a UTS namespace.");
 	}
 }
 
@@ -1163,8 +1167,10 @@ static int lxc_spawn(struct lxc_handler *handler)
 		flags &= ~CLONE_NEWNET;
 	handler->pid = lxc_clone(do_start, handler, flags);
 	if (handler->pid < 0) {
-		SYSERROR("failed to fork into a new namespace");
+		SYSERROR("Failed to fork into a set of new namespaces.");
 		goto out_delete_net;
+	} else {
+		INFO("Cloned a set of new namespaces.");
 	}
 
 	if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid, &errmsg)) {
@@ -1343,8 +1349,10 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 		/* if the backing store is a device, mount it here and now */
 		if (rootfs_is_blockdev(conf)) {
 			if (unshare(CLONE_NEWNS) < 0) {
-				ERROR("Error unsharing mounts");
+				ERROR("Error unsharing MOUNT namespace.");
 				goto out_fini_nonet;
+			} else {
+				INFO("Unshared MOUNT namespace.");
 			}
 			remount_all_slave();
 			if (do_rootfs_setup(conf, name, lxcpath) < 0) {

From c7dc07216f6217df30ab7a3048ecf1326206195c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Thu, 27 Oct 2016 14:41:49 +0200
Subject: [PATCH 233/334] conf: explicitly remove veth device from host

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 42 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 8 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index f217d82..132b9b0 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2882,6 +2882,7 @@ int lxc_create_network(struct lxc_handler *handler)
 
 void lxc_delete_network(struct lxc_handler *handler)
 {
+	int ret;
 	struct lxc_list *network = &handler->conf->network;
 	struct lxc_list *iterator;
 	struct lxc_netdev *netdev;
@@ -2891,24 +2892,49 @@ void lxc_delete_network(struct lxc_handler *handler)
 
 		if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
 			if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
-				WARN("failed to rename to the initial name the " \
-				     "netdev '%s'", netdev->link);
+				WARN("Failed to rename to the initial name the " \
+						"netdev '%s'", netdev->link);
 			continue;
 		}
 
 		if (netdev_deconf[netdev->type](handler, netdev)) {
-			WARN("failed to destroy netdev");
+			WARN("Failed to destroy netdev");
 		}
 
 		/* Recent kernel remove the virtual interfaces when the network
 		 * namespace is destroyed but in case we did not moved the
 		 * interface to the network namespace, we have to destroy it
 		 */
-		if (netdev->ifindex != 0 &&
-		    lxc_netdev_delete_by_index(netdev->ifindex))
-			WARN("failed to remove interface %d '%s'",
-				netdev->ifindex,
-				netdev->name ? netdev->name : "(null)");
+		if (netdev->ifindex != 0) {
+			ret = lxc_netdev_delete_by_index(netdev->ifindex);
+			if (ret < 0)
+				WARN("Failed to remove interface %d '%s': %s.",
+						netdev->ifindex,
+						netdev->name ? netdev->name : "(null)", strerror(-ret));
+			else
+				INFO("Removed interface %d '%s'.",
+						netdev->ifindex,
+						netdev->name ? netdev->name : "(null)");
+		}
+
+		/* Explicitly delete host veth device to prevent lingering
+		 * devices. We had issues in LXD around this.
+		 */
+		if (netdev->type == LXC_NET_VETH) {
+			char *hostveth = NULL;
+			if (netdev->priv.veth_attr.pair)
+				hostveth = netdev->priv.veth_attr.pair;
+			else if (strlen(netdev->priv.veth_attr.veth1) > 0)
+				hostveth = netdev->priv.veth_attr.veth1;
+
+			if (hostveth) {
+				ret = lxc_netdev_delete_by_name(hostveth);
+				if (ret < 0)
+					WARN("Failed to remove '%s' from host.", hostveth);
+				else
+					INFO("Deleted '%s' from host.", hostveth);
+			}
+		}
 	}
 }
 

From 74ba41200257cf25dcee283a7c65dcd4f54e75da Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 13:40:44 +0200
Subject: [PATCH 234/334] conf, start: be smarter when deleting networks

- So far we blindly called lxc_delete_network() to make sure that we deleted
  all network interfaces. This resulted in pointless netlink calls, especially
  when a container had multiple networks defined. Let's be smarter and have
  lxc_delete_network() return a boolean that indicates whether *all* configured
  networks have been deleted. If so, don't needlessly try to delete them again
  in start.c. This also decreases confusing error messages a user might see.

- When we receive -ENODEV from one of our lxc_netdev_delete_*() functions,
  let's assume that either the network device already got deleted or that it
  got moved to a different network namespace. Inform the user about this but do
  not report an error in this case.

- When we have explicitly deleted the host side of a veth pair let's
  immediately free(priv.veth_attr.pair) and NULL it, or
  memset(priv.veth_attr.pair, ...) the corresponding member so we don't
  needlessly try to destroy them again when we have to call
  lxc_delete_network() again in start.c

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c  | 61 ++++++++++++++++++++++++++++++++++++++-------------------
 src/lxc/conf.h  |  2 +-
 src/lxc/start.c | 10 ++++++++--
 3 files changed, 50 insertions(+), 23 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 132b9b0..63aa27e 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2880,20 +2880,22 @@ int lxc_create_network(struct lxc_handler *handler)
 	return 0;
 }
 
-void lxc_delete_network(struct lxc_handler *handler)
+bool lxc_delete_network(struct lxc_handler *handler)
 {
 	int ret;
 	struct lxc_list *network = &handler->conf->network;
 	struct lxc_list *iterator;
 	struct lxc_netdev *netdev;
+	bool deleted_all = true;
 
 	lxc_list_for_each(iterator, network) {
 		netdev = iterator->elem;
 
 		if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
 			if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
-				WARN("Failed to rename to the initial name the " \
-						"netdev '%s'", netdev->link);
+				WARN("Failed to rename interface with index %d "
+				     "to its initial name \"%s\".",
+				     netdev->ifindex, netdev->link);
 			continue;
 		}
 
@@ -2907,35 +2909,54 @@ void lxc_delete_network(struct lxc_handler *handler)
 		 */
 		if (netdev->ifindex != 0) {
 			ret = lxc_netdev_delete_by_index(netdev->ifindex);
-			if (ret < 0)
-				WARN("Failed to remove interface %d '%s': %s.",
-						netdev->ifindex,
-						netdev->name ? netdev->name : "(null)", strerror(-ret));
-			else
-				INFO("Removed interface %d '%s'.",
-						netdev->ifindex,
-						netdev->name ? netdev->name : "(null)");
+			if (-ret == ENODEV) {
+				INFO("Interface \"%s\" with index %d already "
+				     "deleted or existing in different network "
+				     "namespace.",
+				     netdev->name ? netdev->name : "(null)",
+				     netdev->ifindex);
+			} else if (ret < 0) {
+				deleted_all = false;
+				WARN("Failed to remove interface \"%s\" with "
+				     "index %d: %s.",
+				     netdev->name ? netdev->name : "(null)",
+				     netdev->ifindex, strerror(-ret));
+			} else {
+				INFO("Removed interface \"%s\" with index %d.",
+				     netdev->name ? netdev->name : "(null)",
+				     netdev->ifindex);
+			}
 		}
 
 		/* Explicitly delete host veth device to prevent lingering
 		 * devices. We had issues in LXD around this.
 		 */
 		if (netdev->type == LXC_NET_VETH) {
-			char *hostveth = NULL;
-			if (netdev->priv.veth_attr.pair)
+			char *hostveth;
+			if (netdev->priv.veth_attr.pair) {
 				hostveth = netdev->priv.veth_attr.pair;
-			else if (strlen(netdev->priv.veth_attr.veth1) > 0)
+				ret = lxc_netdev_delete_by_name(hostveth);
+				if (ret < 0) {
+					WARN("Failed to remove interface \"%s\" from host: %s.", hostveth, strerror(-ret));
+				} else {
+					INFO("Removed interface \"%s\" from host.", hostveth);
+					free(netdev->priv.veth_attr.pair);
+					netdev->priv.veth_attr.pair = NULL;
+				}
+			} else if (strlen(netdev->priv.veth_attr.veth1) > 0) {
 				hostveth = netdev->priv.veth_attr.veth1;
-
-			if (hostveth) {
 				ret = lxc_netdev_delete_by_name(hostveth);
-				if (ret < 0)
-					WARN("Failed to remove '%s' from host.", hostveth);
-				else
-					INFO("Deleted '%s' from host.", hostveth);
+				if (ret < 0) {
+					WARN("Failed to remove \"%s\" from host: %s.", hostveth, strerror(-ret));
+				} else {
+					INFO("Removed interface \"%s\" from host.", hostveth);
+					memset((void *)&netdev->priv.veth_attr.veth1, 0, sizeof(netdev->priv.veth_attr.veth1));
+				}
 			}
 		}
 	}
+
+	return deleted_all;
 }
 
 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 10d78e5..fff89bc 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -401,7 +401,7 @@ extern int pin_rootfs(const char *rootfs);
 
 extern int lxc_requests_empty_network(struct lxc_handler *handler);
 extern int lxc_create_network(struct lxc_handler *handler);
-extern void lxc_delete_network(struct lxc_handler *handler);
+extern bool lxc_delete_network(struct lxc_handler *handler);
 extern int lxc_assign_network(const char *lxcpath, char *lxcname,
 			      struct lxc_list *networks, pid_t pid);
 extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 7d4517e..30640d2 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1318,6 +1318,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	struct lxc_handler *handler;
 	int err = -1;
 	int status;
+	bool removed_all_netdevs = true;
 
 	handler = lxc_init(name, conf, lxcpath);
 	if (!handler) {
@@ -1412,7 +1413,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	lxc_restore_phys_nics_to_netns(handler->netnsfd, handler->conf);
 
 	DEBUG("Tearing down virtual network devices used by container");
-	lxc_delete_network(handler);
+	removed_all_netdevs = lxc_delete_network(handler);
 
 	if (handler->pinfd >= 0) {
 		close(handler->pinfd);
@@ -1422,7 +1423,12 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	lxc_monitor_send_exit_code(name, status, handler->lxcpath);
 	err =  lxc_error_set_and_log(handler->pid, status);
 out_fini:
-	lxc_delete_network(handler);
+	if (!removed_all_netdevs) {
+		DEBUG("Failed tearing down all network devices used by container. Trying again!");
+		removed_all_netdevs = lxc_delete_network(handler);
+		if (!removed_all_netdevs)
+			DEBUG("Failed tearing down network devices used by container. Not trying again!");
+	}
 
 out_detach_blockdev:
 	detach_block_device(handler->conf);

From 1ba79bfeb2345d2de9c2ef4f3201791dae862c48 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 16:58:48 +0200
Subject: [PATCH 235/334] start, utils: improve preserve_ns()

- Allocating an error message that the caller must free seems pointless. We can
  just print the error message in preserve_ns() itself. This also allows us to
  avoid using the GNU extension asprintf().
- Improve lxc_preserve_ns(): By passing in NULL or "" as the second argument
  the function can now also be used to check whether namespaces are supported
  by the kernel.
- Use lxc_preserve_ns() in preserve_ns().

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/start.c | 51 +++++++++++++++++----------------------------------
 src/lxc/utils.c |  8 +++++++-
 2 files changed, 24 insertions(+), 35 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 30640d2..4692748 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -128,34 +128,29 @@ static void close_ns(int ns_fd[LXC_NS_MAX]) {
 	}
 }
 
-/*
- * preserve_ns: open /proc/@pid/ns/@ns for each namespace specified
+/* preserve_ns: open /proc/@pid/ns/@ns for each namespace specified
  * in clone_flags.
- * Return true on success, false on failure.  On failure, leave an error
- * message in *errmsg, which caller must free.
+ * Return true on success, false on failure.
  */
-static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid,
-			char **errmsg)
+static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid)
 {
 	int i, ret;
-	char path[MAXPATHLEN];
 
 	for (i = 0; i < LXC_NS_MAX; i++)
 		ns_fd[i] = -1;
 
-	snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
-	if (access(path, X_OK)) {
-		if (asprintf(errmsg, "Kernel does not support setns.") == -1)
-			*errmsg = NULL;
+	ret = lxc_preserve_ns(pid, "");
+	if (ret < 0) {
+		SYSERROR("Kernel does not support attaching to namespaces.");
 		return false;
+	} else {
+		close(ret);
 	}
 
 	for (i = 0; i < LXC_NS_MAX; i++) {
 		if ((clone_flags & ns_info[i].clone_flag) == 0)
 			continue;
-		snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid,
-		         ns_info[i].proc_name);
-		ns_fd[i] = open(path, O_RDONLY | O_CLOEXEC);
+		ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
 		if (ns_fd[i] < 0)
 			goto error;
 	}
@@ -163,15 +158,10 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid,
 	return true;
 
 error:
-	if (errno == ENOENT) {
-		ret = asprintf(errmsg, "Kernel does not support setns for %s",
-			ns_info[i].proc_name);
-	} else {
-		ret = asprintf(errmsg, "Failed to open %s: %s",
-			path, strerror(errno));
-	}
-	if (ret == -1)
-		*errmsg = NULL;
+	if (errno == ENOENT)
+		SYSERROR("Kernel does not support attaching to %s namespaces.", ns_info[i].proc_name);
+	else
+		SYSERROR("Failed to open file descriptor for %s namespace: %s.", ns_info[i].proc_name, strerror(errno));
 	close_ns(ns_fd);
 	return false;
 }
@@ -1068,7 +1058,6 @@ static int lxc_spawn(struct lxc_handler *handler)
 {
 	int failed_before_rename = 0;
 	const char *name = handler->name;
-	char *errmsg = NULL;
 	bool cgroups_connected = false;
 	int saved_ns_fd[LXC_NS_MAX];
 	int preserve_mask = 0, i, flags;
@@ -1143,12 +1132,9 @@ static int lxc_spawn(struct lxc_handler *handler)
 			INFO("failed to pin the container's rootfs");
 	}
 
-	if (!preserve_ns(saved_ns_fd, preserve_mask, getpid(), &errmsg)) {
-		SYSERROR("Failed to preserve requested namespaces: %s",
-			errmsg ? errmsg : "(Out of memory)");
-		free(errmsg);
+	if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
 		goto out_delete_net;
-	}
+
 	if (attach_ns(handler->conf->inherit_ns_fd) < 0)
 		goto out_delete_net;
 
@@ -1173,11 +1159,8 @@ static int lxc_spawn(struct lxc_handler *handler)
 		INFO("Cloned a set of new namespaces.");
 	}
 
-	if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid, &errmsg)) {
-		INFO("Failed to store namespace references for stop hook: %s",
-			errmsg ? errmsg : "(Out of memory)");
-		free(errmsg);
-	}
+	if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid))
+		INFO("Failed to preserve namespace for lxc.hook.stop.");
 
 	if (attach_ns(saved_ns_fd))
 		WARN("failed to restore saved namespaces");
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index e7b498e..70f5aeb 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1975,7 +1975,13 @@ int lxc_preserve_ns(const int pid, const char *ns)
 	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 3 /* /ns */ + 20 /* /NS_NAME */ + 1 /* \0 */;
 	char path[len];
 
-	ret = snprintf(path, len, "/proc/%d/ns/%s", pid, ns);
+	/* This way we can use this function to also check whether namespaces
+	 * are supported by the kernel by passing in the NULL or the empty
+	 * string.
+	 */
+	ret = snprintf(path, len, "/proc/%d/ns%s%s", pid,
+		       !ns || strcmp(ns, "") == 0 ? "" : "/",
+		       !ns || strcmp(ns, "") == 0 ? "" : ns);
 	if (ret < 0 || (size_t)ret >= len)
 		return -1;
 

From c6677625eebdaf07851f886e77bc07d99e30ef6e Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 17:27:49 +0200
Subject: [PATCH 236/334] start, error: improve log + non-functional changes

Improve log and comments in a bunch of places to make it easier for us on bug
reports.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/error.c |   5 +-
 src/lxc/start.c | 520 +++++++++++++++++++++++++++-----------------------------
 2 files changed, 256 insertions(+), 269 deletions(-)

diff --git a/src/lxc/error.c b/src/lxc/error.c
index f433bf9..b7fb687 100644
--- a/src/lxc/error.c
+++ b/src/lxc/error.c
@@ -46,13 +46,12 @@ extern int  lxc_error_set_and_log(int pid, int status)
 	if (WIFEXITED(status)) {
 		ret = WEXITSTATUS(status);
 		if (ret)
-			INFO("child <%d> ended on error (%d)", pid, ret);
+			INFO("Child <%d> ended on error (%d).", pid, ret);
 	}
 
 	if (WIFSIGNALED(status)) {
 		int signal = WTERMSIG(status);
-
-		INFO("child <%d> ended on signal (%d)", pid, signal);
+		INFO("Child <%d> ended on signal (%d).", pid, signal);
 	}
 
 	return ret;
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 4692748..87d4cc3 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -108,16 +108,17 @@ static void print_top_failing_dir(const char *path)
 		saved = *p;
 		*p = '\0';
 		if (access(copy, X_OK)) {
-			SYSERROR("could not access %s.  Please grant it 'x' " \
-			      "access, or add an ACL for the container root.",
-			      copy);
+			SYSERROR("Could not access %s. Please grant it x "
+				 "access, or add an ACL for the container "
+				 "root.", copy);
 			return;
 		}
 		*p = saved;
 	}
 }
 
-static void close_ns(int ns_fd[LXC_NS_MAX]) {
+static void close_ns(int ns_fd[LXC_NS_MAX])
+{
 	int i;
 
 	for (i = 0; i < LXC_NS_MAX; i++) {
@@ -179,7 +180,7 @@ static int attach_ns(const int ns_fd[LXC_NS_MAX]) {
 	return 0;
 
 error:
-	SYSERROR("failed to set namespace '%s'", ns_info[i].proc_name);
+	SYSERROR("Failed to attach %s namespace.", ns_info[i].proc_name);
 	return -1;
 }
 
@@ -188,14 +189,13 @@ static int match_fd(int fd)
 	return (fd == 0 || fd == 1 || fd == 2);
 }
 
-/*
- * Check for any fds we need to close
- * * if fd_to_ignore != -1, then if we find that fd open we will ignore it.
- * * By default we warn about open fds we find.
- * * If closeall is true, we will close open fds.
- * * If lxc-start was passed "-C", then conf->close_all_fds will be true,
- *     in which case we also close all open fds.
- * * A daemonized container will always pass closeall=true.
+/* Check for any fds we need to close.
+ * - If fd_to_ignore != -1, then if we find that fd open we will ignore it.
+ * - By default we warn about open fds we find.
+ * - If closeall is true, we will close open fds.
+ * - If lxc-start was passed "-C", then conf->close_all_fds will be true, in
+ *   which case we also close all open fds.
+ * - A daemonized container will always pass closeall=true.
  */
 int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 {
@@ -209,7 +209,7 @@ int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 restart:
 	dir = opendir("/proc/self/fd");
 	if (!dir) {
-		WARN("failed to open directory: %m");
+		WARN("Failed to open directory: %m.");
 		return -1;
 	}
 
@@ -239,10 +239,10 @@ int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 		if (closeall) {
 			close(fd);
 			closedir(dir);
-			INFO("closed inherited fd %d", fd);
+			INFO("Closed inherited fd: %d.", fd);
 			goto restart;
 		}
-		WARN("inherited fd %d", fd);
+		WARN("Inherited fd: %d.", fd);
 	}
 
 	closedir(dir); /* cannot fail */
@@ -254,30 +254,30 @@ static int setup_signal_fd(sigset_t *oldmask)
 	sigset_t mask;
 	int fd;
 
-	/* Block everything except serious error signals */
+	/* Block everything except serious error signals. */
 	if (sigfillset(&mask) ||
 	    sigdelset(&mask, SIGILL) ||
 	    sigdelset(&mask, SIGSEGV) ||
 	    sigdelset(&mask, SIGBUS) ||
 	    sigdelset(&mask, SIGWINCH) ||
 	    sigprocmask(SIG_BLOCK, &mask, oldmask)) {
-		SYSERROR("failed to set signal mask");
+		SYSERROR("Failed to set signal mask.");
 		return -1;
 	}
 
 	fd = signalfd(-1, &mask, 0);
 	if (fd < 0) {
-		SYSERROR("failed to create the signal fd");
+		SYSERROR("Failed to create signal file descriptor.");
 		return -1;
 	}
 
 	if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
-		SYSERROR("failed to set sigfd to close-on-exec");
+		SYSERROR("Failed to set FD_CLOEXEC on the signal file descriptor: %d.", fd);
 		close(fd);
 		return -1;
 	}
 
-	DEBUG("sigchild handler set");
+	DEBUG("Set SIGCHLD handler with file descriptor: %d.", fd);
 
 	return fd;
 }
@@ -293,43 +293,44 @@ static int signal_handler(int fd, uint32_t events, void *data,
 
 	ret = read(fd, &siginfo, sizeof(siginfo));
 	if (ret < 0) {
-		ERROR("failed to read signal info");
+		ERROR("Failed to read signal info from signal file descriptor: %d.", fd);
 		return -1;
 	}
 
 	if (ret != sizeof(siginfo)) {
-		ERROR("unexpected siginfo size");
+		ERROR("Unexpected size for siginfo struct.");
 		return -1;
 	}
 
-	// check whether init is running
+	/* Check whether init is running. */
 	info.si_pid = 0;
 	ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG);
-	if (ret == 0 && info.si_pid == *pid) {
+	if (ret == 0 && info.si_pid == *pid)
 		init_died = true;
-	}
 
 	if (siginfo.ssi_signo != SIGCHLD) {
 		kill(*pid, siginfo.ssi_signo);
-		INFO("forwarded signal %d to pid %d", siginfo.ssi_signo, *pid);
+		INFO("Forwarded signal %d to pid %d.", siginfo.ssi_signo, *pid);
 		return init_died ? 1 : 0;
 	}
 
-	if (siginfo.ssi_code == CLD_STOPPED ||
-	    siginfo.ssi_code == CLD_CONTINUED) {
-		INFO("container init process was stopped/continued");
+	if (siginfo.ssi_code == CLD_STOPPED) {
+		INFO("Container init process was stopped.");
+		return init_died ? 1 : 0;
+	} else if (siginfo.ssi_code == CLD_CONTINUED) {
+		INFO("Container init process was continued.");
 		return init_died ? 1 : 0;
 	}
 
-	/* more robustness, protect ourself from a SIGCHLD sent
-	 * by a process different from the container init
+	/* More robustness, protect ourself from a SIGCHLD sent
+	 * by a process different from the container init.
 	 */
 	if (siginfo.ssi_pid != *pid) {
-		WARN("invalid pid for SIGCHLD");
+		WARN("Invalid pid for SIGCHLD. Received pid %d, expected pid %d.", siginfo.ssi_pid, *pid);
 		return init_died ? 1 : 0;
 	}
 
-	DEBUG("container init process exited");
+	DEBUG("Container init process %d exited.", *pid);
 	return 1;
 }
 
@@ -347,33 +348,33 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
 	struct lxc_epoll_descr descr;
 
 	if (lxc_mainloop_open(&descr)) {
-		ERROR("failed to create mainloop");
+		ERROR("Failed to create LXC mainloop.");
 		goto out_sigfd;
 	}
 
 	if (lxc_mainloop_add_handler(&descr, sigfd, signal_handler, &pid)) {
-		ERROR("failed to add handler for the signal");
+		ERROR("Failed to add signal handler with file descriptor %d to LXC mainloop.", sigfd);
 		goto out_mainloop_open;
 	}
 
 	if (lxc_console_mainloop_add(&descr, handler->conf)) {
-		ERROR("failed to add console handler to mainloop");
+		ERROR("Failed to add console handler to LXC mainloop.");
 		goto out_mainloop_open;
 	}
 
 	if (lxc_cmd_mainloop_add(name, &descr, handler)) {
-		ERROR("failed to add command handler to mainloop");
+		ERROR("Failed to add command handler to LXC mainloop.");
 		goto out_mainloop_open;
 	}
 
 	if (handler->conf->need_utmp_watch) {
 		#if HAVE_SYS_CAPABILITY_H
 		if (lxc_utmp_mainloop_add(&descr, handler)) {
-			ERROR("failed to add utmp handler to mainloop");
+			ERROR("Failed to add utmp handler to LXC mainloop.");
 			goto out_mainloop_open;
 		}
 		#else
-			DEBUG("not starting utmp handler as cap_sys_boot cannot be dropped without capabilities support");
+			DEBUG("Not starting utmp handler as CAP_SYS_BOOT cannot be dropped without capabilities support.");
 		#endif
 	}
 
@@ -381,8 +382,10 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
 
 out_mainloop_open:
 	lxc_mainloop_close(&descr);
+
 out_sigfd:
 	close(sigfd);
+
 	return -1;
 }
 
@@ -409,7 +412,7 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char
 
 	handler->name = strdup(name);
 	if (!handler->name) {
-		ERROR("failed to allocate memory");
+		ERROR("Failed to allocate memory.");
 		goto out_free;
 	}
 
@@ -417,66 +420,66 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char
 		goto out_free_name;
 
 	if (lxc_read_seccomp_config(conf) != 0) {
-		ERROR("failed loading seccomp policy");
+		ERROR("Failed loading seccomp policy.");
 		goto out_close_maincmd_fd;
 	}
 
-	/* Begin by setting the state to STARTING */
+	/* Begin by setting the state to STARTING. */
 	if (lxc_set_state(name, handler, STARTING)) {
-		ERROR("failed to set state '%s'", lxc_state2str(STARTING));
+		ERROR("Failed to set state for container \"%s\" to \"%s\".", name, lxc_state2str(STARTING));
 		goto out_close_maincmd_fd;
 	}
 
-	/* Start of environment variable setup for hooks */
-	if (name && setenv("LXC_NAME", name, 1)) {
-		SYSERROR("failed to set environment variable for container name");
-	}
-	if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) {
-		SYSERROR("failed to set environment variable for config path");
-	}
-	if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) {
-		SYSERROR("failed to set environment variable for rootfs mount");
-	}
-	if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) {
-		SYSERROR("failed to set environment variable for rootfs mount");
-	}
-	if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1)) {
-		SYSERROR("failed to set environment variable for console path");
-	}
-	if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1)) {
-		SYSERROR("failed to set environment variable for console log");
-	}
-	if (setenv("LXC_CGNS_AWARE", "1", 1)) {
-		SYSERROR("failed to set LXC_CGNS_AWARE environment variable");
-	}
-	/* End of environment variable setup for hooks */
+	/* Start of environment variable setup for hooks. */
+	if (name && setenv("LXC_NAME", name, 1))
+		SYSERROR("Failed to set environment variable: LXC_NAME=%s.", name);
+
+	if (conf->rcfile && setenv("LXC_CONFIG_FILE", conf->rcfile, 1))
+		SYSERROR("Failed to set environment variable: LXC_CONFIG_FILE=%s.", conf->rcfile);
+
+	if (conf->rootfs.mount && setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1))
+		SYSERROR("Failed to set environment variable: LXC_ROOTFS_MOUNT=%s.", conf->rootfs.mount);
+
+	if (conf->rootfs.path && setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1))
+		SYSERROR("Failed to set environment variable: LXC_ROOTFS_PATH=%s.", conf->rootfs.path);
+
+	if (conf->console.path && setenv("LXC_CONSOLE", conf->console.path, 1))
+		SYSERROR("Failed to set environment variable: LXC_CONSOLE=%s.", conf->console.path);
+
+	if (conf->console.log_path && setenv("LXC_CONSOLE_LOGPATH", conf->console.log_path, 1))
+		SYSERROR("Failed to set environment variable: LXC_CONSOLE_LOGPATH=%s.", conf->console.log_path);
+
+	if (setenv("LXC_CGNS_AWARE", "1", 1))
+		SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1.");
+	/* End of environment variable setup for hooks. */
 
 	if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) {
-		ERROR("failed to run pre-start hooks for container '%s'.", name);
+		ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name);
 		goto out_aborting;
 	}
 
-	/* the signal fd has to be created before forking otherwise
-	 * if the child process exits before we setup the signal fd,
-	 * the event will be lost and the command will be stuck */
+	/* The signal fd has to be created before forking otherwise if the child
+	 * process exits before we setup the signal fd, the event will be lost
+	 * and the command will be stuck.
+	 */
 	handler->sigfd = setup_signal_fd(&handler->oldmask);
 	if (handler->sigfd < 0) {
-		ERROR("failed to set sigchild fd handler");
+		ERROR("Failed to setup SIGCHLD fd handler.");
 		goto out_delete_tty;
 	}
 
-	/* do this after setting up signals since it might unblock SIGWINCH */
+	/* Do this after setting up signals since it might unblock SIGWINCH. */
 	if (lxc_console_create(conf)) {
-		ERROR("failed to create console");
+		ERROR("Failed to create console for container \"%s\".", name);
 		goto out_restore_sigmask;
 	}
 
 	if (ttys_shift_ids(conf) < 0) {
-		ERROR("Failed to shift tty into container");
+		ERROR("Failed to shift tty into container.");
 		goto out_restore_sigmask;
 	}
 
-	INFO("'%s' is initialized", name);
+	INFO("Container \"%s\" is initialized.", name);
 	return handler;
 
 out_restore_sigmask:
@@ -503,8 +506,8 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	char *namespaces[LXC_NS_MAX+1];
 	size_t namespace_count = 0;
 
-	/* The STOPPING state is there for future cleanup code
-	 * which can take awhile
+	/* The STOPPING state is there for future cleanup code which can take
+	 * awhile.
 	 */
 	lxc_set_state(name, handler, STOPPING);
 
@@ -513,7 +516,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 			rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d",
 			              ns_info[i].proc_name, self, handler->nsfd[i]);
 			if (rc == -1) {
-				SYSERROR("failed to allocate memory");
+				SYSERROR("Failed to allocate memory.");
 				break;
 			}
 			++namespace_count;
@@ -521,15 +524,14 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	}
 	namespaces[namespace_count] = NULL;
 
-	if (handler->conf->reboot && setenv("LXC_TARGET", "reboot", 1)) {
-		SYSERROR("failed to set environment variable for stop target");
-	}
-	if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1)) {
-		SYSERROR("failed to set environment variable for stop target");
-	}
+	if (handler->conf->reboot && setenv("LXC_TARGET", "reboot", 1))
+		SYSERROR("Failed to set environment variable: LXC_TARGET=reboot.");
+
+	if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1))
+		SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
 
 	if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces))
-		ERROR("failed to run stop hooks for container '%s'.", name);
+		ERROR("Failed to run lxc.hook.stop for container \"%s\".", name);
 
 	while (namespace_count--)
 		free(namespaces[namespace_count]);
@@ -548,17 +550,18 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	lxc_set_state(name, handler, STOPPED);
 
 	if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) {
-		ERROR("failed to run post-stop hooks for container '%s'.", name);
+		ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name);
 		if (handler->conf->reboot) {
 			WARN("Container will be stopped instead of rebooted.");
 			handler->conf->reboot = 0;
-			setenv("LXC_TARGET", "stop", 1);
+			if (setenv("LXC_TARGET", "stop", 1))
+				WARN("Failed to set environment variable: LXC_TARGET=stop.");
 		}
 	}
 
-	/* reset mask set by setup_signal_fd */
+	/* Reset mask set by setup_signal_fd. */
 	if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL))
-		WARN("failed to restore sigprocmask");
+		WARN("Failed to restore signal mask.");
 
 	lxc_console_delete(&handler->conf->console);
 	lxc_delete_tty(&handler->conf->tty_info);
@@ -584,16 +587,17 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
 	lxc_set_state(name, handler, ABORTING);
 	if (handler->pid > 0)
 		kill(handler->pid, SIGKILL);
-	while ((ret = waitpid(-1, &status, 0)) > 0) ;
+	while ((ret = waitpid(-1, &status, 0)) > 0) {
+		;
+	}
 }
 
 #include <sys/reboot.h>
 #include <linux/reboot.h>
 
-/*
- * reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL
- * in a child pid namespace if container reboot support exists.
- * Otherwise, it will either succeed or return -EPERM.
+/* reboot(LINUX_REBOOT_CMD_CAD_ON) will return -EINVAL in a child pid namespace
+ * if container reboot support exists.  Otherwise, it will either succeed or
+ * return -EPERM.
  */
 static int container_reboot_supported(void *arg)
 {
@@ -624,7 +628,7 @@ static int must_drop_cap_sys_boot(struct lxc_conf *conf)
 	ret = fscanf(f, "%d", &v);
 	fclose(f);
 	if (ret != 1) {
-		DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del");
+		DEBUG("Failed to read /proc/sys/kernel/ctrl-alt-del.");
 		return 1;
 	}
 	cmd = v ? LINUX_REBOOT_CMD_CAD_ON : LINUX_REBOOT_CMD_CAD_OFF;
@@ -641,13 +645,13 @@ static int must_drop_cap_sys_boot(struct lxc_conf *conf)
 #endif
 	if (pid < 0) {
 		if (flags & CLONE_NEWUSER)
-			ERROR("failed to clone (%#x): %s (includes CLONE_NEWUSER)", flags, strerror(errno));
+			ERROR("Failed to clone (%#x): %s (includes CLONE_NEWUSER).", flags, strerror(errno));
 		else
-			ERROR("failed to clone (%#x): %s", flags, strerror(errno));
+			ERROR("Failed to clone (%#x): %s.", flags, strerror(errno));
 		return -1;
 	}
 	if (wait(&status) < 0) {
-		SYSERROR("unexpected wait error: %m");
+		SYSERROR("Unexpected wait error: %m.");
 		return -1;
 	}
 
@@ -657,9 +661,8 @@ static int must_drop_cap_sys_boot(struct lxc_conf *conf)
 	return 0;
 }
 
-/*
- * netpipe is used in the unprivileged case to transfer the ifindexes
- * from parent to child
+/* netpipe is used in the unprivileged case to transfer the ifindexes from
+ * parent to child
  */
 static int netpipe = -1;
 
@@ -690,7 +693,7 @@ static int read_unpriv_netifindex(struct lxc_list *network)
 		if (netdev->type != LXC_NET_VETH)
 			continue;
 		if (!(netdev->name = malloc(IFNAMSIZ))) {
-			ERROR("Out of memory");
+			ERROR("Out of memory.");
 			close(netpipe);
 			return -1;
 		}
@@ -711,24 +714,24 @@ static int do_start(void *data)
 	char path[PATH_MAX];
 
 	if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
-		SYSERROR("failed to set sigprocmask");
+		SYSERROR("Failed to set signal mask.");
 		return -1;
 	}
 
-	/* This prctl must be before the synchro, so if the parent
-	 * dies before we set the parent death signal, we will detect
-	 * its death with the synchro right after, otherwise we have
-	 * a window where the parent can exit before we set the pdeath
-	 * signal leading to a unsupervized container.
+	/* This prctl must be before the synchro, so if the parent dies before
+	 * we set the parent death signal, we will detect its death with the
+	 * synchro right after, otherwise we have a window where the parent can
+	 * exit before we set the pdeath signal leading to a unsupervized
+	 * container.
 	 */
 	if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
-		SYSERROR("failed to set pdeath signal");
+		SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL.");
 		return -1;
 	}
 
 	lxc_sync_fini_parent(handler);
 
-	/* don't leak the pinfd to the container */
+	/* Don't leak the pinfd to the container. */
 	if (handler->pinfd >= 0) {
 		close(handler->pinfd);
 	}
@@ -736,21 +739,21 @@ static int do_start(void *data)
 	if (lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP))
 		return -1;
 
-	/* Unshare CLONE_NEWNET after CLONE_NEWUSER  - see
-	  https://github.com/lxc/lxd/issues/1978 */
+	/* Unshare CLONE_NEWNET after CLONE_NEWUSER. See
+	 * https://github.com/lxc/lxd/issues/1978.
+	 */
 	if ((handler->clone_flags & (CLONE_NEWNET | CLONE_NEWUSER)) ==
-			(CLONE_NEWNET | CLONE_NEWUSER)) {
+	    (CLONE_NEWNET | CLONE_NEWUSER)) {
 		ret = unshare(CLONE_NEWNET);
 		if (ret < 0) {
-			SYSERROR("Error unsharing network namespace");
+			SYSERROR("Failed to unshare CLONE_NEWNET.");
 			goto out_warn_father;
-		} else {
-			INFO("Unshared NET namespace.");
 		}
+		INFO("Unshared CLONE_NEWNET.");
 	}
 
-	/* Tell the parent task it can begin to configure the
-	 * container and wait for it to finish
+	/* Tell the parent task it can begin to configure the container and wait
+	 * for it to finish.
 	 */
 	if (lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE))
 		return -1;
@@ -758,11 +761,10 @@ static int do_start(void *data)
 	if (read_unpriv_netifindex(&handler->conf->network) < 0)
 		goto out_warn_father;
 
-	/*
-	 * if we are in a new user namespace, become root there to have
-	 * privilege over our namespace. When using lxc-execute we default to root,
-	 * but this can be overriden using the lxc.init_uid and lxc.init_gid
-	 * configuration options.
+	/* If we are in a new user namespace, become root there to have
+	 * privilege over our namespace. When using lxc-execute we default to
+	 * root, but this can be overriden using the lxc.init_uid and
+	 * lxc.init_gid configuration options.
 	 */
 	if (!lxc_list_empty(&handler->conf->id_map)) {
 		gid_t new_gid = 0;
@@ -773,17 +775,17 @@ static int do_start(void *data)
 		if (handler->conf->is_execute && handler->conf->init_uid)
 			new_uid = handler->conf->init_uid;
 
-		NOTICE("switching to gid/uid %d/%d in new user namespace", new_gid, new_uid);
+		NOTICE("Switching to uid=%d and gid=%d in new user namespace.", new_uid, new_gid);
 		if (setgid(new_gid)) {
-			SYSERROR("setgid");
+			SYSERROR("Failed to setgid().");
 			goto out_warn_father;
 		}
 		if (setuid(new_uid)) {
-			SYSERROR("setuid");
+			SYSERROR("Failed to setuid().");
 			goto out_warn_father;
 		}
 		if (setgroups(0, NULL)) {
-			SYSERROR("setgroups");
+			SYSERROR("Failed to setgroups().");
 			goto out_warn_father;
 		}
 	}
@@ -796,18 +798,16 @@ static int do_start(void *data)
 	#if HAVE_SYS_CAPABILITY_H
 	if (handler->conf->need_utmp_watch) {
 		if (prctl(PR_CAPBSET_DROP, CAP_SYS_BOOT, 0, 0, 0)) {
-			SYSERROR("failed to remove CAP_SYS_BOOT capability");
+			SYSERROR("Failed to remove the CAP_SYS_BOOT capability.");
 			goto out_warn_father;
 		}
-		DEBUG("Dropped cap_sys_boot");
+		DEBUG("Dropped the CAP_SYS_BOOT capability.");
 	}
 	#endif
 
 	ret = snprintf(path, sizeof(path), "%s/dev/null", handler->conf->rootfs.mount);
-	if (ret < 0 || ret >= sizeof(path)) {
-		SYSERROR("sprintf'd too many chars");
+	if (ret < 0 || ret >= sizeof(path))
 		goto out_warn_father;
-	}
 
 	/* In order to checkpoint restore, we need to have everything in the
 	 * same mount namespace. However, some containers may not have a
@@ -824,16 +824,17 @@ static int do_start(void *data)
 
 		if (devnull_fd < 0)
 			goto out_warn_father;
-		WARN("using host's /dev/null for container init's std fds, migraiton won't work");
+		WARN("Using /dev/null from the host for container init's "
+		     "standard file descriptors. Migration will not work.");
 	}
 
 	/* Setup the container, ip, names, utsname, ... */
 	if (lxc_setup(handler)) {
-		ERROR("failed to setup the container");
+		ERROR("Failed to setup container \"%s\".", handler->name);
 		goto out_warn_father;
 	}
 
-	/* ask father to setup cgroups and wait for him to finish */
+	/* Ask father to setup cgroups and wait for him to finish. */
 	if (lxc_sync_barrier_parent(handler, LXC_SYNC_CGROUP))
 		goto out_error;
 
@@ -857,55 +858,55 @@ static int do_start(void *data)
 		INFO("Unshared CLONE_NEWCGROUP.");
 	}
 
-	/* Set the label to change to when we exec(2) the container's init */
+	/* Set the label to change to when we exec(2) the container's init. */
 	if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0)
 		goto out_warn_father;
 
 	/* Some init's such as busybox will set sane tty settings on stdin,
 	 * stdout, stderr which it thinks is the console. We already set them
 	 * the way we wanted on the real terminal, and we want init to do its
-	 * setup on its console ie. the pty allocated in lxc_console_create()
-	 * so make sure that that pty is stdin,stdout,stderr.
+	 * setup on its console ie. the pty allocated in lxc_console_create() so
+	 * make sure that that pty is stdin,stdout,stderr.
 	 */
 	if (lxc_console_set_stdfds(handler->conf->console.slave) < 0)
 		goto out_warn_father;
 
-	/* If we mounted a temporary proc, then unmount it now */
+	/* If we mounted a temporary proc, then unmount it now. */
 	tmp_proc_unmount(handler->conf);
 
 	if (lxc_seccomp_load(handler->conf) != 0)
 		goto out_warn_father;
 
 	if (run_lxc_hooks(handler->name, "start", handler->conf, handler->lxcpath, NULL)) {
-		ERROR("failed to run start hooks for container '%s'.", handler->name);
+		ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name);
 		goto out_warn_father;
 	}
 
-	/* The clearenv() and putenv() calls have been moved here
-	 * to allow us to use environment variables passed to the various
-	 * hooks, such as the start hook above.  Not all of the
-	 * variables like CONFIG_PATH or ROOTFS are valid in this
-	 * context but others are. */
+	/* The clearenv() and putenv() calls have been moved here to allow us to
+	 * use environment variables passed to the various hooks, such as the
+	 * start hook above. Not all of the variables like CONFIG_PATH or ROOTFS
+	 * are valid in this context but others are.
+	 */
 	if (clearenv()) {
-		SYSERROR("failed to clear environment");
-		/* don't error out though */
+		SYSERROR("Failed to clear environment.");
+		/* Don't error out though. */
 	}
 
 	lxc_list_for_each(iterator, &handler->conf->environment) {
 		if (putenv((char *)iterator->elem)) {
-			SYSERROR("failed to set environment variable '%s'", (char *)iterator->elem);
+			SYSERROR("Failed to set environment variable: %s.", (char *)iterator->elem);
 			goto out_warn_father;
 		}
 	}
 
 	if (putenv("container=lxc")) {
-		SYSERROR("failed to set environment variable 'container=lxc'");
+		SYSERROR("Failed to set environment variable: container=lxc.");
 		goto out_warn_father;
 	}
 
 	if (handler->conf->pty_names) {
 		if (putenv(handler->conf->pty_names)) {
-			SYSERROR("failed to set environment variable for container ptys");
+			SYSERROR("Failed to set environment variable for container ptys.");
 			goto out_warn_father;
 		}
 	}
@@ -929,13 +930,15 @@ static int do_start(void *data)
 
 	setsid();
 
-	/* after this call, we are in error because this
-	 * ops should not return as it execs */
+	/* After this call, we are in error because this ops should not return
+	 * as it execs.
+	 */
 	handler->ops->start(handler, handler->data);
 
 out_warn_father:
-	/* we want the parent to know something went wrong, so we return a special
-	 * error code. */
+	/* We want the parent to know something went wrong, so we return a
+	 * special error code.
+	 */
 	lxc_sync_wake_parent(handler, LXC_SYNC_ERROR);
 
 out_error:
@@ -960,17 +963,13 @@ static int save_phys_nics(struct lxc_conf *conf)
 			continue;
 		conf->saved_nics = realloc(conf->saved_nics,
 				(conf->num_savednics+1)*sizeof(struct saved_nic));
-		if (!conf->saved_nics) {
-			SYSERROR("failed to allocate memory");
+		if (!conf->saved_nics)
 			return -1;
-		}
 		conf->saved_nics[conf->num_savednics].ifindex = netdev->ifindex;
 		conf->saved_nics[conf->num_savednics].orig_name = strdup(netdev->link);
-		if (!conf->saved_nics[conf->num_savednics].orig_name) {
-			SYSERROR("failed to allocate memory");
+		if (!conf->saved_nics[conf->num_savednics].orig_name)
 			return -1;
-		}
-		INFO("stored saved_nic #%d idx %d name %s", conf->num_savednics,
+		INFO("Stored saved_nic #%d idx %d name %s.", conf->num_savednics,
 			conf->saved_nics[conf->num_savednics].ifindex,
 			conf->saved_nics[conf->num_savednics].orig_name);
 		conf->num_savednics++;
@@ -982,7 +981,7 @@ static int save_phys_nics(struct lxc_conf *conf)
 static int recv_fd(int sock, int *fd)
 {
 	if (lxc_abstract_unix_recv_fd(sock, fd, NULL, 0) < 0) {
-		SYSERROR("Error receiving tty fd from child");
+		SYSERROR("Error receiving tty file descriptor from child process.");
 		return -1;
 	}
 	if (*fd == -1)
@@ -999,18 +998,16 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
 	if (!conf->tty)
 		return 0;
 
-	tty_info->pty_info = malloc(sizeof(*tty_info->pty_info)*conf->tty);
-	if (!tty_info->pty_info) {
-		SYSERROR("failed to allocate pty_info");
+	tty_info->pty_info = malloc(sizeof(*tty_info->pty_info) * conf->tty);
+	if (!tty_info->pty_info)
 		return -1;
-	}
 
 	for (i = 0; i < conf->tty; i++) {
 		struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 		pty_info->busy = 0;
 		if (recv_fd(sock, &pty_info->slave) < 0 ||
-				recv_fd(sock, &pty_info->master) < 0) {
-			ERROR("Error receiving tty info from child");
+		    recv_fd(sock, &pty_info->master) < 0) {
+			ERROR("Error receiving tty info from child process.");
 			return -1;
 		}
 	}
@@ -1022,36 +1019,26 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
 void resolve_clone_flags(struct lxc_handler *handler)
 {
 	handler->clone_flags = CLONE_NEWPID | CLONE_NEWNS;
-	INFO("Adding CLONE_NEWPID to clone flags.");
-	INFO("Adding CLONE_NEWNS to clone flags.");
 
-	if (!lxc_list_empty(&handler->conf->id_map)) {
-		INFO("Adding CLONE_NEWUSER to clone flags.");
+	if (!lxc_list_empty(&handler->conf->id_map))
 		handler->clone_flags |= CLONE_NEWUSER;
-	}
 
 	if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) {
-		if (!lxc_requests_empty_network(handler)) {
-			INFO("Adding CLONE_NEWNET to clone flags.");
+		if (!lxc_requests_empty_network(handler))
 			handler->clone_flags |= CLONE_NEWNET;
-		}
 	} else {
 		INFO("Inheriting a NET namespace.");
 	}
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) {
-		INFO("Adding CLONE_NEWIPC to clone flags.");
+	if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1)
 		handler->clone_flags |= CLONE_NEWIPC;
-	} else {
+	else
 		INFO("Inheriting an IPC namespace.");
-	}
 
-	if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
-		INFO("Adding CLONE_NEWUTS to clone flags.");
+	if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1)
 		handler->clone_flags |= CLONE_NEWUTS;
-	} else {
+	else
 		INFO("Inheriting a UTS namespace.");
-	}
 }
 
 static int lxc_spawn(struct lxc_handler *handler)
@@ -1085,51 +1072,50 @@ static int lxc_spawn(struct lxc_handler *handler)
 			/* Find gateway addresses from the link device, which is
 			 * no longer accessible inside the container. Do this
 			 * before creating network interfaces, since goto
-			 * out_delete_net does not work before lxc_clone. */
+			 * out_delete_net does not work before lxc_clone.
+			 */
 			if (lxc_find_gateway_addresses(handler)) {
-				ERROR("failed to find gateway addresses");
+				ERROR("Failed to find gateway addresses.");
 				lxc_sync_fini(handler);
 				return -1;
 			}
 
-			/* that should be done before the clone because we will
-			 * fill the netdev index and use them in the child
+			/* That should be done before the clone because we will
+			 * fill the netdev index and use them in the child.
 			 */
 			if (lxc_create_network(handler)) {
-				ERROR("failed to create the network");
+				ERROR("Failed to create the network.");
 				lxc_sync_fini(handler);
 				return -1;
 			}
 		}
 
 		if (save_phys_nics(handler->conf)) {
-			ERROR("failed to save physical nic info");
+			ERROR("Failed to save physical nic info.");
 			goto out_abort;
 		}
 	}
 
 	if (!cgroup_init(handler)) {
-		ERROR("failed initializing cgroup support");
+		ERROR("Failed initializing cgroup support.");
 		goto out_delete_net;
 	}
 
 	cgroups_connected = true;
 
 	if (!cgroup_create(handler)) {
-		ERROR("failed creating cgroups");
+		ERROR("Failed creating cgroups.");
 		goto out_delete_net;
 	}
 
-	/*
-	 * if the rootfs is not a blockdev, prevent the container from
-	 * marking it readonly.
-	 *
-	 * if the container is unprivileged then skip rootfs pinning
+	/* If the rootfs is not a blockdev, prevent the container from marking
+	 * it readonly.
+	 * If the container is unprivileged then skip rootfs pinning.
 	 */
 	if (lxc_list_empty(&handler->conf->id_map)) {
 		handler->pinfd = pin_rootfs(handler->conf->rootfs.path);
 		if (handler->pinfd == -1)
-			INFO("failed to pin the container's rootfs");
+			INFO("Failed to pin the rootfs for container \"%s\".", handler->name);
 	}
 
 	if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
@@ -1140,40 +1126,46 @@ static int lxc_spawn(struct lxc_handler *handler)
 
 	if (am_unpriv() && (nveths = count_veths(&handler->conf->network))) {
 		if (pipe(netpipepair) < 0) {
-			SYSERROR("Error creating pipe");
+			SYSERROR("Failed to create pipe.");
 			goto out_delete_net;
 		}
-		/* store netpipe in the global var for do_start's use */
+		/* Store netpipe in the global var for do_start's use. */
 		netpipe = netpipepair[0];
 	}
 
-	/* Create a process in a new set of namespaces */
+	/* Create a process in a new set of namespaces. */
 	flags = handler->clone_flags;
-	if (handler->clone_flags & CLONE_NEWUSER)
+	if (handler->clone_flags & CLONE_NEWUSER) {
+		/* If CLONE_NEWUSER and CLONE_NEWNET was requested, we need to
+		 * clone a new user namespace first and only later unshare our
+		 * network namespace to ensure that network devices ownership is
+		 * set up correctly.
+		 */
 		flags &= ~CLONE_NEWNET;
+	}
 	handler->pid = lxc_clone(do_start, handler, flags);
 	if (handler->pid < 0) {
-		SYSERROR("Failed to fork into a set of new namespaces.");
+		SYSERROR("Failed to clone a new set of namespaces.");
 		goto out_delete_net;
-	} else {
-		INFO("Cloned a set of new namespaces.");
 	}
+	INFO("Cloned a set of new namespaces.");
 
 	if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid))
 		INFO("Failed to preserve namespace for lxc.hook.stop.");
 
 	if (attach_ns(saved_ns_fd))
-		WARN("failed to restore saved namespaces");
+		WARN("Failed to restore saved namespaces.");
 
 	lxc_sync_fini_child(handler);
 
-	/* map the container uids - the container became an invalid
-	 * userid the moment it was cloned with CLONE_NEWUSER - this
-	 * call doesn't change anything immediately, but allows the
-	 * container to setuid(0) (0 being mapped to something else on
-	 * the host) later to become a valid uid again */
+	/* Map the container uids. The container became an invalid userid the
+	 * moment it was cloned with CLONE_NEWUSER. This call doesn't change
+	 * anything immediately, but allows the container to setuid(0) (0 being
+	 * mapped to something else on the host.) later to become a valid uid
+	 * again.
+	 */
 	if (lxc_map_ids(&handler->conf->id_map, handler->pid)) {
-		ERROR("failed to set up id mapping");
+		ERROR("Failed to set up id mapping.");
 		goto out_delete_net;
 	}
 
@@ -1188,11 +1180,11 @@ static int lxc_spawn(struct lxc_handler *handler)
 	}
 
 	if (!cgroup_create_legacy(handler)) {
-		ERROR("failed to setup the legacy cgroups for %s", name);
+		ERROR("Failed to setup legacy cgroups for container \"%s\".", name);
 		goto out_delete_net;
 	}
 	if (!cgroup_setup_limits(handler, false)) {
-		ERROR("failed to setup the cgroup limits for '%s'", name);
+		ERROR("Failed to setup cgroup limits for container \"%s\".", name);
 		goto out_delete_net;
 	}
 
@@ -1205,11 +1197,11 @@ static int lxc_spawn(struct lxc_handler *handler)
 	if (failed_before_rename)
 		goto out_delete_net;
 
-	/* Create the network configuration */
+	/* Create the network configuration. */
 	if (handler->clone_flags & CLONE_NEWNET) {
 		if (lxc_assign_network(handler->lxcpath, handler->name,
-					&handler->conf->network, handler->pid)) {
-			ERROR("failed to create the configured network");
+				       &handler->conf->network, handler->pid)) {
+			ERROR("Failed to create the configured network.");
 			goto out_delete_net;
 		}
 	}
@@ -1224,39 +1216,38 @@ static int lxc_spawn(struct lxc_handler *handler)
 			if (netdev->type != LXC_NET_VETH)
 				continue;
 			if (write(netpipepair[1], netdev->name, IFNAMSIZ) != IFNAMSIZ) {
-				ERROR("Error writing veth name to container");
+				ERROR("Error writing veth name to container.");
 				goto out_delete_net;
 			}
 		}
 		close(netpipepair[1]);
 	}
 
-	/* Tell the child to continue its initialization.  we'll get
-	 * LXC_SYNC_CGROUP when it is ready for us to setup cgroups
+	/* Tell the child to continue its initialization. We'll get
+	 * LXC_SYNC_CGROUP when it is ready for us to setup cgroups.
 	 */
 	if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
 		goto out_delete_net;
 
 	if (!cgroup_setup_limits(handler, true)) {
-		ERROR("failed to setup the devices cgroup for '%s'", name);
+		ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
 		goto out_delete_net;
 	}
 
 	cgroup_disconnect();
 	cgroups_connected = false;
 
-	/* read tty fds allocated by child */
+	/* Read tty fds allocated by child. */
 	if (recv_ttys_from_child(handler) < 0) {
-		ERROR("failed to receive tty info from child");
+		ERROR("Failed to receive tty info from child process.");
 		goto out_delete_net;
 	}
 
-	/* Tell the child to complete its initialization and wait for
-	 * it to exec or return an error.  (the child will never
-	 * return LXC_SYNC_POST_CGROUP+1.  It will either close the
-	 * sync pipe, causing lxc_sync_barrier_child to return
-	 * success, or return a different value, causing us to error
-	 * out).
+	/* Tell the child to complete its initialization and wait for it to exec
+	 * or return an error. (The child will never return
+	 * LXC_SYNC_POST_CGROUP+1. It will either close the sync pipe, causing
+	 * lxc_sync_barrier_child to return success, or return a different
+	 * value, causing us to error out).
 	 */
 	if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CGROUP))
 		return -1;
@@ -1268,8 +1259,8 @@ static int lxc_spawn(struct lxc_handler *handler)
 		goto out_abort;
 
 	if (lxc_set_state(name, handler, RUNNING)) {
-		ERROR("failed to set state to %s",
-			      lxc_state2str(RUNNING));
+		ERROR("Failed to set state for container \"%s\" to \"%s\".", name,
+		      lxc_state2str(RUNNING));
 		goto out_abort;
 	}
 
@@ -1305,7 +1296,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 
 	handler = lxc_init(name, conf, lxcpath);
 	if (!handler) {
-		ERROR("failed to initialize the container");
+		ERROR("Failed to initialize container \"%s\".", name);
 		return -1;
 	}
 	handler->ops = ops;
@@ -1315,41 +1306,41 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 
 	if (must_drop_cap_sys_boot(handler->conf)) {
 		#if HAVE_SYS_CAPABILITY_H
-		DEBUG("Dropping cap_sys_boot");
+		DEBUG("Dropping CAP_SYS_BOOT capability.");
 		#else
-		DEBUG("Can't drop cap_sys_boot as capabilities aren't supported");
+		DEBUG("Not dropping CAP_SYS_BOOT capability as capabilities aren't supported.");
 		#endif
 	} else {
-		DEBUG("Not dropping cap_sys_boot or watching utmp");
+		DEBUG("Not dropping CAP_SYS_BOOT or watching utmp.");
 		handler->conf->need_utmp_watch = 0;
 	}
 
 	if (!attach_block_device(handler->conf)) {
-		ERROR("Failure attaching block device");
+		ERROR("Failed to attach block device.");
 		goto out_fini_nonet;
 	}
 
 	if (geteuid() == 0 && !lxc_list_empty(&conf->id_map)) {
-		/* if the backing store is a device, mount it here and now */
+		/* If the backing store is a device, mount it here and now. */
 		if (rootfs_is_blockdev(conf)) {
 			if (unshare(CLONE_NEWNS) < 0) {
-				ERROR("Error unsharing MOUNT namespace.");
+				ERROR("Failed to unshare CLONE_NEWNS.");
 				goto out_fini_nonet;
-			} else {
-				INFO("Unshared MOUNT namespace.");
 			}
+			INFO("Unshared CLONE_NEWNS.");
+
 			remount_all_slave();
 			if (do_rootfs_setup(conf, name, lxcpath) < 0) {
-				ERROR("Error setting up rootfs mount as root before spawn");
+				ERROR("Error setting up rootfs mount as root before spawn.");
 				goto out_fini_nonet;
 			}
-			INFO("Set up container rootfs as host root");
+			INFO("Set up container rootfs as host root.");
 		}
 	}
 
 	err = lxc_spawn(handler);
 	if (err) {
-		ERROR("failed to spawn '%s'", name);
+		ERROR("Failed to spawn container \"%s\".", name);
 		goto out_detach_blockdev;
 	}
 
@@ -1357,7 +1348,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 
 	err = lxc_poll(name, handler);
 	if (err) {
-		ERROR("mainloop exited with an error");
+		ERROR("LXC mainloop exited with error: %d.", err);
 		if (handler->netnsfd >= 0) {
 			close(handler->netnsfd);
 			handler->netnsfd = -1;
@@ -1368,26 +1359,24 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	while (waitpid(handler->pid, &status, 0) < 0 && errno == EINTR)
 		continue;
 
-	/*
-	 * If the child process exited but was not signaled,
-	 * it didn't call reboot.  This should mean it was an
-	 * lxc-execute which simply exited.  In any case, treat
-	 * it as a 'halt'
+	/* If the child process exited but was not signaled, it didn't call
+	 * reboot. This should mean it was an lxc-execute which simply exited.
+	 * In any case, treat it as a 'halt'.
 	 */
 	if (WIFSIGNALED(status)) {
 		switch(WTERMSIG(status)) {
 		case SIGINT: /* halt */
-			DEBUG("Container halting");
+			DEBUG("Container \"%s\" is halting.", name);
 			break;
 		case SIGHUP: /* reboot */
-			DEBUG("Container rebooting");
+			DEBUG("Container \"%s\" is rebooting.", name);
 			handler->conf->reboot = 1;
 			break;
 		case SIGSYS: /* seccomp */
-			DEBUG("Container violated its seccomp policy");
+			DEBUG("Container \"%s\" violated its seccomp policy.", name);
 			break;
 		default:
-			DEBUG("unknown exit status for init: %d", WTERMSIG(status));
+			DEBUG("Unknown exit status for container \"%s\" init %d.", name, WTERMSIG(status));
 			break;
 		}
 	}
@@ -1395,7 +1384,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	DEBUG("Pushing physical nics back to host namespace");
 	lxc_restore_phys_nics_to_netns(handler->netnsfd, handler->conf);
 
-	DEBUG("Tearing down virtual network devices used by container");
+	DEBUG("Tearing down virtual network devices used by container \"%s\".", name);
 	removed_all_netdevs = lxc_delete_network(handler);
 
 	if (handler->pinfd >= 0) {
@@ -1407,7 +1396,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 	err =  lxc_error_set_and_log(handler->pid, status);
 out_fini:
 	if (!removed_all_netdevs) {
-		DEBUG("Failed tearing down all network devices used by container. Trying again!");
+		DEBUG("Failed tearing down network devices used by container. Trying again!");
 		removed_all_netdevs = lxc_delete_network(handler);
 		if (!removed_all_netdevs)
 			DEBUG("Failed tearing down network devices used by container. Not trying again!");
@@ -1433,10 +1422,10 @@ static int start(struct lxc_handler *handler, void* data)
 {
 	struct start_args *arg = data;
 
-	NOTICE("exec'ing '%s'", arg->argv[0]);
+	NOTICE("Exec'ing \"%s\".", arg->argv[0]);
 
 	execvp(arg->argv[0], arg->argv);
-	SYSERROR("failed to exec %s", arg->argv[0]);
+	SYSERROR("Failed to exec \"%s\".", arg->argv[0]);
 	return 0;
 }
 
@@ -1444,7 +1433,7 @@ static int post_start(struct lxc_handler *handler, void* data)
 {
 	struct start_args *arg = data;
 
-	NOTICE("'%s' started with pid '%d'", arg->argv[0], handler->pid);
+	NOTICE("Started \"%s\" with pid \"%d\".", arg->argv[0], handler->pid);
 	return 0;
 }
 
@@ -1474,23 +1463,22 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
 	if (handler->conf->rootfs.path && handler->conf->rootfs.mount) {
 		bret = do_destroy_container(handler->conf);
 		if (!bret) {
-			ERROR("Error destroying rootfs for %s", name);
+			ERROR("Error destroying rootfs for container \"%s\".", name);
 			return;
 		}
 	}
-	INFO("Destroyed rootfs for %s", name);
+	INFO("Destroyed rootfs for container \"%s\".", name);
 
 	ret = snprintf(destroy, MAXPATHLEN, "%s/%s", handler->lxcpath, name);
 	if (ret < 0 || ret >= MAXPATHLEN) {
-		ERROR("Error printing path for %s", name);
-		ERROR("Error destroying directory for %s", name);
+		ERROR("Error destroying directory for container \"%s\".", name);
 		return;
 	}
 
 	c = lxc_container_new(name, handler->lxcpath);
 	if (c) {
 		if (container_disk_lock(c)) {
-			INFO("Could not update lxc_snapshots file");
+			INFO("Could not update lxc_snapshots file.");
 			lxc_container_put(c);
 		} else {
 			mod_all_rdeps(c, false);
@@ -1505,10 +1493,10 @@ static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
 		ret = lxc_rmdir_onedev(destroy, NULL);
 
 	if (ret < 0) {
-		ERROR("Error destroying directory for %s", name);
+		ERROR("Error destroying directory for container \"%s\".", name);
 		return;
 	}
-	INFO("Destroyed directory for %s", name);
+	INFO("Destroyed directory for container \"%s\".", name);
 }
 
 static int lxc_rmdir_onedev_wrapper(void *data)

From a2f2695a6d440ff217e20d11364842b0df133d36 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Mon, 31 Oct 2016 15:54:42 +0100
Subject: [PATCH 237/334] start, namespace: move ns_info to namespace.{c,h}

It's much more appropriate there and makes start.{c,h} cleaner and leaner.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/namespace.c | 30 +++++++++++++++---------------
 src/lxc/namespace.h | 18 +++++++++++++++++-
 src/lxc/start.c     | 14 +++-----------
 src/lxc/start.h     | 18 ------------------
 4 files changed, 35 insertions(+), 45 deletions(-)

diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c
index 19b6593..bb76f4c 100644
--- a/src/lxc/namespace.c
+++ b/src/lxc/namespace.c
@@ -64,29 +64,29 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
 	ret = clone(do_clone, stack  + stack_size, flags | SIGCHLD, &clone_arg);
 #endif
 	if (ret < 0)
-		ERROR("failed to clone (%#x): %s", flags, strerror(errno));
+		ERROR("Failed to clone (%#x): %s.", flags, strerror(errno));
 
 	return ret;
 }
 
-static const char * const namespaces_list[] = {
-	"MOUNT", "PID", "UTSNAME", "IPC",
-	"USER", "NETWORK"
-};
-static const int cloneflags_list[] = {
-	CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
-	CLONE_NEWUSER, CLONE_NEWNET
+const struct ns_info ns_info[LXC_NS_MAX] = {
+	[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"},
+	[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"},
+	[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"},
+	[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"},
+	[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
+	[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"},
+	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
 };
 
 int lxc_namespace_2_cloneflag(char *namespace)
 {
-	int i, len;
-	len = sizeof(namespaces_list)/sizeof(namespaces_list[0]);
-	for (i = 0; i < len; i++)
-		if (!strcmp(namespaces_list[i], namespace))
-			return cloneflags_list[i];
+	int i;
+	for (i = 0; i < LXC_NS_MAX; i++)
+		if (!strcasecmp(ns_info[i].proc_name, namespace))
+			return ns_info[i].clone_flag;
 
-	ERROR("invalid namespace name %s", namespace);
+	ERROR("Invalid namespace name: %s.", namespace);
 	return -1;
 }
 
@@ -96,7 +96,7 @@ int lxc_fill_namespace_flags(char *flaglist, int *flags)
 	int aflag;
 
 	if (!flaglist) {
-		ERROR("need at least one namespace to unshare");
+		ERROR("At least one namespace is needed.");
 		return -1;
 	}
 
diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h
index 027c765..57167f4 100644
--- a/src/lxc/namespace.h
+++ b/src/lxc/namespace.h
@@ -53,6 +53,23 @@
 #  define CLONE_NEWNET            0x40000000
 #endif
 
+enum {
+	LXC_NS_MNT,
+	LXC_NS_PID,
+	LXC_NS_UTS,
+	LXC_NS_IPC,
+	LXC_NS_USER,
+	LXC_NS_NET,
+	LXC_NS_CGROUP,
+	LXC_NS_MAX
+};
+
+extern const struct ns_info {
+	const char *proc_name;
+	int clone_flag;
+	const char *flag_name;
+} ns_info[LXC_NS_MAX];
+
 #if defined(__ia64__)
 int __clone2(int (*__fn) (void *__arg), void *__child_stack_base,
              size_t __child_stack_size, int __flags, void *__arg, ...);
@@ -62,7 +79,6 @@ int clone(int (*fn)(void *), void *child_stack,
 	/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
 #endif
 
-
 extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
 
 extern int lxc_namespace_2_cloneflag(char *namespace);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 87d4cc3..f3efb6a 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -76,16 +76,6 @@
 
 lxc_log_define(lxc_start, lxc);
 
-const struct ns_info ns_info[LXC_NS_MAX] = {
-	[LXC_NS_MNT] = {"mnt", CLONE_NEWNS},
-	[LXC_NS_PID] = {"pid", CLONE_NEWPID},
-	[LXC_NS_UTS] = {"uts", CLONE_NEWUTS},
-	[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC},
-	[LXC_NS_USER] = {"user", CLONE_NEWUSER},
-	[LXC_NS_NET] = {"net", CLONE_NEWNET},
-	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP}
-};
-
 extern void mod_all_rdeps(struct lxc_container *c, bool inc);
 static bool do_destroy_container(struct lxc_conf *conf);
 static int lxc_rmdir_onedev_wrapper(void *data);
@@ -1148,7 +1138,9 @@ static int lxc_spawn(struct lxc_handler *handler)
 		SYSERROR("Failed to clone a new set of namespaces.");
 		goto out_delete_net;
 	}
-	INFO("Cloned a set of new namespaces.");
+	for (i = 0; i < LXC_NS_MAX; i++)
+		if (flags & ns_info[i].clone_flag)
+			INFO("Cloned %s.", ns_info[i].flag_name);
 
 	if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid))
 		INFO("Failed to preserve namespace for lxc.hook.stop.");
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 65d553b..3bae878 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -42,24 +42,6 @@ struct lxc_operations {
 
 struct cgroup_desc;
 
-enum {
-	LXC_NS_MNT,
-	LXC_NS_PID,
-	LXC_NS_UTS,
-	LXC_NS_IPC,
-	LXC_NS_USER,
-	LXC_NS_NET,
-	LXC_NS_CGROUP,
-	LXC_NS_MAX
-};
-
-struct ns_info {
-	const char *proc_name;
-	int clone_flag;
-};
-
-extern const struct ns_info ns_info[LXC_NS_MAX];
-
 struct lxc_handler {
 	pid_t pid;
 	char *name;

From f23504af5bc03169504d2639f52b0e485dd1d2ee Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 19 Nov 2016 05:45:01 +0100
Subject: [PATCH 238/334] attach, utils: bugfixes

- simply check /proc/self/ns
- improve SYSERROR() report
- use #define to prevent gcc & clang to use a VLA

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/attach.c | 6 ++----
 src/lxc/utils.c  | 9 +++++----
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index e7e67f4..f896f71 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -212,7 +212,6 @@ static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
 
 static int lxc_attach_to_ns(pid_t pid, int which)
 {
-	char path[MAXPATHLEN];
 	/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
 	 * the file for user namespaces in /proc/$pid/ns will be called
 	 * 'user' once the kernel supports it
@@ -227,8 +226,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 	int i, j, saved_errno;
 
 
-	snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
-	if (access(path, X_OK)) {
+	if (access("/proc/self/ns", X_OK)) {
 		ERROR("Does this kernel version support 'attach' ?");
 		return -1;
 	}
@@ -253,7 +251,7 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 				close(fd[j]);
 
 			errno = saved_errno;
-			SYSERROR("failed to open '%s'", path);
+			SYSERROR("failed to open namespace: '%s'.", ns[i]);
 			return -1;
 		}
 	}
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 70f5aeb..9198340 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1972,17 +1972,18 @@ int lxc_append_string(char ***list, char *entry)
 int lxc_preserve_ns(const int pid, const char *ns)
 {
 	int ret;
-	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 3 /* /ns */ + 20 /* /NS_NAME */ + 1 /* \0 */;
-	char path[len];
+/* 5 /proc + 21 /int_as_str + 3 /ns + 20 /NS_NAME + 1 \0 */
+#define __NS_PATH_LEN 50
+	char path[__NS_PATH_LEN];
 
 	/* This way we can use this function to also check whether namespaces
 	 * are supported by the kernel by passing in the NULL or the empty
 	 * string.
 	 */
-	ret = snprintf(path, len, "/proc/%d/ns%s%s", pid,
+	ret = snprintf(path, __NS_PATH_LEN, "/proc/%d/ns%s%s", pid,
 		       !ns || strcmp(ns, "") == 0 ? "" : "/",
 		       !ns || strcmp(ns, "") == 0 ? "" : ns);
-	if (ret < 0 || (size_t)ret >= len)
+	if (ret < 0 || (size_t)ret >= __NS_PATH_LEN)
 		return -1;
 
 	return open(path, O_RDONLY | O_CLOEXEC);

From b3677ba87fe58922790ef01882b47869ab5a0511 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 20 Nov 2016 06:17:53 +0100
Subject: [PATCH 239/334] attach: use ns_info[LXC_NS_MAX] struct

Using custom structs in attach.c risks getting out of sync with the commonly
used ns_info[LXC_NS_MAX] struct and thus attaching to wrong namespaces. Switch
to using ns_info[LXC_NS_MAX].

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/attach.c | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index f896f71..22252f4 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -212,17 +212,7 @@ static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
 
 static int lxc_attach_to_ns(pid_t pid, int which)
 {
-	/* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
-	 * the file for user namespaces in /proc/$pid/ns will be called
-	 * 'user' once the kernel supports it
-	 */
-	static char *ns[] = { "user", "mnt", "pid", "uts", "ipc", "net", "cgroup" };
-	static int flags[] = {
-		CLONE_NEWUSER, CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWUTS, CLONE_NEWIPC,
-		CLONE_NEWNET, CLONE_NEWCGROUP
-	};
-	static const int size = sizeof(ns) / sizeof(char *);
-	int fd[size];
+	int fd[LXC_NS_MAX];
 	int i, j, saved_errno;
 
 
@@ -231,16 +221,16 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 		return -1;
 	}
 
-	for (i = 0; i < size; i++) {
+	for (i = 0; i < LXC_NS_MAX; i++) {
 		/* ignore if we are not supposed to attach to that
 		 * namespace
 		 */
-		if (which != -1 && !(which & flags[i])) {
+		if (which != -1 && !(which & ns_info[i].clone_flag)) {
 			fd[i] = -1;
 			continue;
 		}
 
-		fd[i] = lxc_preserve_ns(pid, ns[i]);
+		fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
 		if (fd[i] < 0) {
 			saved_errno = errno;
 
@@ -251,23 +241,28 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 				close(fd[j]);
 
 			errno = saved_errno;
-			SYSERROR("failed to open namespace: '%s'.", ns[i]);
+			SYSERROR("failed to open namespace: '%s'.", ns_info[i].proc_name);
 			return -1;
 		}
 	}
 
-	for (i = 0; i < size; i++) {
-		if (fd[i] >= 0 && setns(fd[i], 0) != 0) {
+	for (i = 0; i < LXC_NS_MAX; i++) {
+		if (fd[i] < 0)
+			continue;
+
+		if (setns(fd[i], 0) < 0) {
 			saved_errno = errno;
 
-			for (j = i; j < size; j++)
+			for (j = i; j < LXC_NS_MAX; j++)
 				close(fd[j]);
 
 			errno = saved_errno;
-			SYSERROR("failed to set namespace '%s'", ns[i]);
+			SYSERROR("Failed to attach to namespace \"%s\".", ns_info[i].proc_name);
 			return -1;
 		}
 
+		DEBUG("Attached to namespace \"%s\".", ns_info[i].proc_name);
+
 		close(fd[i]);
 	}
 
@@ -1192,11 +1187,9 @@ static int attach_child_main(void* data)
 		flags = fcntl(fd, F_GETFL);
 		if (flags < 0)
 			continue;
-		if (flags & FD_CLOEXEC) {
-			if (fcntl(fd, F_SETFL, flags & ~FD_CLOEXEC) < 0) {
+		if (flags & FD_CLOEXEC)
+			if (fcntl(fd, F_SETFL, flags & ~FD_CLOEXEC) < 0)
 				SYSERROR("Unable to clear CLOEXEC from fd");
-			}
-		}
 	}
 
 	/* we don't need proc anymore */

From 1d4a17332d800df99de48708a49a0b99cf629637 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sun, 20 Nov 2016 06:20:07 +0100
Subject: [PATCH 240/334] namespace: always attach to user namespace first

Move the user namespace at the first position in the array so that we always
attach to it first when iterating over the struct and using setns() to switch
namespaces. This especially affects lxc_attach(): Suppose you cloned a new user
namespace and mount namespace as an unprivileged user on the host and want to
setns() to the mount namespace. This requires you to attach to the user
namespace first otherwise the kernel will fail this check:

    if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
        !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
        !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
    	return -EPERM;

in

    linux/fs/namespace.c:mntns_install().

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/namespace.c | 18 +++++++++++++++++-
 src/lxc/namespace.h |  2 +-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c
index bb76f4c..3a5b3be 100644
--- a/src/lxc/namespace.c
+++ b/src/lxc/namespace.c
@@ -69,12 +69,28 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
 	return ret;
 }
 
+/* Leave the user namespace at the first position in the array of structs so
+ * that we always attach to it first when iterating over the struct and using
+ * setns() to switch namespaces. This especially affects lxc_attach(): Suppose
+ * you cloned a new user namespace and mount namespace as an unprivileged user
+ * on the host and want to setns() to the mount namespace. This requires you to
+ * attach to the user namespace first otherwise the kernel will fail this check:
+ *
+ *        if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
+ *            !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
+ *            !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
+ *            return -EPERM;
+ *
+ *    in
+ *
+ *        linux/fs/namespace.c:mntns_install().
+ */
 const struct ns_info ns_info[LXC_NS_MAX] = {
+	[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
 	[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"},
 	[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"},
 	[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"},
 	[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"},
-	[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
 	[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"},
 	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
 };
diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h
index 57167f4..4916950 100644
--- a/src/lxc/namespace.h
+++ b/src/lxc/namespace.h
@@ -54,11 +54,11 @@
 #endif
 
 enum {
+	LXC_NS_USER,
 	LXC_NS_MNT,
 	LXC_NS_PID,
 	LXC_NS_UTS,
 	LXC_NS_IPC,
-	LXC_NS_USER,
 	LXC_NS_NET,
 	LXC_NS_CGROUP,
 	LXC_NS_MAX

From 312953a70bc45ff7f23d8a6f8d3bf18f4bf500ca Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Mon, 21 Nov 2016 18:11:32 +0100
Subject: [PATCH 241/334] cgroup: improve isolcpus handling

- add more logging
- only write to cpuset.cpus if we really have to
- simplify cleanup on error and success

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 90 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 66 insertions(+), 24 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 795f326..285fd98 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -420,6 +420,7 @@ static ssize_t get_max_cpus(char *cpulist)
 	return cpus;
 }
 
+#define __ISOL_CPUS "/sys/devices/system/cpu/isolated"
 static bool filter_and_set_cpus(char *path, bool am_initialized)
 {
 	char *lastslash, *fpath, oldv;
@@ -429,78 +430,108 @@ static bool filter_and_set_cpus(char *path, bool am_initialized)
 	ssize_t maxposs = 0, maxisol = 0;
 	char *cpulist = NULL, *posscpus = NULL, *isolcpus = NULL;
 	uint32_t *possmask = NULL, *isolmask = NULL;
-	bool bret = false;
+	bool bret = false, flipped_bit = false;
 
 	lastslash = strrchr(path, '/');
 	if (!lastslash) { // bug...  this shouldn't be possible
-		ERROR("cgfsng:copy_parent_file: bad path %s", path);
+		ERROR("Invalid path: %s.", path);
 		return bret;
 	}
 	oldv = *lastslash;
 	*lastslash = '\0';
 	fpath = must_make_path(path, "cpuset.cpus", NULL);
 	posscpus = read_file(fpath);
-	if (!posscpus)
-		goto cleanup;
+	if (!posscpus) {
+		SYSERROR("Could not read file: %s.\n", fpath);
+		goto on_error;
+	}
 
 	/* Get maximum number of cpus found in possible cpuset. */
 	maxposs = get_max_cpus(posscpus);
 	if (maxposs < 0)
-		goto cleanup;
+		goto on_error;
 
-	isolcpus = read_file("/sys/devices/system/cpu/isolated");
-	if (!isolcpus)
-		goto cleanup;
+	if (!file_exists(__ISOL_CPUS)) {
+		/* This system doesn't expose isolated cpus. */
+		DEBUG("Path: "__ISOL_CPUS" to read isolated cpus from does not exist.\n");
+		goto on_success;
+	}
+
+	isolcpus = read_file(__ISOL_CPUS);
+	if (!isolcpus) {
+		SYSERROR("Could not read file "__ISOL_CPUS);
+		goto on_error;
+	}
 	if (!isdigit(isolcpus[0])) {
+		DEBUG("No isolated cpus detected.");
 		cpulist = posscpus;
 		/* No isolated cpus but we weren't already initialized by
 		 * someone. We should simply copy the parents cpuset.cpus
 		 * values.
 		 */
-		if (!am_initialized)
+		if (!am_initialized) {
+			DEBUG("Copying cpuset of parent cgroup.");
 			goto copy_parent;
+		}
 		/* No isolated cpus but we were already initialized by someone.
 		 * Nothing more to do for us.
 		 */
-		bret = true;
-		goto cleanup;
+		goto on_success;
 	}
 
 	/* Get maximum number of cpus found in isolated cpuset. */
 	maxisol = get_max_cpus(isolcpus);
 	if (maxisol < 0)
-		goto cleanup;
+		goto on_error;
 
 	if (maxposs < maxisol)
 		maxposs = maxisol;
 	maxposs++;
 
 	possmask = lxc_cpumask(posscpus, maxposs);
-	if (!possmask)
-		goto cleanup;
+	if (!possmask) {
+		ERROR("Could not create cpumask for all possible cpus.\n");
+		goto on_error;
+	}
 
 	isolmask = lxc_cpumask(isolcpus, maxposs);
-	if (!isolmask)
-		goto cleanup;
+	if (!isolmask) {
+		ERROR("Could not create cpumask for all isolated cpus.\n");
+		goto on_error;
+	}
 
 	for (i = 0; i <= maxposs; i++) {
 		if (is_set(i, isolmask) && is_set(i, possmask)) {
+			flipped_bit = true;
 			clear_bit(i, possmask);
 		}
 	}
 
+	if (!flipped_bit) {
+		DEBUG("No isolated cpus present in cpuset.");
+		goto on_success;
+	}
+	DEBUG("Removed isolated cpus from cpuset.");
+
 	cpulist = lxc_cpumask_to_cpulist(possmask, maxposs);
-	if (!cpulist) /* Bug */
-		goto cleanup;
+	if (!cpulist) {
+		ERROR("Could not create cpu list.\n");
+		goto on_error;
+	}
 
 copy_parent:
 	*lastslash = oldv;
 	fpath = must_make_path(path, "cpuset.cpus", NULL);
 	ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false);
-	if (!ret)
-		bret = true;
+	if (ret < 0) {
+		SYSERROR("Could not write cpu list to: %s.\n", fpath);
+		goto on_error;
+	}
+
+on_success:
+	bret = true;
 
-cleanup:
+on_error:
 	free(fpath);
 
 	free(isolcpus);
@@ -579,6 +610,7 @@ static bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 		free(cgpath);
 		return false;
 	}
+
 	clonechildrenpath = must_make_path(cgpath, "cgroup.clone_children", NULL);
 	if (!file_exists(clonechildrenpath)) { /* unified hierarchy doesn't have clone_children */
 		free(clonechildrenpath);
@@ -593,10 +625,15 @@ static bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 	}
 
 	/* Make sure any isolated cpus are removed from cpuset.cpus. */
-	if (!filter_and_set_cpus(cgpath, v == '1'))
+	if (!filter_and_set_cpus(cgpath, v == '1')) {
+		SYSERROR("Failed to remove isolated cpus.");
+		free(clonechildrenpath);
+		free(cgpath);
 		return false;
+	}
 
 	if (v == '1') {  /* already set for us by someone else */
+		DEBUG("\"cgroup.clone_children\" was already set to \"1\".");
 		free(clonechildrenpath);
 		free(cgpath);
 		return true;
@@ -604,6 +641,7 @@ static bool handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 
 	/* copy parent's settings */
 	if (!copy_parent_file(cgpath, "cpuset.mems")) {
+		SYSERROR("Failed to copy \"cpuset.mems\" settings.");
 		free(cgpath);
 		free(clonechildrenpath);
 		return false;
@@ -1256,10 +1294,14 @@ struct cgroup_ops *cgfsng_ops_init(void)
 static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
 {
 	h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
-	if (dir_exists(h->fullcgpath)) // it must not already exist
+	if (dir_exists(h->fullcgpath)) { // it must not already exist
+		ERROR("Path \"%s\" already existed.", h->fullcgpath);
 		return false;
-	if (!handle_cpuset_hierarchy(h, cgname))
+	}
+	if (!handle_cpuset_hierarchy(h, cgname)) {
+		ERROR("Failed to handle cgroupfs v1 cpuset controller.");
 		return false;
+	}
 	return mkdir_p(h->fullcgpath, 0755) == 0;
 }
 

From 9af8795ffabf3e0d28b8e8d9f07a8435e7c49381 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Mon, 21 Nov 2016 22:31:39 +0100
Subject: [PATCH 242/334] cgroups: handle non-existent isolcpus file

If the file "/sys/devices/system/cpu/isolated" doesn't exist, we can't just
simply bail. We still need to check whether we need to copy the parents cpu
settings.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/cgroups/cgfsng.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 285fd98..d3215d7 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -454,6 +454,18 @@ static bool filter_and_set_cpus(char *path, bool am_initialized)
 	if (!file_exists(__ISOL_CPUS)) {
 		/* This system doesn't expose isolated cpus. */
 		DEBUG("Path: "__ISOL_CPUS" to read isolated cpus from does not exist.\n");
+		cpulist = posscpus;
+		/* No isolated cpus but we weren't already initialized by
+		 * someone. We should simply copy the parents cpuset.cpus
+		 * values.
+		 */
+		if (!am_initialized) {
+			DEBUG("Copying cpuset of parent cgroup.");
+			goto copy_parent;
+		}
+		/* No isolated cpus but we were already initialized by someone.
+		 * Nothing more to do for us.
+		 */
 		goto on_success;
 	}
 

From d7cfb1de30bde9dff7700b979cd86dd88259d69b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 17:32:47 +0200
Subject: [PATCH 243/334] utils: add lxc_safe_uint()

This function safely parses an unsigned integer. On success it returns 0 and
stores the unsigned integer in @converted. On error it returns a negative
errno.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 20 ++++++++++++++++++++
 src/lxc/utils.h |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 9198340..9bf3157 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1988,3 +1988,23 @@ int lxc_preserve_ns(const int pid, const char *ns)
 
 	return open(path, O_RDONLY | O_CLOEXEC);
 }
+
+int lxc_safe_uint(const char *numstr, unsigned int *converted)
+{
+	char *err = NULL;
+	unsigned long int uli;
+
+	errno = 0;
+	uli = strtoul(numstr, &err, 0);
+	if (errno > 0)
+		return -errno;
+
+	if (!err || err == numstr || *err != '\0')
+		return -EINVAL;
+
+	if (uli > UINT_MAX)
+		return -ERANGE;
+
+	*converted = (unsigned)uli;
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 9b92daf..0706125 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -316,4 +316,8 @@ int lxc_preserve_ns(const int pid, const char *ns);
 
 /* Check whether a signal is blocked by a process. */
 bool task_blocking_signal(pid_t pid, int signal);
+
+/* Helper functions to parse numbers. */
+int lxc_safe_uint(const char *numstr, unsigned int *converted);
+
 #endif /* __LXC_UTILS_H */

From 3d5bac9261224a31dc8409759c78d8fe483289f2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 17:41:34 +0200
Subject: [PATCH 244/334] tests: add unit tests for lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxc-test-utils.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 081ed4b..9f25419 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <sched.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -220,6 +221,34 @@ void test_detect_ramfs_rootfs(void)
 	if (fret == EXIT_SUCCESS)
 		return;
 	exit(fret);
+
+void test_lxc_safe_uint(void)
+{
+	int ret;
+	unsigned int n;
+	size_t len = /* 2^64 = 21 - 1 */ 21;
+	char uint_max[len];
+
+	ret = snprintf(uint_max, len, "%lu", (unsigned long)UINT_MAX + 1);
+	if (ret < 0 || (size_t)ret >= len) {
+		lxc_error("%s\n", "Failed to create string via snprintf().");
+		exit(EXIT_FAILURE);
+	}
+
+	lxc_test_assert_abort((0 == lxc_safe_uint("1234345", &n)) && n == 1234345);
+	lxc_test_assert_abort((0 == lxc_safe_uint("   345", &n)) && n == 345);
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("   g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("   3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("   345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("   g345", &n)));
+	lxc_test_assert_abort((-ERANGE == lxc_safe_uint(uint_max, &n)));
 }
 
 void test_lxc_string_replace(void)
@@ -280,6 +309,7 @@ int main(int argc, char *argv[])
 	test_lxc_string_in_array();
 	test_lxc_deslashify();
 	test_detect_ramfs_rootfs();
+	test_lxc_safe_uint();
 
 	exit(EXIT_SUCCESS);
 }

From 6460fc550bf1eaa0e1e88aaed956c0ca4ea4b5af Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 7 Sep 2016 17:47:50 +0200
Subject: [PATCH 245/334] utils: add lxc_safe_int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 20 ++++++++++++++++++++
 src/lxc/utils.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 9bf3157..3b05842 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -2008,3 +2008,23 @@ int lxc_safe_uint(const char *numstr, unsigned int *converted)
 	*converted = (unsigned)uli;
 	return 0;
 }
+
+int lxc_safe_int(const char *numstr, int *converted)
+{
+	char *err = NULL;
+	signed long int sli;
+
+	errno = 0;
+	sli = strtol(numstr, &err, 0);
+	if (errno > 0)
+		return -errno;
+
+	if (!err || err == numstr || *err != '\0')
+		return -EINVAL;
+
+	if (sli > INT_MAX)
+		return -ERANGE;
+
+	*converted = (int)sli;
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 0706125..8fba515 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -319,5 +319,6 @@ bool task_blocking_signal(pid_t pid, int signal);
 
 /* Helper functions to parse numbers. */
 int lxc_safe_uint(const char *numstr, unsigned int *converted);
+int lxc_safe_int(const char *numstr, int *converted);
 
 #endif /* __LXC_UTILS_H */

From f41ee3e000549bb05df40e2f6340057e64a89936 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Wed, 7 Sep 2016 17:51:33 +0200
Subject: [PATCH 246/334] tests: add unit tests for lxc_safe_int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxc-test-utils.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 9f25419..46f8cf3 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -221,6 +221,7 @@ void test_detect_ramfs_rootfs(void)
 	if (fret == EXIT_SUCCESS)
 		return;
 	exit(fret);
+}
 
 void test_lxc_safe_uint(void)
 {
@@ -251,6 +252,37 @@ void test_lxc_safe_uint(void)
 	lxc_test_assert_abort((-ERANGE == lxc_safe_uint(uint_max, &n)));
 }
 
+void test_lxc_safe_int(void)
+{
+	int ret;
+	signed int n;
+	size_t len = /* 2^64 = 21 - 1 */ 21;
+	char int_max[len];
+
+	ret = snprintf(int_max, len, "%ld", (signed long)INT_MAX + 1);
+	if (ret < 0 || (size_t)ret >= len) {
+		lxc_error("%s\n", "Failed to create string via snprintf().");
+		exit(EXIT_FAILURE);
+	}
+
+	lxc_test_assert_abort((0 == lxc_safe_int("1234345", &n)) && n == 1234345);
+	lxc_test_assert_abort((0 == lxc_safe_int("   345", &n)) && n == 345);
+	lxc_test_assert_abort((0 == lxc_safe_int("-1234345", &n)) && n == -1234345);
+	lxc_test_assert_abort((0 == lxc_safe_int("   -345", &n)) && n == -345);
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("   g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("   3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("   345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_int("   g345", &n)));
+	lxc_test_assert_abort((-ERANGE == lxc_safe_int(int_max, &n)));
+}
+
 void test_lxc_string_replace(void)
 {
 	char *s;
@@ -310,6 +342,7 @@ int main(int argc, char *argv[])
 	test_lxc_deslashify();
 	test_detect_ramfs_rootfs();
 	test_lxc_safe_uint();
+	test_lxc_safe_int();
 
 	exit(EXIT_SUCCESS);
 }

From 104b6a3aef3bba0e84e3c6dfa674e74db82bce54 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 19:41:42 +0200
Subject: [PATCH 247/334] conf/ile: get ip prefix via lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    |  4 ++--
 src/lxc/confile.c | 11 ++++++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index fff89bc..580e9a0 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -62,7 +62,7 @@ enum {
 struct lxc_inetdev {
 	struct in_addr addr;
 	struct in_addr bcast;
-	int prefix;
+	unsigned int prefix;
 };
 
 struct lxc_route {
@@ -80,7 +80,7 @@ struct lxc_inet6dev {
 	struct in6_addr addr;
 	struct in6_addr mcast;
 	struct in6_addr acast;
-	int prefix;
+	unsigned int prefix;
 };
 
 struct lxc_route6 {
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 9c250f3..3807a6a 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -848,8 +848,12 @@ static int config_network_ipv4(const char *key, const char *value,
 	}
 
 	/* no prefix specified, determine it from the network class */
-	inetdev->prefix = prefix ? atoi(prefix) :
-		config_ip_prefix(&inetdev->addr);
+	if (prefix) {
+		if (lxc_safe_uint(prefix, &inetdev->prefix) < 0)
+			return -1;
+	} else {
+		inetdev->prefix = config_ip_prefix(&inetdev->addr);
+	}
 
 	/* if no broadcast address, let compute one from the
 	 * prefix and address
@@ -947,7 +951,8 @@ static int config_network_ipv6(const char *key, const char *value,
 	if (slash) {
 		*slash = '\0';
 		netmask = slash + 1;
-		inet6dev->prefix = atoi(netmask);
+		if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0)
+			return -1;
 	}
 
 	if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) {

From 64b7bd703f0b986e915c392c35382e52eb158247 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 19:53:19 +0200
Subject: [PATCH 248/334] confile: use lxc_safe_u/int in config_init_{u,g}id

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/confile.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 3807a6a..9f63dad 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1060,14 +1060,24 @@ static int config_init_cmd(const char *key, const char *value,
 static int config_init_uid(const char *key, const char *value,
 				 struct lxc_conf *lxc_conf)
 {
-	lxc_conf->init_uid = atoi(value);
+	unsigned int init_uid;
+
+	if (lxc_safe_uint(value, &init_uid) < 0)
+		return -1;
+	lxc_conf->init_uid = init_uid;
+
 	return 0;
 }
 
 static int config_init_gid(const char *key, const char *value,
 				 struct lxc_conf *lxc_conf)
 {
-	lxc_conf->init_gid = atoi(value);
+	unsigned int init_gid;
+
+	if (lxc_safe_uint(value, &init_gid) < 0)
+		return -1;
+	lxc_conf->init_gid = init_gid;
+
 	return 0;
 }
 

From 773d583126720c542436bf8d6f81caab92d0c49f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 19:58:10 +0200
Subject: [PATCH 249/334] conf/ile: use lxc_safe_uint() in config_pts()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 580e9a0..b806dc2 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -294,7 +294,7 @@ struct lxc_conf {
 	int is_execute;
 	char *fstab;
 	int tty;
-	int pts;
+	unsigned int pts;
 	int reboot;
 	int need_utmp_watch;
 	signed long personality;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 9f63dad..91fb1df 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1137,9 +1137,8 @@ static int config_personality(const char *key, const char *value,
 static int config_pts(const char *key, const char *value,
 		      struct lxc_conf *lxc_conf)
 {
-	int maxpts = atoi(value);
-
-	lxc_conf->pts = maxpts;
+	if (lxc_safe_uint(value, &lxc_conf->pts) < 0)
+		return -1;
 
 	return 0;
 }

From e68d7e3cb4f5a8885f59f39472eef257c16796f8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:01:21 +0200
Subject: [PATCH 250/334] conf/ile: use lxc_safe_u/int() in config_start()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    |  4 ++--
 src/lxc/confile.c | 11 ++++++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index b806dc2..b1d9923 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -343,8 +343,8 @@ struct lxc_conf {
 
 	int inherit_ns_fd[LXC_NS_MAX];
 
-	int start_auto;
-	int start_delay;
+	unsigned int start_auto;
+	unsigned int start_delay;
 	int start_order;
 	struct lxc_list groups;
 	int nbd_idx;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 91fb1df..6e01587 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1147,15 +1147,20 @@ static int config_start(const char *key, const char *value,
 		      struct lxc_conf *lxc_conf)
 {
 	if(strcmp(key, "lxc.start.auto") == 0) {
-		lxc_conf->start_auto = atoi(value);
+		if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0)
+			return -1;
+		if (lxc_conf->start_auto > 1)
+			return -1;
 		return 0;
 	}
 	else if (strcmp(key, "lxc.start.delay") == 0) {
-		lxc_conf->start_delay = atoi(value);
+		if (lxc_safe_uint(value, &lxc_conf->start_delay) < 0)
+			return -1;
 		return 0;
 	}
 	else if (strcmp(key, "lxc.start.order") == 0) {
-		lxc_conf->start_order = atoi(value);
+		if (lxc_safe_int(value, &lxc_conf->start_order) < 0)
+			return -1;
 		return 0;
 	}
 	SYSERROR("Unknown key: %s", key);

From db934c4a558effc33941d9ea6553bcb8c5e22c61 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:05:07 +0200
Subject: [PATCH 251/334] conf/ile: use lxc_safe_uint() in config_monitor()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index b1d9923..fb2bfc0 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -350,7 +350,7 @@ struct lxc_conf {
 	int nbd_idx;
 
 	/* unshare the mount namespace in the monitor */
-	int monitor_unshare;
+	unsigned int monitor_unshare;
 
 	/* set to true when rootfs has been setup */
 	bool rootfs_setup;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 6e01587..ff28194 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1171,7 +1171,8 @@ static int config_monitor(const char *key, const char *value,
 			  struct lxc_conf *lxc_conf)
 {
 	if(strcmp(key, "lxc.monitor.unshare") == 0) {
-		lxc_conf->monitor_unshare = atoi(value);
+		if (lxc_safe_uint(value, &lxc_conf->monitor_unshare) < 0)
+			return -1;
 		return 0;
 	}
 	SYSERROR("Unknown key: %s", key);

From 99e746b984876205a67c15e405ee1545a04358a7 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:06:40 +0200
Subject: [PATCH 252/334] conf/ile: use lxc_safe_uint() in config_tty()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index fb2bfc0..07d4090 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -293,7 +293,7 @@ struct saved_nic {
 struct lxc_conf {
 	int is_execute;
 	char *fstab;
-	int tty;
+	unsigned int tty;
 	unsigned int pts;
 	int reboot;
 	int need_utmp_watch;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index ff28194..771defa 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1255,9 +1255,8 @@ static int config_environment(const char *key, const char *value,
 static int config_tty(const char *key, const char *value,
 		      struct lxc_conf *lxc_conf)
 {
-	int nbtty = atoi(value);
-
-	lxc_conf->tty = nbtty;
+	if (lxc_safe_uint(value, &lxc_conf->tty) < 0)
+		return -1;
 
 	return 0;
 }

From 1b2f6ef94a5d169929cc3c96b566cab0e14c4521 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:08:12 +0200
Subject: [PATCH 253/334] conf/ile: use lxc_safe_uint() in config_kmsg()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 07d4090..70eec92 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -329,7 +329,7 @@ struct lxc_conf {
 	int haltsignal; // signal used to halt container
 	int rebootsignal; // signal used to reboot container
 	int stopsignal; // signal used to hard stop container
-	int kmsg;  // if 1, create /dev/kmsg symlink
+	unsigned int kmsg;  // if 1, create /dev/kmsg symlink
 	char *rcfile;	// Copy of the top level rcfile we read
 
 	// Logfile and logleve can be set in a container config file.
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 771defa..254c7d9 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1270,9 +1270,11 @@ static int config_ttydir(const char *key, const char *value,
 static int config_kmsg(const char *key, const char *value,
 			  struct lxc_conf *lxc_conf)
 {
-	int v = atoi(value);
+	if (lxc_safe_uint(value, &lxc_conf->kmsg) < 0)
+		return -1;
 
-	lxc_conf->kmsg = v;
+	if (lxc_conf->kmsg > 1)
+		return -1;
 
 	return 0;
 }

From e245c633daaf8199f0a088442588276afcfaeea2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:10:25 +0200
Subject: [PATCH 254/334] conf/ile: avoid atoi in config_lsm_aa_incomplete()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    |  2 +-
 src/lxc/confile.c | 16 +++++++++++-----
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 70eec92..d6556b1 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -317,7 +317,7 @@ struct lxc_conf {
 	struct lxc_list hooks[NUM_LXC_HOOKS];
 
 	char *lsm_aa_profile;
-	int lsm_aa_allow_incomplete;
+	unsigned int lsm_aa_allow_incomplete;
 	char *lsm_se_context;
 	int tmp_umount_proc;
 	char *seccomp;  // filename with the seccomp rules
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 254c7d9..8d426ce 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1288,9 +1288,13 @@ static int config_lsm_aa_profile(const char *key, const char *value,
 static int config_lsm_aa_incomplete(const char *key, const char *value,
 				 struct lxc_conf *lxc_conf)
 {
-	int v = atoi(value);
+	if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0)
+		return -1;
 
-	lxc_conf->lsm_aa_allow_incomplete = v == 1 ? 1 : 0;
+	if (lxc_conf->lsm_aa_allow_incomplete > 1) {
+		ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only be set to 0 or 1");
+		return -1;
+	}
 
 	return 0;
 }
@@ -1322,10 +1326,12 @@ static int config_loglevel(const char *key, const char *value,
 	if (!value || strlen(value) == 0)
 		return 0;
 
-	if (value[0] >= '0' && value[0] <= '9')
-		newlevel = atoi(value);
-	else
+	if (value[0] >= '0' && value[0] <= '9') {
+		if (lxc_safe_int(value, &newlevel) < 0)
+			return -1;
+	} else {
 		newlevel = lxc_log_priority_to_int(value);
+	}
 	// store these values in the lxc_conf, and then try to set for
 	// actual current logging.
 	lxc_conf->loglevel = newlevel;

From 856a5733dcd6fdf10f935773f7a6ca78a492f802 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:22:35 +0200
Subject: [PATCH 255/334] conf/ile: use lxc_safe_uint() in config_autodev()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index d6556b1..523d580 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -325,7 +325,7 @@ struct lxc_conf {
 	scmp_filter_ctx seccomp_ctx;
 #endif
 	int maincmd_fd;
-	int autodev;  // if 1, mount and fill a /dev at start
+	unsigned int autodev;  // if 1, mount and fill a /dev at start
 	int haltsignal; // signal used to halt container
 	int rebootsignal; // signal used to reboot container
 	int stopsignal; // signal used to hard stop container
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 8d426ce..2908da5 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1341,9 +1341,13 @@ static int config_loglevel(const char *key, const char *value,
 static int config_autodev(const char *key, const char *value,
 			  struct lxc_conf *lxc_conf)
 {
-	int v = atoi(value);
+	if (lxc_safe_uint(value, &lxc_conf->autodev) < 0)
+		return -1;
 
-	lxc_conf->autodev = v;
+	if (lxc_conf->autodev > 1) {
+		ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1");
+		return -1;
+	}
 
 	return 0;
 }

From 16ba55ae07c3d2e1b9a41825f2191373af9eb23b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 28 Oct 2016 20:24:17 +0200
Subject: [PATCH 256/334] conf/ile: avoid atoi() in config_ephemeral()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.h    | 2 +-
 src/lxc/confile.c | 7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 523d580..7aeba17 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -377,7 +377,7 @@ struct lxc_conf {
 	gid_t init_gid;
 
 	/* indicator if the container will be destroyed on shutdown */
-	int ephemeral;
+	unsigned int ephemeral;
 };
 
 #ifdef HAVE_TLS
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 2908da5..2abde72 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -2955,13 +2955,12 @@ bool network_new_hwaddrs(struct lxc_conf *conf)
 static int config_ephemeral(const char *key, const char *value,
 			    struct lxc_conf *lxc_conf)
 {
-	int v = atoi(value);
+	if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0)
+		return -1;
 
-	if (v != 0 && v != 1) {
+	if (lxc_conf->ephemeral > 1) {
 		ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1");
 		return -1;
-	} else {
-		lxc_conf->ephemeral = v;
 	}
 
 	return 0;

From 14da4d1ffd20579078ee43940d1e077c033799f8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:00:06 +0200
Subject: [PATCH 257/334] utils: use lxc_safe_int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 3b05842..e1191a3 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1766,7 +1766,7 @@ int mount_proc_if_needed(const char *rootfs)
 {
 	char path[MAXPATHLEN];
 	char link[20];
-	int linklen, ret;
+	int link_to_pid, linklen, ret;
 	int mypid;
 
 	ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs);
@@ -1785,7 +1785,9 @@ int mount_proc_if_needed(const char *rootfs)
 	}
 	if (linklen < 0) /* /proc not mounted */
 		goto domount;
-	if (atoi(link) != mypid) {
+	if (lxc_safe_int(link, &link_to_pid) < 0)
+		return -1;
+	if (link_to_pid != mypid) {
 		/* wrong /procs mounted */
 		umount2(path, MNT_DETACH); /* ignore failure */
 		goto domount;

From 74dd0998de93b4a5bd5a28f0f3bd4fb416aec18f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:03:49 +0200
Subject: [PATCH 258/334] lxc_monitord: use lxc_safe_int() && use exit()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/lxc_monitord.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
index c317cbe..61c8411 100644
--- a/src/lxc/lxc_monitord.c
+++ b/src/lxc/lxc_monitord.c
@@ -362,14 +362,15 @@ int main(int argc, char *argv[])
 	ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log",
 		       (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH ) );
 	if (ret < 0 || ret >= sizeof(logpath))
-		return EXIT_FAILURE;
+		exit(EXIT_FAILURE);
 
 	ret = lxc_log_init(NULL, logpath, "NOTICE", "lxc-monitord", 0, lxcpath);
 	if (ret)
 		INFO("Failed to open log file %s, log will be lost", lxcpath);
 	lxc_log_options_no_override();
 
-	pipefd = atoi(argv[2]);
+	if (lxc_safe_int(argv[2], &pipefd) < 0)
+		exit(EXIT_FAILURE);
 
 	if (sigfillset(&mask) ||
 	    sigdelset(&mask, SIGILL)  ||
@@ -378,7 +379,7 @@ int main(int argc, char *argv[])
 	    sigdelset(&mask, SIGTERM) ||
 	    sigprocmask(SIG_BLOCK, &mask, NULL)) {
 		SYSERROR("failed to set signal mask");
-		return 1;
+		exit(EXIT_FAILURE);
 	}
 
 	signal(SIGILL,  lxc_monitord_sig_handler);
@@ -428,7 +429,5 @@ int main(int argc, char *argv[])
 	ret = EXIT_SUCCESS;
 	NOTICE("monitor exiting");
 out:
-	if (ret == 0)
-		return 0;
-	return 1;
+	exit(ret);
 }

From 6b9550e2d8aa3696f5de7c29fc4dc6a44209e4bf Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:08:00 +0200
Subject: [PATCH 259/334] start: use lxc_safe_int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/start.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index f3efb6a..0ca5ba0 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -215,7 +215,10 @@ int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore)
 		if (!strcmp(direntp->d_name, ".."))
 			continue;
 
-		fd = atoi(direntp->d_name);
+		if (lxc_safe_int(direntp->d_name, &fd) < 0) {
+			INFO("Could not parse file descriptor for: %s", direntp->d_name);
+			continue;
+		}
 
 		if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore)
 			continue;

From f36346a8b9b8198ad93a4e50ddae5177495c413a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:20:14 +0200
Subject: [PATCH 260/334] conf: use lxc_safe_{u}int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/conf.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 63aa27e..c54ee41 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2504,7 +2504,8 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 {
 	char veth1buf[IFNAMSIZ], *veth1;
 	char veth2buf[IFNAMSIZ], *veth2;
-	int bridge_index, err, mtu = 0;
+	int bridge_index, err;
+	unsigned int mtu = 0;
 
 	if (netdev->priv.veth_attr.pair) {
 		veth1 = netdev->priv.veth_attr.pair;
@@ -2556,8 +2557,10 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 	}
 
 	if (netdev->mtu) {
-		mtu = atoi(netdev->mtu);
-		INFO("Retrieved mtu %d", mtu);
+		if (lxc_safe_uint(netdev->mtu, &mtu) < 0)
+			WARN("Failed to parse mtu from.");
+		else
+			INFO("Retrieved mtu %d", mtu);
 	} else if (netdev->link) {
 		bridge_index = if_nametoindex(netdev->link);
 		if (bridge_index) {
@@ -2706,6 +2709,7 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
 	char peer[IFNAMSIZ];
 	int err;
 	static uint16_t vlan_cntr = 0;
+	unsigned int mtu = 0;
 
 	if (!netdev->link) {
 		ERROR("no link specified for vlan netdev");
@@ -2735,7 +2739,12 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
 	DEBUG("instantiated vlan '%s', ifindex is '%d'", " vlan1000",
 	      netdev->ifindex);
 	if (netdev->mtu) {
-		err = lxc_netdev_set_mtu(peer, atoi(netdev->mtu));
+		if (lxc_safe_uint(netdev->mtu, &mtu) < 0) {
+			ERROR("Failed to retrieve mtu from: '%d'/'%s'.",
+			      netdev->ifindex, netdev->name);
+			return -1;
+		}
+		err = lxc_netdev_set_mtu(peer, mtu);
 		if (err) {
 			ERROR("failed to set mtu '%s' for %s : %s",
 			      netdev->mtu, peer, strerror(-err));
@@ -4449,8 +4458,10 @@ void suggest_default_idmap(void)
 		p2++;
 		if (!*p2)
 			continue;
-		uid = atoi(p);
-		urange = atoi(p2);
+		if (lxc_safe_uint(p, &uid) < 0)
+			WARN("Could not parse UID.");
+		if (lxc_safe_uint(p2, &urange) < 0)
+			WARN("Could not parse UID range.");
 	}
 	fclose(f);
 
@@ -4478,8 +4489,10 @@ void suggest_default_idmap(void)
 		p2++;
 		if (!*p2)
 			continue;
-		gid = atoi(p);
-		grange = atoi(p2);
+		if (lxc_safe_uint(p, &gid) < 0)
+			WARN("Could not parse GID.");
+		if (lxc_safe_uint(p2, &grange) < 0)
+			WARN("Could not parse GID range.");
 	}
 	fclose(f);
 

From dc1e435f2e2d31b895b413b592b3f42f6b0ef120 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:22:17 +0200
Subject: [PATCH 261/334] tools/lxc_execute: use lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_execute.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c
index 13fa799..fae2dca 100644
--- a/src/lxc/tools/lxc_execute.c
+++ b/src/lxc/tools/lxc_execute.c
@@ -58,10 +58,19 @@ static int my_checker(const struct lxc_arguments* args)
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
 	switch (c) {
-	case 'f': args->rcfile = arg; break;
-	case 's': return lxc_config_define_add(&defines, arg); break;
-	case 'u': args->uid = atoi(arg); break;
-	case 'g': args->gid = atoi(arg);
+	case 'f':
+		args->rcfile = arg;
+		break;
+	case 's':
+		return lxc_config_define_add(&defines, arg);
+		break;
+	case 'u':
+		if (lxc_safe_uint(arg, &args->uid) < 0)
+			return -1;
+		break;
+	case 'g':
+		if (lxc_safe_uint(arg, &args->gid) < 0)
+			return -1;
 	}
 	return 0;
 }

From c453697f94df967a19dfccd85bfe8d7650b0b987 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:23:39 +0200
Subject: [PATCH 262/334] tools/lxc_stop: use lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_stop.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index d87ed16..f0786fc 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -38,15 +38,28 @@
 
 lxc_log_define(lxc_stop_ui, lxc);
 
-static int my_parser(struct lxc_arguments* args, int c, char* arg)
+static int my_parser(struct lxc_arguments *args, int c, char *arg)
 {
 	switch (c) {
-	case 'r': args->reboot = 1; break;
-	case 'W': args->nowait = 1; break;
-	case 't': args->timeout = atoi(arg); break;
-	case 'k': args->hardstop = 1; break;
-	case OPT_NO_LOCK: args->nolock = 1; break;
-	case OPT_NO_KILL: args->nokill = 1; break;
+	case 'r':
+		args->reboot = 1;
+		break;
+	case 'W':
+		args->nowait = 1;
+		break;
+	case 't':
+		if (lxc_safe_int(arg, &args->timeout) < 0)
+			return -1;
+		break;
+	case 'k':
+		args->hardstop = 1;
+		break;
+	case OPT_NO_LOCK:
+		args->nolock = 1;
+		break;
+	case OPT_NO_KILL:
+		args->nokill = 1;
+		break;
 	}
 	return 0;
 }

From 0f44398bd67bfc5c6e7a1ec0493c10ce33517d98 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:39:36 +0200
Subject: [PATCH 263/334] utils: add lxc_safe_long()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 22 +++++++++++++++++++++-
 src/lxc/utils.h |  1 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index e1191a3..200f5cd 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -2007,7 +2007,7 @@ int lxc_safe_uint(const char *numstr, unsigned int *converted)
 	if (uli > UINT_MAX)
 		return -ERANGE;
 
-	*converted = (unsigned)uli;
+	*converted = (unsigned int)uli;
 	return 0;
 }
 
@@ -2030,3 +2030,23 @@ int lxc_safe_int(const char *numstr, int *converted)
 	*converted = (int)sli;
 	return 0;
 }
+
+int lxc_safe_long(const char *numstr, long int *converted)
+{
+	char *err = NULL;
+	signed long int sli;
+
+	errno = 0;
+	sli = strtol(numstr, &err, 0);
+	if (errno > 0)
+		return -errno;
+
+	if (!err || err == numstr || *err != '\0')
+		return -EINVAL;
+
+	if (sli > LONG_MAX)
+		return -ERANGE;
+
+	*converted = sli;
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 8fba515..0d63bb6 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -320,5 +320,6 @@ bool task_blocking_signal(pid_t pid, int signal);
 /* Helper functions to parse numbers. */
 int lxc_safe_uint(const char *numstr, unsigned int *converted);
 int lxc_safe_int(const char *numstr, int *converted);
+int lxc_safe_long(const char *numstr, long int *converted);
 
 #endif /* __LXC_UTILS_H */

From 45cf2817685c102421f14149334eea4331219260 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:39:54 +0200
Subject: [PATCH 264/334] tests: add unit tests for lxc_safe_long()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxc-test-utils.c | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 46f8cf3..ecbbca1 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -22,10 +22,12 @@
  */
 
 #define _GNU_SOURCE
+#define __STDC_FORMAT_MACROS
 #include <errno.h>
 #include <fcntl.h>
-#include <sched.h>
+#include <inttypes.h>
 #include <limits.h>
+#include <sched.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -283,6 +285,40 @@ void test_lxc_safe_int(void)
 	lxc_test_assert_abort((-ERANGE == lxc_safe_int(int_max, &n)));
 }
 
+void test_lxc_safe_long(void)
+{
+	int ret;
+	signed long int n;
+	size_t len = /* 2^64 = 21 - 1 */ 21;
+	char long_max[len];
+
+	ret = snprintf(long_max, len, "%lld", LLONG_MAX);
+	if (ret < 0 || (size_t)ret >= len) {
+		lxc_error("%s\n", "Failed to create string via snprintf().");
+		exit(EXIT_FAILURE);
+	}
+
+	lxc_test_assert_abort((0 == lxc_safe_long("1234345", &n)) && n == 1234345);
+	lxc_test_assert_abort((0 == lxc_safe_long("   345", &n)) && n == 345);
+	lxc_test_assert_abort((0 == lxc_safe_long("-1234345", &n)) && n == -1234345);
+	lxc_test_assert_abort((0 == lxc_safe_long("   -345", &n)) && n == -345);
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("   g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("   3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("   345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g   ", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("g", &n)));
+	lxc_test_assert_abort((-EINVAL == lxc_safe_long("   g345", &n)));
+	if (LONG_MAX != LLONG_MAX)
+		lxc_test_assert_abort((-ERANGE == lxc_safe_long(long_max, &n)));
+	else
+		lxc_test_assert_abort((0 == lxc_safe_long(long_max, &n)) && n == LONG_MAX);
+}
+
 void test_lxc_string_replace(void)
 {
 	char *s;
@@ -343,6 +379,7 @@ int main(int argc, char *argv[])
 	test_detect_ramfs_rootfs();
 	test_lxc_safe_uint();
 	test_lxc_safe_int();
+	test_lxc_safe_long();
 
 	exit(EXIT_SUCCESS);
 }

From 9dfa6e193a2fd40d909f175c1675b70b793a158d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 12:40:15 +0200
Subject: [PATCH 265/334] tools/lxc_stop: use lxc_safe_long()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_stop.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index f0786fc..64b742d 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -48,7 +48,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
 		args->nowait = 1;
 		break;
 	case 't':
-		if (lxc_safe_int(arg, &args->timeout) < 0)
+		if (lxc_safe_long(arg, &args->timeout) < 0)
 			return -1;
 		break;
 	case 'k':
@@ -168,17 +168,14 @@ int main(int argc, char *argv[])
 
 	/* Set default timeout */
 	if (my_args.timeout == -2) {
-		if (my_args.hardstop) {
+		if (my_args.hardstop)
 			my_args.timeout = 0;
-		}
-		else {
+		else
 			my_args.timeout = 60;
-		}
 	}
 
-	if (my_args.nowait) {
+	if (my_args.nowait)
 		my_args.timeout = 0;
-	}
 
 	/* some checks */
 	if (!my_args.hardstop && my_args.timeout < -1) {

From 0dd2eef277f01330084f272785b78ac2af8be22d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 13:11:14 +0200
Subject: [PATCH 266/334] tools/lxc_top: use lxc_safe_int()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_top.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c
index faeab33..d8e7247 100644
--- a/src/lxc/tools/lxc_top.c
+++ b/src/lxc/tools/lxc_top.c
@@ -74,9 +74,16 @@ static int ct_alloc_cnt = 0;
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
 	switch (c) {
-	case 'd': delay = atoi(arg); break;
-	case 's': sort_by = arg[0]; break;
-	case 'r': sort_reverse = 1; break;
+	case 'd':
+		if (lxc_safe_int(arg, &delay) < 0)
+			return -1;
+		break;
+	case 's':
+		sort_by = arg[0];
+		break;
+	case 'r':
+		sort_reverse = 1;
+		break;
 	}
 	return 0;
 }

From 3b56f0327b79afda95ec6441d3fb77053cb5dfc8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 13:13:21 +0200
Subject: [PATCH 267/334] tools/lxc_ls: use lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_ls.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index 5e2cb4a..b5ddeef 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -459,8 +459,14 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
 				goto put_and_next;
 
 			tmp = ls_get_config_item(c, "lxc.start.auto", running);
-			if (tmp)
-				l->autostart = atoi(tmp);
+			if (tmp) {
+				unsigned int astart = 0;
+				if (lxc_safe_uint(tmp, &astart) < 0)
+					WARN("Could not parse value for 'lxc.start.auto'.");
+				if (astart > 1)
+					DEBUG("Wrong value for 'lxc.start.auto = %d'.", astart);
+				l->autostart = astart == 1 ? true : false;
+			}
 			free(tmp);
 
 			if (running) {

From 4efa4bb965dc5547b7e8418d0f72eee6ac5ae966 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 13:23:47 +0200
Subject: [PATCH 268/334] tools/lxc_autostart: use lxc_safe_{int,long}()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/tools/lxc_autostart.c | 38 +++++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c
index 267cb6c..a24dd7c 100644
--- a/src/lxc/tools/lxc_autostart.c
+++ b/src/lxc/tools/lxc_autostart.c
@@ -26,6 +26,7 @@
 #include "arguments.h"
 #include "list.h"
 #include "log.h"
+#include "utils.h"
 
 lxc_log_define(lxc_autostart_ui, lxc);
 static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list);
@@ -35,14 +36,31 @@ struct lxc_list *cmd_groups_list = NULL;
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
 	switch (c) {
-	case 'k': args->hardstop = 1; break;
-	case 'L': args->list = 1; break;
-	case 'r': args->reboot = 1; break;
-	case 's': args->shutdown = 1; break;
-	case 'a': args->all = 1; break;
-	case 'A': args->ignore_auto = 1; break;
-	case 'g': cmd_groups_list = accumulate_list( arg, ",", cmd_groups_list); break;
-	case 't': args->timeout = atoi(arg); break;
+	case 'k':
+		args->hardstop = 1;
+		break;
+	case 'L':
+		args->list = 1;
+		break;
+	case 'r':
+		args->reboot = 1;
+		break;
+	case 's':
+		args->shutdown = 1;
+		break;
+	case 'a':
+		args->all = 1;
+		break;
+	case 'A':
+		args->ignore_auto = 1;
+		break;
+	case 'g':
+		cmd_groups_list = accumulate_list(arg, ",", cmd_groups_list);
+		break;
+	case 't':
+		if (lxc_safe_long(arg, &args->timeout) < 0)
+			return -1;
+		break;
 	}
 	return 0;
 }
@@ -290,7 +308,9 @@ static int get_config_integer(struct lxc_container *c, char *key) {
 		return 0;
 	}
 
-	ret = atoi(value);
+	if (lxc_safe_int(value, &ret) < 0)
+		DEBUG("Could not parse config item.");
+
 	free(value);
 
 	return ret;

From 89154b89106968cad1d4e286b734717e0513be83 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Sat, 29 Oct 2016 13:29:26 +0200
Subject: [PATCH 269/334] tools/lxc_console: use lxc_safe_uint()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/arguments.h         |  2 +-
 src/lxc/tools/lxc_console.c | 31 ++++++++++++++++++-------------
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
index 4e7591f..c00f0a2 100644
--- a/src/lxc/arguments.h
+++ b/src/lxc/arguments.h
@@ -61,7 +61,7 @@ struct lxc_arguments {
 	const char *share_ns[32]; // size must be greater than LXC_NS_MAX
 
 	/* for lxc-console */
-	int ttynum;
+	unsigned int ttynum;
 	char escape;
 
 	/* for lxc-wait */
diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c
index 5d8dd4d..88a24be 100644
--- a/src/lxc/tools/lxc_console.c
+++ b/src/lxc/tools/lxc_console.c
@@ -22,29 +22,29 @@
  */
 
 #define _GNU_SOURCE
-#include <stdio.h>
-#undef _GNU_SOURCE
-#include <stdlib.h>
 #include <errno.h>
-#include <string.h>
 #include <fcntl.h>
-#include <unistd.h>
-#include <signal.h>
 #include <libgen.h>
 #include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
 #include <sys/param.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/ioctl.h>
+#include <sys/types.h>
 
 #include <lxc/lxccontainer.h>
 
+#include "arguments.h"
+#include "commands.h"
 #include "error.h"
-#include "lxc.h"
 #include "log.h"
+#include "lxc.h"
 #include "mainloop.h"
-#include "arguments.h"
-#include "commands.h"
+#include "utils.h"
 
 lxc_log_define(lxc_console_ui, lxc);
 
@@ -58,8 +58,13 @@ static char etoc(const char *expr)
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
 	switch (c) {
-	case 't': args->ttynum = atoi(arg); break;
-	case 'e': args->escape = etoc(arg); break;
+	case 't':
+		if (lxc_safe_uint(arg, &args->ttynum) < 0)
+			return -1;
+		break;
+	case 'e':
+		args->escape = etoc(arg);
+		break;
 	}
 	return 0;
 }

From 0d7574d59aebee39d9e79482e8fcf17535396088 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 22 Nov 2016 09:42:59 +0100
Subject: [PATCH 270/334] tools: replace non-standard namespace identifiers

The identifiers for namespaces used with lxc-unshare and lxc-attach as given on
the manpage do not align with the standard identifiers. This affects network,
mount, and uts namespaces. The standard identifiers are: "mnt", "uts", and
"net" whereas lxc-unshare and lxc-attach use "MOUNT", "UTSNAME", and "NETWORK".
I'm weary to hack this into namespace.{c.h} by e.g. adding additional members
to the ns_info struct or to special case this in lxc_fill_namespace_flags().
Internally, we should only accept standard identifiers to ensure that we are
always correctly aligned with the kernel. So let's use some cheap memmove()s to
replace them by their standard identifiers in lxc-unshare and lxc-attach.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/tools/lxc_attach.c  | 26 ++++++++++++++++++++++++++
 src/lxc/tools/lxc_unshare.c | 30 ++++++++++++++++++++++++++----
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 51fd536..4dd3883 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -107,6 +107,8 @@ static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
 
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
+	char **it;
+	char *del;
 	int ret;
 
 	switch (c) {
@@ -125,6 +127,30 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
 		break;
 	case 's':
 		namespace_flags = 0;
+
+		/* The identifiers for namespaces used with lxc-attach as given
+		 * on the manpage do not align with the standard identifiers.
+		 * This affects network, mount, and uts namespaces. The standard
+		 * identifiers are: "mnt", "uts", and "net" whereas lxc-attach
+		 * uses "MOUNT", "UTSNAME", and "NETWORK". So let's use some
+		 * cheap memmove()s to replace them by their standard
+		 * identifiers. Let's illustrate this with an example:
+		 * Assume the string:
+		 *
+		 *	"IPC|MOUNT|PID"
+		 *
+		 * then we memmove()
+		 *
+		 *	dest: del + 1 == ONT|PID
+		 *	src:  del + 3 == NT|PID
+		 */
+		while ((del = strstr(arg, "MOUNT")))
+			memmove(del + 1, del + 3, strlen(del) - 2);
+
+		for (it = (char *[]){"NETWORK", "UTSNAME", NULL}; it && *it; it++)
+			while ((del = strstr(arg, *it)))
+				memmove(del + 3, del + 7, strlen(del) - 6);
+
 		ret = lxc_fill_namespace_flags(arg, &namespace_flags);
 		if (ret)
 			return -1;
diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
index 6c9423f..72ea00c 100644
--- a/src/lxc/tools/lxc_unshare.c
+++ b/src/lxc/tools/lxc_unshare.c
@@ -76,7 +76,7 @@ static void usage(char *cmd)
 	fprintf(stderr, "\t -i <iface>   : Interface name to be moved into container (presumably with NETWORK unsharing set)\n");
 	fprintf(stderr, "\t -H <hostname>: Set the hostname in the container\n");
 	fprintf(stderr, "\t -d           : Daemonize (do not wait for container to exit)\n");
-	fprintf(stderr, "\t -M           : reMount default fs inside container (/proc /dev/shm /dev/mqueue)\n");
+	fprintf(stderr, "\t -M           : Remount default fs inside container (/proc /dev/shm /dev/mqueue)\n");
 	_exit(EXIT_SUCCESS);
 }
 
@@ -151,12 +151,12 @@ static int do_start(void *arg)
 
 int main(int argc, char *argv[])
 {
+	char *del;
+	char **it, **args;
 	int opt, status;
 	int ret;
 	char *namespaces = NULL;
-	char **args;
-	int flags = 0;
-	int daemonize = 0;
+	int flags = 0, daemonize = 0;
 	uid_t uid = 0; /* valid only if (flags & CLONE_NEWUSER) */
 	pid_t pid;
 	struct my_iflist *tmpif, *my_iflist = NULL;
@@ -213,6 +213,28 @@ int main(int argc, char *argv[])
 	if (ret)
 		exit(EXIT_FAILURE);
 
+	/* The identifiers for namespaces used with lxc-unshare as given on the
+	 * manpage do not align with the standard identifiers. This affects
+	 * network, mount, and uts namespaces. The standard identifiers are:
+	 * "mnt", "uts", and "net" whereas lxc-unshare uses "MOUNT", "UTSNAME",
+	 * and "NETWORK". So let's use some cheap memmove()s to replace them by
+	 * their standard identifiers. Let's illustrate this with an example:
+	 * Assume the string:
+	 *
+	 *	"IPC|MOUNT|PID"
+	 *
+	 * then we memmove()
+	 *
+	 *	dest: del + 1 == ONT|PID
+	 *	src:  del + 3 == NT|PID
+	 */
+	while ((del = strstr(namespaces, "MOUNT")))
+		memmove(del + 1, del + 3, strlen(del) - 2);
+
+	for (it = (char *[]){"NETWORK", "UTSNAME", NULL}; it && *it; it++)
+		while ((del = strstr(namespaces, *it)))
+			memmove(del + 3, del + 7, strlen(del) - 6);
+
 	ret = lxc_fill_namespace_flags(namespaces, &flags);
 	if (ret)
 		usage(argv[0]);

From 6d14aa2b8a3d924fde5673073ae1c6bb4917f604 Mon Sep 17 00:00:00 2001
From: Cam Cope <cam at dropbox.com>
Date: Tue, 22 Nov 2016 15:16:32 -0800
Subject: [PATCH 271/334] Configure a static MAC address on the LXC bridge

Signed-off-by: Cam Cope <cam at dropbox.com>
---
 config/init/common/lxc-net.in | 2 ++
 lxc.spec.in                   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/config/init/common/lxc-net.in b/config/init/common/lxc-net.in
index d457e78..4797f20 100644
--- a/config/init/common/lxc-net.in
+++ b/config/init/common/lxc-net.in
@@ -9,6 +9,7 @@ varlib="@LOCALSTATEDIR@/lib"
 
 USE_LXC_BRIDGE="true"
 LXC_BRIDGE="lxcbr0"
+LXC_BRIDGE_MAC="00:16:3e:00:00:00"
 LXC_ADDR="10.0.3.1"
 LXC_NETMASK="255.255.255.0"
 LXC_NETWORK="10.0.3.0/24"
@@ -45,6 +46,7 @@ ifup() {
     MASK=`_netmask2cidr ${LXC_NETMASK}`
     CIDR_ADDR="${LXC_ADDR}/${MASK}"
     ip addr add ${CIDR_ADDR} dev $1
+    ip link set dev $1 address $LXC_BRIDGE_MAC
     ip link set dev $1 up
 }
 
diff --git a/lxc.spec.in b/lxc.spec.in
index dadd739..0e64907 100644
--- a/lxc.spec.in
+++ b/lxc.spec.in
@@ -195,6 +195,7 @@ USE_LXC_BRIDGE="true"
 # If you have the dnsmasq daemon installed, you'll also have to update
 # /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
 LXC_BRIDGE="lxcbr0"
+LXC_BRIDGE_MAC="00:16:3e:00:00:00"
 LXC_ADDR="$SUBNET.1"
 LXC_NETMASK="255.255.255.0"
 LXC_NETWORK="$SUBNET.0/24"

From 6c27d1a68a88a448c3389405e67736b70f3fd3ee Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 22 Nov 2016 17:38:18 +0100
Subject: [PATCH 272/334] tests: remove overflow tests

They do not behave correctly on some architectures, so let's remove them for
now and come up with better ones later.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/tests/lxc-test-utils.c | 33 ---------------------------------
 1 file changed, 33 deletions(-)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index ecbbca1..e32415b 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -227,16 +227,7 @@ void test_detect_ramfs_rootfs(void)
 
 void test_lxc_safe_uint(void)
 {
-	int ret;
 	unsigned int n;
-	size_t len = /* 2^64 = 21 - 1 */ 21;
-	char uint_max[len];
-
-	ret = snprintf(uint_max, len, "%lu", (unsigned long)UINT_MAX + 1);
-	if (ret < 0 || (size_t)ret >= len) {
-		lxc_error("%s\n", "Failed to create string via snprintf().");
-		exit(EXIT_FAILURE);
-	}
 
 	lxc_test_assert_abort((0 == lxc_safe_uint("1234345", &n)) && n == 1234345);
 	lxc_test_assert_abort((0 == lxc_safe_uint("   345", &n)) && n == 345);
@@ -251,21 +242,11 @@ void test_lxc_safe_uint(void)
 	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g   ", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_uint("   g345", &n)));
-	lxc_test_assert_abort((-ERANGE == lxc_safe_uint(uint_max, &n)));
 }
 
 void test_lxc_safe_int(void)
 {
-	int ret;
 	signed int n;
-	size_t len = /* 2^64 = 21 - 1 */ 21;
-	char int_max[len];
-
-	ret = snprintf(int_max, len, "%ld", (signed long)INT_MAX + 1);
-	if (ret < 0 || (size_t)ret >= len) {
-		lxc_error("%s\n", "Failed to create string via snprintf().");
-		exit(EXIT_FAILURE);
-	}
 
 	lxc_test_assert_abort((0 == lxc_safe_int("1234345", &n)) && n == 1234345);
 	lxc_test_assert_abort((0 == lxc_safe_int("   345", &n)) && n == 345);
@@ -282,21 +263,11 @@ void test_lxc_safe_int(void)
 	lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g   ", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_int("g", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_int("   g345", &n)));
-	lxc_test_assert_abort((-ERANGE == lxc_safe_int(int_max, &n)));
 }
 
 void test_lxc_safe_long(void)
 {
-	int ret;
 	signed long int n;
-	size_t len = /* 2^64 = 21 - 1 */ 21;
-	char long_max[len];
-
-	ret = snprintf(long_max, len, "%lld", LLONG_MAX);
-	if (ret < 0 || (size_t)ret >= len) {
-		lxc_error("%s\n", "Failed to create string via snprintf().");
-		exit(EXIT_FAILURE);
-	}
 
 	lxc_test_assert_abort((0 == lxc_safe_long("1234345", &n)) && n == 1234345);
 	lxc_test_assert_abort((0 == lxc_safe_long("   345", &n)) && n == 345);
@@ -313,10 +284,6 @@ void test_lxc_safe_long(void)
 	lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g   ", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_long("g", &n)));
 	lxc_test_assert_abort((-EINVAL == lxc_safe_long("   g345", &n)));
-	if (LONG_MAX != LLONG_MAX)
-		lxc_test_assert_abort((-ERANGE == lxc_safe_long(long_max, &n)));
-	else
-		lxc_test_assert_abort((0 == lxc_safe_long(long_max, &n)) && n == LONG_MAX);
 }
 
 void test_lxc_string_replace(void)

From ef7bedf6387d50b04297a6534730078cf9f9d20d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Fri, 18 Nov 2016 17:03:25 +0100
Subject: [PATCH 273/334] attach: do not send procfd to attached process

So far, we opened a file descriptor refering to proc on the host inside the
host namespace and handed that fd to the attached process in
attach_child_main(). This was done to ensure that LSM labels were correctly
setup. However, by exploiting a potential kernel bug, ptrace could be used to
prevent the file descriptor from being closed which in turn could be used by an
unprivileged container to gain access to the host namespace. Aside from this
needing an upstream kernel fix, we should make sure that we don't pass the fd
for proc itself to the attached process. However, we cannot completely prevent
this, as the attached process needs to be able to change its apparmor profile
by writing to /proc/self/attr/exec or /proc/self/attr/current. To minimize the
attack surface, we only send the fd for /proc/self/attr/exec or
/proc/self/attr/current to the attached process. To do this we introduce a
little more IPC between the child and parent:

	 * IPC mechanism: (X is receiver)
	 *   initial process        intermediate          attached
	 *        X           <---  send pid of
	 *                          attached proc,
	 *                          then exit
	 *    send 0 ------------------------------------>    X
	 *                                              [do initialization]
	 *        X  <------------------------------------  send 1
	 *   [add to cgroup, ...]
	 *    send 2 ------------------------------------>    X
	 *						[set LXC_ATTACH_NO_NEW_PRIVS]
	 *        X  <------------------------------------  send 3
	 *   [open LSM label fd]
	 *    send 4 ------------------------------------>    X
	 *   						[set LSM label]
	 *   close socket                                 close socket
	 *                                                run program

The attached child tells the parent when it is ready to have its LSM labels set
up. The parent then opens an approriate fd for the child PID to
/proc/<pid>/attr/exec or /proc/<pid>/attr/current and sends it via SCM_RIGHTS
to the child. The child can then set its LSM laben. Both sides then close the
socket fds and the child execs the requested process.

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/attach.c | 215 ++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 149 insertions(+), 66 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 22252f4..d5ae2bc 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -22,41 +22,43 @@
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/unistd.h>
+#include <sys/mount.h>
 #include <sys/param.h>
 #include <sys/prctl.h>
-#include <sys/mount.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/wait.h>
-#include <linux/unistd.h>
-#include <pwd.h>
 
 #if !HAVE_DECL_PR_CAPBSET_DROP
 #define PR_CAPBSET_DROP 24
 #endif
 
-#include "namespace.h"
-#include "log.h"
+#include "af_unix.h"
 #include "attach.h"
 #include "caps.h"
-#include "config.h"
-#include "utils.h"
-#include "commands.h"
 #include "cgroup.h"
-#include "lxclock.h"
+#include "commands.h"
 #include "conf.h"
+#include "config.h"
+#include "confile.h"
+#include "log.h"
+#include "lsm/lsm.h"
+#include "lxclock.h"
 #include "lxcseccomp.h"
+#include "namespace.h"
+#include "utils.h"
+
 #include <lxc/lxccontainer.h>
-#include "lsm/lsm.h"
-#include "confile.h"
 
 #if HAVE_SYS_PERSONALITY_H
 #include <sys/personality.h>
@@ -76,80 +78,103 @@
 
 lxc_log_define(lxc_attach, lxc);
 
-int lsm_set_label_at(int procfd, int on_exec, char* lsm_label) {
+static int lsm_openat(int procfd, pid_t pid, int on_exec)
+{
+	int ret = -1;
 	int labelfd = -1;
-	int ret = 0;
 	const char* name;
-	char* command = NULL;
+#define __LSMATTRLEN /* /proc */ (5 + /* /pid-to-str */ 21 + /* /current */ 7 + /* \0 */ 1)
+	char path[__LSMATTRLEN];
 
 	name = lsm_name();
 
 	if (strcmp(name, "nop") == 0)
-		goto out;
+		return 0;
 
 	if (strcmp(name, "none") == 0)
-		goto out;
+		return 0;
 
 	/* We don't support on-exec with AppArmor */
 	if (strcmp(name, "AppArmor") == 0)
 		on_exec = 0;
 
 	if (on_exec) {
-		labelfd = openat(procfd, "self/attr/exec", O_RDWR);
-	}
-	else {
-		labelfd = openat(procfd, "self/attr/current", O_RDWR);
+		ret = snprintf(path, __LSMATTRLEN, "%d/attr/exec", pid);
+		if (ret < 0 || ret >= __LSMATTRLEN)
+			return -1;
+		labelfd = openat(procfd, path, O_RDWR);
+	} else {
+		ret = snprintf(path, __LSMATTRLEN, "%d/attr/current", pid);
+		if (ret < 0 || ret >= __LSMATTRLEN)
+			return -1;
+		labelfd = openat(procfd, path, O_RDWR);
 	}
 
 	if (labelfd < 0) {
 		SYSERROR("Unable to open LSM label");
-		ret = -1;
-		goto out;
+		return -1;
 	}
 
+	return labelfd;
+}
+
+static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
+{
+	int fret = -1;
+	const char* name;
+	char *command = NULL;
+
+	name = lsm_name();
+
+	if (strcmp(name, "nop") == 0)
+		return 0;
+
+	if (strcmp(name, "none") == 0)
+		return 0;
+
+	/* We don't support on-exec with AppArmor */
+	if (strcmp(name, "AppArmor") == 0)
+		on_exec = 0;
+
 	if (strcmp(name, "AppArmor") == 0) {
 		int size;
 
 		command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
 		if (!command) {
 			SYSERROR("Failed to write apparmor profile");
-			ret = -1;
 			goto out;
 		}
 
 		size = sprintf(command, "changeprofile %s", lsm_label);
 		if (size < 0) {
 			SYSERROR("Failed to write apparmor profile");
-			ret = -1;
 			goto out;
 		}
 
-		if (write(labelfd, command, size + 1) < 0) {
-			SYSERROR("Unable to set LSM label");
-			ret = -1;
+		if (write(lsm_labelfd, command, size + 1) < 0) {
+			SYSERROR("Unable to set LSM label: %s.", command);
 			goto out;
 		}
-	}
-	else if (strcmp(name, "SELinux") == 0) {
-		if (write(labelfd, lsm_label, strlen(lsm_label) + 1) < 0) {
+		INFO("Set LSM label to: %s.", command);
+	} else if (strcmp(name, "SELinux") == 0) {
+		if (write(lsm_labelfd, lsm_label, strlen(lsm_label) + 1) < 0) {
 			SYSERROR("Unable to set LSM label");
-			ret = -1;
 			goto out;
 		}
-	}
-	else {
+		INFO("Set LSM label to: %s.", lsm_label);
+	} else {
 		ERROR("Unable to restore label for unknown LSM: %s", name);
-		ret = -1;
 		goto out;
 	}
+	fret = 0;
 
 out:
 	free(command);
 
-	if (labelfd != -1)
-		close(labelfd);
+	if (lsm_labelfd != -1)
+		close(lsm_labelfd);
 
-	return ret;
+	return fret;
 }
 
 static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
@@ -638,7 +663,6 @@ struct attach_clone_payload {
 	struct lxc_proc_context_info* init_ctx;
 	lxc_attach_exec_t exec_function;
 	void* exec_payload;
-	int procfd;
 };
 
 static int attach_child_main(void* data);
@@ -710,7 +734,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	char* cwd;
 	char* new_cwd;
 	int ipc_sockets[2];
-	int procfd;
 	signed long personality;
 
 	if (!options)
@@ -780,6 +803,11 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	 *        X  <------------------------------------  send 1
 	 *   [add to cgroup, ...]
 	 *    send 2 ------------------------------------>    X
+	 *						[set LXC_ATTACH_NO_NEW_PRIVS]
+	 *        X  <------------------------------------  send 3
+	 *   [open LSM label fd]
+	 *    send 4 ------------------------------------>    X
+	 *   						[set LSM label]
 	 *   close socket                                 close socket
 	 *                                                run program
 	 */
@@ -813,6 +841,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	}
 
 	if (pid) {
+		int procfd = -1;
 		pid_t to_cleanup_pid = pid;
 
 		/* initial thread, we close the socket that is for the
@@ -827,6 +856,15 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 				goto cleanup_error;
 		}
 
+		/* Open /proc before setns() to the containers namespace so we
+		 * don't rely on any information from inside the container.
+		 */
+		procfd = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+		if (procfd < 0) {
+			SYSERROR("Unable to open /proc.");
+			goto cleanup_error;
+		}
+
 		/* Let the child process know to go ahead */
 		status = 0;
 		ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
@@ -839,7 +877,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL);
 		if (ret <= 0) {
 			if (ret != 0)
-				ERROR("error using IPC to receive pid of attached process");
+				ERROR("error using IPC to receive notification "
+						"from attached process (1)");
 			goto cleanup_error;
 		}
 
@@ -878,10 +917,40 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		status = 2;
 		ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
 		if (ret <= 0) {
-			ERROR("error using IPC to notify attached process for initialization (2)");
+			ERROR("Error using IPC to notify attached process for "
+			      "initialization (2): %s.", strerror(errno));
 			goto cleanup_error;
 		}
 
+		/* Wait for the (grand)child to tell us that it's ready to set
+		 * up its LSM labels.
+		 */
+		expected = 3;
+		ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected);
+		if (ret <= 0) {
+			ERROR("Error using IPC for the child to tell us to open LSM fd (3): %s.",
+					strerror(errno));
+			goto cleanup_error;
+		}
+
+		/* Open LSM fd and send it to child. */
+		if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
+			int on_exec, labelfd;
+			on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
+			/* Open fd for the LSM security module. */
+			labelfd = lsm_openat(procfd, attached_pid, on_exec);
+			if (labelfd < 0)
+				goto cleanup_error;
+
+			/* Send child fd of the LSM security module to write to. */
+			ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
+			if (ret <= 0) {
+				ERROR("Error using IPC to send child LSM fd (4): %s.",
+						strerror(errno));
+				goto cleanup_error;
+			}
+		}
+
 		/* now shut down communication with child, we're done */
 		shutdown(ipc_sockets[0], SHUT_RDWR);
 		close(ipc_sockets[0]);
@@ -899,6 +968,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		/* first shut down the socket, then wait for the pid,
 		 * otherwise the pid we're waiting for may never exit
 		 */
+		if (procfd >= 0)
+			close(procfd);
 		shutdown(ipc_sockets[0], SHUT_RDWR);
 		close(ipc_sockets[0]);
 		if (to_cleanup_pid)
@@ -925,13 +996,6 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	if ((options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) && cgns_supported())
 		options->namespaces |= CLONE_NEWCGROUP;
 
-	procfd = open("/proc", O_DIRECTORY | O_RDONLY);
-	if (procfd < 0) {
-		SYSERROR("Unable to open /proc");
-		shutdown(ipc_sockets[1], SHUT_RDWR);
-		rexit(-1);
-	}
-
 	/* attach now, create another subprocess later, since pid namespaces
 	 * only really affect the children of the current process
 	 */
@@ -959,8 +1023,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 			.options = options,
 			.init_ctx = init_ctx,
 			.exec_function = exec_function,
-			.exec_payload = exec_payload,
-			.procfd = procfd
+			.exec_payload = exec_payload
 		};
 		/* We use clone_parent here to make this subprocess a direct child of
 		 * the initial process. Then this intermediate process can exit and
@@ -998,7 +1061,6 @@ static int attach_child_main(void* data)
 {
 	struct attach_clone_payload* payload = (struct attach_clone_payload*)data;
 	int ipc_socket = payload->ipc_socket;
-	int procfd = payload->procfd;
 	lxc_attach_options_t* options = payload->options;
 	struct lxc_proc_context_info* init_ctx = payload->init_ctx;
 #if HAVE_SYS_PERSONALITY_H
@@ -1009,6 +1071,7 @@ static int attach_child_main(void* data)
 	int expected;
 	long flags;
 	int fd;
+	int lsm_labelfd;
 	uid_t new_uid;
 	gid_t new_gid;
 
@@ -1019,7 +1082,7 @@ static int attach_child_main(void* data)
 	status = -1;
 	ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected);
 	if (ret <= 0) {
-		ERROR("error using IPC to receive notification from initial process (0)");
+		ERROR("Error using IPC to receive notification from initial process (0): %s.", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
@@ -1118,7 +1181,7 @@ static int attach_child_main(void* data)
 	status = 1;
 	ret = lxc_write_nointr(ipc_socket, &status, sizeof(status));
 	if (ret != sizeof(status)) {
-		ERROR("error using IPC to notify initial process for initialization (1)");
+		ERROR("Error using IPC to notify initial process for initialization (1): %s.", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
@@ -1130,30 +1193,53 @@ static int attach_child_main(void* data)
 	status = -1;
 	ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected);
 	if (ret <= 0) {
-		ERROR("error using IPC to receive final notification from initial process (2)");
+		ERROR("Error using IPC to receive message from initial process "
+		      "that it is done pre-initializing (2): %s",
+		      strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
-	shutdown(ipc_socket, SHUT_RDWR);
-	close(ipc_socket);
 
-	/* set new apparmor profile/selinux context */
+	/* Tell the (grand)parent to send us LSM label fd. */
+	status = 3;
+	ret = lxc_write_nointr(ipc_socket, &status, sizeof(status));
+	if (ret <= 0) {
+		ERROR("Error using IPC to tell parent to set up LSM labels (3): %s.", strerror(errno));
+		shutdown(ipc_socket, SHUT_RDWR);
+		rexit(-1);
+	}
+
 	if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
 		int on_exec;
+		/* Receive fd for LSM security module. */
+		ret = lxc_abstract_unix_recv_fd(ipc_socket, &lsm_labelfd, NULL, 0);
+		if (ret <= 0) {
+			ERROR("Error using IPC for parent to tell us LSM label fd (4): %s.", strerror(errno));
+			shutdown(ipc_socket, SHUT_RDWR);
+			rexit(-1);
+		}
 
+		/* Change into our new LSM profile. */
 		on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
-		if (lsm_set_label_at(procfd, on_exec, init_ctx->lsm_label) < 0) {
+		if (lsm_set_label_at(lsm_labelfd, on_exec, init_ctx->lsm_label) < 0) {
+			SYSERROR("Failed to set LSM label.");
+			shutdown(ipc_socket, SHUT_RDWR);
+			close(lsm_labelfd);
 			rexit(-1);
 		}
+		close(lsm_labelfd);
 	}
 
 	if (init_ctx->container && init_ctx->container->lxc_conf &&
 			lxc_seccomp_load(init_ctx->container->lxc_conf) != 0) {
 		ERROR("Loading seccomp policy");
+		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
+	shutdown(ipc_socket, SHUT_RDWR);
+	close(ipc_socket);
 	lxc_proc_put_context_info(init_ctx);
 
 	/* The following is done after the communication socket is
@@ -1192,9 +1278,6 @@ static int attach_child_main(void* data)
 				SYSERROR("Unable to clear CLOEXEC from fd");
 	}
 
-	/* we don't need proc anymore */
-	close(procfd);
-
 	/* we're done, so we can now do whatever the user intended us to do */
 	rexit(payload->exec_function(payload->exec_payload));
 }

From 2dbff50f0dce18eba59aca449f8aebd16db38bc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 23 Nov 2016 14:13:59 -0500
Subject: [PATCH 274/334] change version to 2.0.6 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index ad5e16c..4640c0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 m4_define([lxc_devel], 0)
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 5)
+m4_define([lxc_version_micro], 6)
 m4_define([lxc_version_beta], [])
 
 m4_define([lxc_abi_major], 1)

From dfc0b35fe373f76cfb2aa717ff0cf276d0d5c6cb Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 24 Nov 2016 07:58:01 +0100
Subject: [PATCH 275/334] attach: simplify lsm_openat()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/attach.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index d5ae2bc..dd2b4c3 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -78,12 +78,13 @@
 
 lxc_log_define(lxc_attach, lxc);
 
+/* /proc/pid-to-str/current\0 = (5 + 21 + 7 + 1) */
+#define __LSMATTRLEN (5 + 21 + 7 + 1)
 static int lsm_openat(int procfd, pid_t pid, int on_exec)
 {
 	int ret = -1;
 	int labelfd = -1;
-	const char* name;
-#define __LSMATTRLEN /* /proc */ (5 + /* /pid-to-str */ 21 + /* /current */ 7 + /* \0 */ 1)
+	const char *name;
 	char path[__LSMATTRLEN];
 
 	name = lsm_name();
@@ -98,20 +99,16 @@ static int lsm_openat(int procfd, pid_t pid, int on_exec)
 	if (strcmp(name, "AppArmor") == 0)
 		on_exec = 0;
 
-	if (on_exec) {
+	if (on_exec)
 		ret = snprintf(path, __LSMATTRLEN, "%d/attr/exec", pid);
-		if (ret < 0 || ret >= __LSMATTRLEN)
-			return -1;
-		labelfd = openat(procfd, path, O_RDWR);
-	} else {
+	else
 		ret = snprintf(path, __LSMATTRLEN, "%d/attr/current", pid);
-		if (ret < 0 || ret >= __LSMATTRLEN)
-			return -1;
-		labelfd = openat(procfd, path, O_RDWR);
-	}
+	if (ret < 0 || ret >= __LSMATTRLEN)
+		return -1;
 
+	labelfd = openat(procfd, path, O_RDWR);
 	if (labelfd < 0) {
-		SYSERROR("Unable to open LSM label");
+		SYSERROR("Unable to open file descriptor to set LSM label.");
 		return -1;
 	}
 

From 5b3214cabc793a51d9cdb0232a699c1530758f5e Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 02:42:51 +0100
Subject: [PATCH 276/334] log: use thread-safe localtime_r()

This fixes a race in liblxc logging which can lead to deadlocks. The reproducer
for this issue before this is to simply compile with --enable-tests and then
run:

    lxc-test-concurrent -j 20 -m create,start,stop,destroy -D

which should deadlock.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 525e4f0..e721236 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -20,6 +20,8 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+
+#define _GNU_SOURCE
 #include <assert.h>
 #include <stdio.h>
 #include <errno.h>
@@ -31,8 +33,6 @@
 #include <pthread.h>
 #include <time.h>
 
-#define __USE_GNU /* for *_CLOEXEC */
-
 #include <fcntl.h>
 #include <stdlib.h>
 
@@ -72,7 +72,7 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 {
 	char date[LXC_LOG_DATEFOMAT_SIZE] = "20150427012246";
 	char buffer[LXC_LOG_BUFFER_SIZE];
-	const struct tm *t;
+	struct tm newtime;
 	int n;
 	int ms;
 	int fd_to_use = -1;
@@ -88,8 +88,10 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	if (fd_to_use == -1)
 		return 0;
 
-	t = localtime(&event->timestamp.tv_sec);
-	strftime(date, sizeof(date), "%Y%m%d%H%M%S", t);
+	if (!localtime_r(&event->timestamp.tv_sec, &newtime))
+		return 0;
+
+	strftime(date, sizeof(date), "%Y%m%d%H%M%S", &newtime);
 	ms = event->timestamp.tv_usec / 1000;
 	n = snprintf(buffer, sizeof(buffer),
 		     "%15s %10s.%03d %-8s %s - %s:%s:%d - ",

From 31db998489b66029845d3dd5db92147702382a47 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 20:02:24 +0100
Subject: [PATCH 277/334] configure: check whether gettid() is declared

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 configure.ac  |  2 +-
 src/lxc/log.c | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 4640c0d..1360611 100644
--- a/configure.ac
+++ b/configure.ac
@@ -620,7 +620,7 @@ AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include <sys/prctl.h>])
 AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h sys/personality.h utmpx.h sys/timerfd.h])
 
 # Check for some syscalls functions
-AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat])
+AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid])
 
 # Check for some functions
 AC_CHECK_LIB(pthread, main)
diff --git a/src/lxc/log.c b/src/lxc/log.c
index e721236..1b3a99c 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -42,6 +42,20 @@
 
 #define LXC_LOG_DATEFOMAT_SIZE  15
 
+#ifndef HAVE_GETTID
+static inline pid_t gettid(void)
+{
+#ifdef __NR_gettid
+	return (pid_t)syscall(SYS_gettid);
+#else
+	errno = ENOSYS;
+	return -1;
+#endif
+}
+#else
+extern pid_t gettid(void);
+#endif
+
 int lxc_log_fd = -1;
 int lxc_quiet_specified;
 int lxc_log_use_global_fd;

From 27e0a15145b9b8756de95b4dbcf5f01ec6dd2986 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 17:28:18 +0100
Subject: [PATCH 278/334] log: fix race

localtime_r() can lead to deadlocks because it calls __tzset() and
__tzconvert() internally. The deadlock stems from an interaction between these
functions and the functions in monitor.c and commands.{c,h}. The latter
functions will write to the log independent of the container thread that is
currently running. Since the monitor fork()ed it seems to duplicate the mutex
states of the time functions mentioned above causing the deadlock.
As a short termm fix, I suggest to simply disable receiving the time when
monitor.c or command.{c,h} functions are called. This should be ok, since the
[lxc monitor] will only emit a few messages and thread-safety is currently more
important than beautiful logs. The rest of the log stays the same as it was
before.

Here is an example output from logs where I printed the pid and tid of the
process that is currently writing to the log:

            lxc 20161125170200.619 INFO     lxc_start:   18695-18695: - start.c:lxc_check_inherited:243 - Closed inherited fd: 23.
            lxc 20161125170200.640 DEBUG    lxc_start:   18677-18677: - start.c:__lxc_start:1334 - Not dropping CAP_SYS_BOOT or watching utmp.
            lxc 20161125170200.640 INFO     lxc_cgroup:  18677-18677: - cgroups/cgroup.c:cgroup_init:68 - cgroup driver cgroupfs-ng initing for lxc-test-concurrent-0

----------> lxc 20150427012246.000 INFO     lxc_monitor: 13017-18622: - monitor.c:lxc_monitor_sock_name:178 - using monitor sock name lxc/ad055575fe28ddd5//var/lib/lxc

            lxc 20161125170200.662 DEBUG    lxc_cgfsng:  18677-18677: - cgroups/cgfsng.c:filter_and_set_cpus:478 - No isolated cpus detected.
            lxc 20161125170200.662 DEBUG    lxc_cgfsng:  18677-18677: - cgroups/cgfsng.c:handle_cpuset_hierarchy:648 - "cgroup.clone_children" was already set to "1".

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 1b3a99c..a7c79b1 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -88,7 +88,7 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	char buffer[LXC_LOG_BUFFER_SIZE];
 	struct tm newtime;
 	int n;
-	int ms;
+	int ms = 0;
 	int fd_to_use = -1;
 
 #ifndef NO_LXC_CONF
@@ -102,11 +102,25 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	if (fd_to_use == -1)
 		return 0;
 
-	if (!localtime_r(&event->timestamp.tv_sec, &newtime))
-		return 0;
-
-	strftime(date, sizeof(date), "%Y%m%d%H%M%S", &newtime);
-	ms = event->timestamp.tv_usec / 1000;
+	/* localtime_r() can lead to deadlocks because it calls __tzset() and
+	 * __tzconvert() internally. The deadlock stems from an interaction
+	 * between these functions and the functions in monitor.c and
+	 * commands.{c,h}. The latter functions will write to the log
+	 * independent of the container thread that is currently running. Since
+	 * the monitor fork()ed it seems to duplicate the mutex states of the
+	 * time functions mentioned above.
+	 * As a short termm fix, I suggest to simply disable receiving the time
+	 * when monitor.c or command.{c,h} functions are called. This should be
+	 * ok, since the [lxc monitor] will only emit a few messages and
+	 * thread-safety is currently more important than beautiful logs. The
+	 * rest of the log stays the same as it was before.
+	 */
+	if (getpid() == gettid()) {
+		if (!localtime_r(&event->timestamp.tv_sec, &newtime))
+			return 0;
+		strftime(date, sizeof(date), "%Y%m%d%H%M%S", &newtime);
+		ms = event->timestamp.tv_usec / 1000;
+	}
 	n = snprintf(buffer, sizeof(buffer),
 		     "%15s %10s.%03d %-8s %s - %s:%s:%d - ",
 		     log_prefix,
@@ -121,13 +135,9 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 		return n;
 
 	if (n < sizeof(buffer) - 1)
-		n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt,
-			       *event->vap);
-	else {
-		WARN("truncated next event from %d to %zd bytes", n,
-		     sizeof(buffer));
+		n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt, *event->vap);
+	else
 		n = sizeof(buffer) - 1;
-	}
 
 	buffer[n] = '\n';
 

From 82630da5bf617b78a841cad8df116b15845ec014 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 20:23:00 +0100
Subject: [PATCH 279/334] log: use N/A if getpid() != gettid() when threaded

Sample log output:

    lxc 20161125201943.819 INFO     lxc_start - start.c:lxc_check_inherited:243 - Closed inherited fd: 54.
--> lxc N/A                INFO     lxc_monitor - monitor.c:lxc_monitor_sock_name:178 - using monitor sock name lxc/ad055575fe28ddd5//var/lib/lxc
    lxc 20161125201943.958 DEBUG    lxc_commands - commands.c:lxc_cmd_handler:893 - peer has disconnected
--> lxc N/A                DEBUG    lxc_commands - commands.c:lxc_cmd_get_state:579 - 'lxc-test-concurrent-0' is in 'RUNNING' state
    lxc 20161125201943.960 DEBUG    lxc_commands - commands.c:lxc_cmd_handler:893 - peer has disconnected
    lxc 20161125201944.009 INFO     lxc_start - start.c:lxc_check_inherited:243 - Closed inherited fd: 3.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 60 ++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index a7c79b1..94a5179 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -84,7 +84,7 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
 static int log_append_logfile(const struct lxc_log_appender *appender,
 			      struct lxc_log_event *event)
 {
-	char date[LXC_LOG_DATEFOMAT_SIZE] = "20150427012246";
+	char date[LXC_LOG_DATEFOMAT_SIZE] = "N/A";
 	char buffer[LXC_LOG_BUFFER_SIZE];
 	struct tm newtime;
 	int n;
@@ -102,39 +102,53 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	if (fd_to_use == -1)
 		return 0;
 
-	/* localtime_r() can lead to deadlocks because it calls __tzset() and
-	 * __tzconvert() internally. The deadlock stems from an interaction
-	 * between these functions and the functions in monitor.c and
-	 * commands.{c,h}. The latter functions will write to the log
-	 * independent of the container thread that is currently running. Since
-	 * the monitor fork()ed it seems to duplicate the mutex states of the
-	 * time functions mentioned above.
-	 * As a short termm fix, I suggest to simply disable receiving the time
-	 * when monitor.c or command.{c,h} functions are called. This should be
-	 * ok, since the [lxc monitor] will only emit a few messages and
-	 * thread-safety is currently more important than beautiful logs. The
-	 * rest of the log stays the same as it was before.
+	/* localtime_r() can lead to deadlocks when LXC is used multithreaded
+	 * because it calls __tzset() and __tzconvert() internally. The deadlock
+	 * stems from an interaction between these functions and the functions
+	 * in monitor.c and commands.{c,h}. Some of the latter functions will
+	 * write to the log independent of the container thread that is
+	 * currently running. Since the monitor fork()ed it seems to duplicate
+	 * the mutex states of the time functions mentioned above.
+	 * As a short term fix, I suggest to simply disable receiving the time
+	 * when these monitor.c or command.{c,h} functions are called. This
+	 * should be ok, since the [lxc monitor] will only emit a few messages
+	 * and thread-safety is currently more important than beautiful logs.
+	 * The rest of the log stays the same as it was before.
 	 */
 	if (getpid() == gettid()) {
 		if (!localtime_r(&event->timestamp.tv_sec, &newtime))
 			return 0;
 		strftime(date, sizeof(date), "%Y%m%d%H%M%S", &newtime);
 		ms = event->timestamp.tv_usec / 1000;
+		n = snprintf(buffer, sizeof(buffer),
+				"%15s%s%s %14s.%03d %-8s %s - %s:%s:%d - ",
+				log_prefix,
+				log_vmname ? " " : "",
+				log_vmname ? log_vmname : "",
+				date,
+				ms,
+				lxc_log_priority_to_string(event->priority),
+				event->category,
+				event->locinfo->file, event->locinfo->func,
+				event->locinfo->line);
+	} else {
+		n = snprintf(buffer, sizeof(buffer),
+				"%15s%s%s %-14s %3s %-8s %s - %s:%s:%d - ",
+				log_prefix,
+				log_vmname ? " " : "",
+				log_vmname ? log_vmname : "",
+				date,
+				"",
+				lxc_log_priority_to_string(event->priority),
+				event->category,
+				event->locinfo->file, event->locinfo->func,
+				event->locinfo->line);
 	}
-	n = snprintf(buffer, sizeof(buffer),
-		     "%15s %10s.%03d %-8s %s - %s:%s:%d - ",
-		     log_prefix,
-		     date,
-		     ms,
-		     lxc_log_priority_to_string(event->priority),
-		     event->category,
-		     event->locinfo->file, event->locinfo->func,
-		     event->locinfo->line);
 
 	if (n < 0)
 		return n;
 
-	if (n < sizeof(buffer) - 1)
+	if ((size_t)n < (sizeof(buffer) - 1))
 		n += vsnprintf(buffer + n, sizeof(buffer) - n, event->fmt, *event->vap);
 	else
 		n = sizeof(buffer) - 1;

From 62eeccaca2b4bdb18b123f5c33b27b9206557822 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 22:00:45 +0100
Subject: [PATCH 280/334] configure: do not allow variable length arrays

There pointless and marked as optional since C11.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 1360611..83715ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -655,7 +655,7 @@ LXC_CHECK_TLS
 if test "x$GCC" = "xyes"; then
 	CFLAGS="$CFLAGS -Wall"
 	if test "x$enable_werror" = "xyes"; then
-		CFLAGS="$CFLAGS -Werror"
+		CFLAGS="$CFLAGS -Werror -Werror=vla"
 	fi
 fi
 

From d4d6b0ce697f31a0e8c79caebdcc850148fd7949 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 22:01:20 +0100
Subject: [PATCH 281/334] tree-wide: remove any variable length arrays

They are pointless and marked optional since C11.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/tools/lxc_cgroup.c  |  5 ++---
 src/lxc/tools/lxc_unshare.c |  2 +-
 src/lxc/utils.c             | 11 +++++------
 src/tests/lxc-test-utils.c  |  9 +++++----
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/src/lxc/tools/lxc_cgroup.c b/src/lxc/tools/lxc_cgroup.c
index 32d333a..4027630 100644
--- a/src/lxc/tools/lxc_cgroup.c
+++ b/src/lxc/tools/lxc_cgroup.c
@@ -121,9 +121,8 @@ int main(int argc, char *argv[])
 			exit(EXIT_FAILURE);
 		}
 	} else {
-		int len = 4096;
-		char buffer[len];
-		int ret = c->get_cgroup_item(c, state_object, buffer, len);
+		char buffer[MAXPATHLEN];
+		int ret = c->get_cgroup_item(c, state_object, buffer, MAXPATHLEN);
 		if (ret < 0) {
 			ERROR("failed to retrieve value of '%s' for '%s:%s'",
 			      state_object, my_args.lxcpath[0], my_args.name);
diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c
index 72ea00c..82c8244 100644
--- a/src/lxc/tools/lxc_unshare.c
+++ b/src/lxc/tools/lxc_unshare.c
@@ -82,7 +82,7 @@ static void usage(char *cmd)
 
 static bool lookup_user(const char *optarg, uid_t *uid)
 {
-	char name[sysconf(_SC_LOGIN_NAME_MAX)];
+	char name[MAXPATHLEN];
 	struct passwd *pwent = NULL;
 
 	if (!optarg || (optarg[0] == '\0'))
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 200f5cd..7ddf1db 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1896,6 +1896,8 @@ int lxc_strmunmap(void *addr, size_t length)
 }
 
 /* Check whether a signal is blocked by a process. */
+/* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
+#define __PROC_STATUS_LEN (5 + 21 + 7 + 1)
 bool task_blocking_signal(pid_t pid, int signal)
 {
 	bool bret = false;
@@ -1905,13 +1907,10 @@ bool task_blocking_signal(pid_t pid, int signal)
 	int ret;
 	FILE *f;
 
-	/* The largest integer that can fit into long int is 2^64. This is a
-	 * 20-digit number. */
-	size_t len = /* /proc */ 5 + /* /pid-to-str */ 21 + /* /status */ 7 + /* \0 */ 1;
-	char status[len];
+	char status[__PROC_STATUS_LEN];
 
-	ret = snprintf(status, len, "/proc/%d/status", pid);
-	if (ret < 0 || ret >= len)
+	ret = snprintf(status, __PROC_STATUS_LEN, "/proc/%d/status", pid);
+	if (ret < 0 || ret >= __PROC_STATUS_LEN)
 		return bret;
 
 	f = fopen(status, "r");
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index e32415b..800c029 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -70,13 +70,14 @@ void test_lxc_deslashify(void)
 	free(s);
 }
 
+/* /proc/int_as_str/ns/mnt\0 = (5 + 21 + 7 + 1) */
+#define __MNTNS_LEN (5 + 21 + 7 + 1)
 void test_detect_ramfs_rootfs(void)
 {
 	size_t i;
 	int ret;
 	int fret = EXIT_FAILURE;
-	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 7 /* /ns/mnt */ + 1 /* \0 */;
-	char path[len];
+	char path[__MNTNS_LEN];
 	int init_ns = -1;
 	char tmpf1[] = "lxc-test-utils-XXXXXX";
 	char tmpf2[] = "lxc-test-utils-XXXXXX";
@@ -118,8 +119,8 @@ void test_detect_ramfs_rootfs(void)
 		"78 24 8:1 / /boot/efi rw,relatime shared:30 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro",
 	};
 
-	ret = snprintf(path, len, "/proc/self/ns/mnt");
-	if (ret < 0 || (size_t)ret >= len) {
+	ret = snprintf(path, __MNTNS_LEN, "/proc/self/ns/mnt");
+	if (ret < 0 || (size_t)ret >= __MNTNS_LEN) {
 		lxc_error("%s\n", "Failed to create path with snprintf().");
 		goto non_test_error;
 	}

From 62c990f89ceef898b33ec2cbdccce7dbf0e9fe60 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 23 Nov 2016 06:47:07 +0100
Subject: [PATCH 282/334] conf: non-functional changes

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 78 ++++++++++++++++++++++++++++------------------------------
 1 file changed, 37 insertions(+), 41 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index c54ee41..053f50c 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -24,20 +24,34 @@
 #define _GNU_SOURCE
 #include "config.h"
 
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <pwd.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
 #include <string.h>
-#include <dirent.h>
+#include <time.h>
 #include <unistd.h>
-#include <inttypes.h>
-#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <linux/loop.h>
+#include <linux/memfd.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-#include <time.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
 
 #ifdef HAVE_STATVFS
 #include <sys/statvfs.h>
@@ -49,37 +63,21 @@
 #include <../include/openpty.h>
 #endif
 
-#include <linux/loop.h>
-
-#include <sys/types.h>
-#include <sys/utsname.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/mount.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <libgen.h>
-
-#include "bdev.h"
-#include "network.h"
-#include "error.h"
 #include "af_unix.h"
-#include "parse.h"
-#include "utils.h"
+#include "bdev.h"
+#include "caps.h"       /* for lxc_caps_last_cap() */
+#include "cgroup.h"
 #include "conf.h"
+#include "error.h"
 #include "log.h"
-#include "caps.h"       /* for lxc_caps_last_cap() */
 #include "lxcaufs.h"
-#include "lxcoverlay.h"
-#include "cgroup.h"
 #include "lxclock.h"
+#include "lxcoverlay.h"
+#include "lxcseccomp.h"
 #include "namespace.h"
+#include "network.h"
+#include "parse.h"
+#include "utils.h"
 #include "lsm/lsm.h"
 
 #if HAVE_SYS_CAPABILITY_H
@@ -96,8 +94,6 @@
 #include <mntent.h>
 #endif
 
-#include "lxcseccomp.h"
-
 lxc_log_define(lxc_conf, lxc);
 
 #define LINELEN 4096
@@ -135,10 +131,10 @@ lxc_log_define(lxc_conf, lxc);
 static int pivot_root(const char * new_root, const char * put_old)
 {
 #ifdef __NR_pivot_root
-return syscall(__NR_pivot_root, new_root, put_old);
+	return syscall(__NR_pivot_root, new_root, put_old);
 #else
-errno = ENOSYS;
-return -1;
+	errno = ENOSYS;
+	return -1;
 #endif
 }
 #else
@@ -150,10 +146,10 @@ extern int pivot_root(const char * new_root, const char * put_old);
 static int sethostname(const char * name, size_t len)
 {
 #ifdef __NR_sethostname
-return syscall(__NR_sethostname, name, len);
+	return syscall(__NR_sethostname, name, len);
 #else
-errno = ENOSYS;
-return -1;
+	errno = ENOSYS;
+	return -1;
 #endif
 }
 #endif

From 038a2174c048fd74f9edda5c7362f9df9183e88d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 25 Nov 2016 20:55:38 +0100
Subject: [PATCH 283/334] configure: check for memfd_create()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 configure.ac | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 83715ce..5a6b084 100644
--- a/configure.ac
+++ b/configure.ac
@@ -617,10 +617,10 @@ AM_CONDITIONAL([IS_BIONIC], [test "x$is_bionic" = "xyes"])
 AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include <sys/prctl.h>])
 
 # Check for some headers
-AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h sys/personality.h utmpx.h sys/timerfd.h])
+AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h sys/memfd.h sys/personality.h utmpx.h sys/timerfd.h])
 
 # Check for some syscalls functions
-AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid])
+AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create])
 
 # Check for some functions
 AC_CHECK_LIB(pthread, main)

From 19b5201a7cd14c4f879130209768754fe410e15d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 23 Nov 2016 06:47:37 +0100
Subject: [PATCH 284/334] conf, criu: add make_anonymous_mount_file()

Before we used tmpfile() to write out mount entries for the container. This
requires a writeable /tmp file system which can be a problem for systems where
this filesystem is not present. This commit switches from tmpfile() to using
the memfd_create() syscall. It allows us to create an anonymous tmpfs file (And
is somewhat similar to mmap().) which is automatically deleted as soon as any
references to it are dropped. In case we detect that syscall is not
implemented, we fallback to using tmpfile().

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 src/lxc/conf.h |  2 +-
 src/lxc/criu.c |  2 +-
 3 files changed, 88 insertions(+), 13 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 053f50c..f40da30 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -39,7 +39,6 @@
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <linux/loop.h>
-#include <linux/memfd.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <sys/mman.h>
@@ -63,6 +62,10 @@
 #include <../include/openpty.h>
 #endif
 
+#ifdef HAVE_LINUX_MEMFD_H
+#include <linux/memfd.h>
+#endif
+
 #include "af_unix.h"
 #include "bdev.h"
 #include "caps.h"       /* for lxc_caps_last_cap() */
@@ -163,6 +166,59 @@ static int sethostname(const char * name, size_t len)
 #define MS_PRIVATE (1<<18)
 #endif
 
+/* memfd_create() */
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
+
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+#ifndef HAVE_MEMFD_CREATE
+static int memfd_create(const char *name, unsigned int flags) {
+	#ifndef __NR_memfd_create
+		#if defined __i386__
+			#define __NR_memfd_create 356
+		#elif defined __x86_64__
+			#define __NR_memfd_create 319
+		#elif defined __arm__
+			#define __NR_memfd_create 385
+		#elif defined __aarch64__
+			#define __NR_memfd_create 279
+		#elif defined __s390__
+			#define __NR_memfd_create 350
+		#elif defined __powerpc__
+			#define __NR_memfd_create 360
+		#elif defined __sparc__
+			#define __NR_memfd_create 348
+		#elif defined __blackfin__
+			#define __NR_memfd_create 390
+		#elif defined __ia64__
+			#define __NR_memfd_create 1340
+		#elif defined _MIPS_SIM
+			#if _MIPS_SIM == _MIPS_SIM_ABI32
+				#define __NR_memfd_create 4354
+			#endif
+			#if _MIPS_SIM == _MIPS_SIM_NABI32
+				#define __NR_memfd_create 6318
+			#endif
+			#if _MIPS_SIM == _MIPS_SIM_ABI64
+				#define __NR_memfd_create 5314
+			#endif
+		#endif
+	#endif
+	#ifdef __NR_memfd_create
+	return syscall(__NR_memfd_create, name, flags);
+	#else
+	errno = ENOSYS;
+	return -1;
+	#endif
+}
+#else
+extern int memfd_create(const char *name, unsigned int flags);
+#endif
+
 char *lxchook_names[NUM_LXC_HOOKS] = {
 	"pre-start", "pre-mount", "mount", "autodev", "start", "stop", "post-stop", "clone", "destroy" };
 
@@ -1946,34 +2002,53 @@ static int setup_mount(const struct lxc_rootfs *rootfs, const char *fstab,
 	return ret;
 }
 
-FILE *write_mount_file(struct lxc_list *mount)
+FILE *make_anonymous_mount_file(struct lxc_list *mount)
 {
-	FILE *file;
-	struct lxc_list *iterator;
+	int ret;
 	char *mount_entry;
+	struct lxc_list *iterator;
+	FILE *file;
+	int fd = -1;
+
+	fd = memfd_create("lxc_mount_file", MFD_CLOEXEC);
+	if (fd < 0) {
+		if (errno != ENOSYS)
+			return NULL;
+		file = tmpfile();
+	} else {
+		file = fdopen(fd, "r+");
+	}
 
-	file = tmpfile();
 	if (!file) {
-		ERROR("Could not create temporary file: %s.", strerror(errno));
+		if (fd != -1)
+			close(fd);
+		ERROR("Could not create mount entry file: %s.", strerror(errno));
 		return NULL;
 	}
 
 	lxc_list_for_each(iterator, mount) {
 		mount_entry = iterator->elem;
-		fprintf(file, "%s\n", mount_entry);
+		ret = fprintf(file, "%s\n", mount_entry);
+		if (ret < strlen(mount_entry))
+			WARN("Could not write mount entry to anonymous mount file.");
+	}
+
+	if (fseek(file, 0, SEEK_SET) < 0) {
+		fclose(file);
+		return NULL;
 	}
 
-	rewind(file);
 	return file;
 }
 
-static int setup_mount_entries(const struct lxc_rootfs *rootfs, struct lxc_list *mount,
-	const char *lxc_name, const char *lxc_path)
+static int setup_mount_entries(const struct lxc_rootfs *rootfs,
+			       struct lxc_list *mount, const char *lxc_name,
+			       const char *lxc_path)
 {
 	FILE *file;
 	int ret;
 
-	file = write_mount_file(mount);
+	file = make_anonymous_mount_file(mount);
 	if (!file)
 		return -1;
 
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 7aeba17..c790bf7 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -445,6 +445,6 @@ extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
 extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
 void remount_all_slave(void);
 extern void suggest_default_idmap(void);
-FILE *write_mount_file(struct lxc_list *mount);
+FILE *make_anonymous_mount_file(struct lxc_list *mount);
 struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings);
 #endif
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index b0a4239..f76eb82 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -330,7 +330,7 @@ static void exec_criu(struct criu_opts *opts)
 		DECLARE_ARG(opts->user->action_script);
 	}
 
-	mnts = write_mount_file(&opts->c->lxc_conf->mount_list);
+	mnts = make_anonymous_mount_file(&opts->c->lxc_conf->mount_list);
 	if (!mnts)
 		goto err;
 

From 4be37478bc03ef8ca65c1145f51d92d050d62496 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 05:03:55 +0100
Subject: [PATCH 285/334] monitor: non-functional changes

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/monitor.c | 147 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 84 insertions(+), 63 deletions(-)

diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c
index dd8ca9e..fab6f55 100644
--- a/src/lxc/monitor.c
+++ b/src/lxc/monitor.c
@@ -22,30 +22,31 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <stdio.h>
 #include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <poll.h>
+#include <stddef.h>
 #include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <netinet/in.h>
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/wait.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <poll.h>
 
-#include "error.h"
+#include "config.h"
 #include "af_unix.h"
+#include "error.h"
 #include "log.h"
 #include "lxclock.h"
-#include "state.h"
 #include "monitor.h"
+#include "state.h"
 #include "utils.h"
 
 lxc_log_define(lxc_monitor, lxc);
@@ -63,21 +64,21 @@ int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path, size_t fifo_path
 
 	if (do_mkdirp) {
 		ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s", rundir, lxcpath);
-		if (ret < 0 || ret >= fifo_path_sz) {
-			ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo", rundir, lxcpath);
+		if (ret < 0 || (size_t)ret >= fifo_path_sz) {
+			ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath);
 			free(rundir);
 			return -1;
 		}
 		ret = mkdir_p(fifo_path, 0755);
 		if (ret < 0) {
-			ERROR("unable to create monitor fifo dir %s", fifo_path);
+			ERROR("Unable to create monitor fifo directory %s.", fifo_path);
 			free(rundir);
 			return ret;
 		}
 	}
 	ret = snprintf(fifo_path, fifo_path_sz, "%s/lxc/%s/monitor-fifo", rundir, lxcpath);
-	if (ret < 0 || ret >= fifo_path_sz) {
-		ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo", rundir, lxcpath);
+	if (ret < 0 || (size_t)ret >= fifo_path_sz) {
+		ERROR("rundir/lxcpath (%s/%s) too long for monitor fifo.", rundir, lxcpath);
 		free(rundir);
 		return -1;
 	}
@@ -96,14 +97,18 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
 	if (ret < 0)
 		return;
 
-	/* open the fifo nonblock in case the monitor is dead, we don't want
-	 * the open to wait for a reader since it may never come.
+	/* Open the fifo nonblock in case the monitor is dead, we don't want the
+	 * open to wait for a reader since it may never come.
 	 */
-	fd = open(fifo_path, O_WRONLY|O_NONBLOCK);
+	fd = open(fifo_path, O_WRONLY | O_NONBLOCK);
 	if (fd < 0) {
-		/* it is normal for this open to fail ENXIO when there is no
-		 * monitor running, so we don't log it
+		/* It is normal for this open() to fail with ENXIO when there is
+		 * no monitor running, so we don't log it.
 		 */
+		if (errno == ENXIO)
+			return;
+
+		WARN("Failed to open fifo to send message: %s.", strerror(errno));
 		return;
 	}
 
@@ -115,34 +120,33 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
 	ret = write(fd, msg, sizeof(*msg));
 	if (ret != sizeof(*msg)) {
 		close(fd);
-		SYSERROR("failed to write monitor fifo %s", fifo_path);
+		SYSERROR("Failed to write to monitor fifo \"%s\".", fifo_path);
 		return;
 	}
 
 	close(fd);
 }
 
-void lxc_monitor_send_state(const char *name, lxc_state_t state, const char *lxcpath)
+void lxc_monitor_send_state(const char *name, lxc_state_t state,
+			    const char *lxcpath)
 {
-	struct lxc_msg msg = { .type = lxc_msg_state,
-			       .value = state };
+	struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
 	strncpy(msg.name, name, sizeof(msg.name));
 	msg.name[sizeof(msg.name) - 1] = 0;
 
 	lxc_monitor_fifo_send(&msg, lxcpath);
 }
 
-void lxc_monitor_send_exit_code(const char *name, int exit_code, const char *lxcpath)
+void lxc_monitor_send_exit_code(const char *name, int exit_code,
+				const char *lxcpath)
 {
-	struct lxc_msg msg = { .type = lxc_msg_exit_code,
-			       .value = exit_code };
+	struct lxc_msg msg = {.type = lxc_msg_exit_code, .value = exit_code};
 	strncpy(msg.name, name, sizeof(msg.name));
 	msg.name[sizeof(msg.name) - 1] = 0;
 
 	lxc_monitor_fifo_send(&msg, lxcpath);
 }
 
-
 /* routines used by monitor subscribers (lxc-monitor) */
 int lxc_monitor_close(int fd)
 {
@@ -152,20 +156,22 @@ int lxc_monitor_close(int fd)
 int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) {
 	size_t len;
 	int ret;
-	char *sockname = &addr->sun_path[1];
+	char *sockname;
 	char *path;
 	uint64_t hash;
 
 	/* addr.sun_path is only 108 bytes, so we hash the full name and
 	 * then append as much of the name as we can fit.
 	 */
+	sockname = &addr->sun_path[1];
 	memset(addr, 0, sizeof(*addr));
 	addr->sun_family = AF_UNIX;
+
 	len = strlen(lxcpath) + 18;
 	path = alloca(len);
 	ret = snprintf(path, len, "lxc/%s/monitor-sock", lxcpath);
-	if (ret < 0 || ret >= len) {
-		ERROR("memory error creating monitor path");
+	if (ret < 0 || (size_t)ret >= len) {
+		ERROR("Failed to create path for monitor.");
 		return -1;
 	}
 
@@ -174,24 +180,27 @@ int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) {
 	ret = snprintf(sockname, len, "lxc/%016" PRIx64 "/%s", hash, lxcpath);
 	if (ret < 0)
 		return -1;
+
 	sockname[sizeof(addr->sun_path)-3] = '\0';
-	INFO("using monitor sock name %s", sockname);
+	INFO("Using monitor socket name \"%s\".", sockname);
+
 	return 0;
 }
 
 int lxc_monitor_open(const char *lxcpath)
 {
 	struct sockaddr_un addr;
-	int fd,ret = 0;
-	int retry,backoff_ms[] = {10, 50, 100};
+	int fd;
+	size_t retry;
 	size_t len;
+	int ret = 0, backoff_ms[] = {10, 50, 100};
 
 	if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
 		return -1;
 
 	fd = socket(PF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0) {
-		ERROR("socket : %s", strerror(errno));
+		ERROR("Failed to create socket: %s.", strerror(errno));
 		return -1;
 	}
 
@@ -199,23 +208,25 @@ int lxc_monitor_open(const char *lxcpath)
 	if (len >= sizeof(addr.sun_path) - 1) {
 		ret = -1;
 		errno = ENAMETOOLONG;
-		goto err1;
+		goto on_error;
 	}
 
-	for (retry = 0; retry < sizeof(backoff_ms)/sizeof(backoff_ms[0]); retry++) {
+	for (retry = 0; retry < sizeof(backoff_ms) / sizeof(backoff_ms[0]); retry++) {
 		ret = connect(fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len);
 		if (ret == 0 || errno != ECONNREFUSED)
 			break;
-		ERROR("connect : backing off %d", backoff_ms[retry]);
+		ERROR("Failed to connect to monitor socket. Retrying in %d ms.", backoff_ms[retry]);
 		usleep(backoff_ms[retry] * 1000);
 	}
 
 	if (ret < 0) {
-		ERROR("connect : %s", strerror(errno));
-		goto err1;
+		ERROR("Failed to connect to monitor socket: %s.", strerror(errno));
+		goto on_error;
 	}
+
 	return fd;
-err1:
+
+on_error:
 	close(fd);
 	return ret;
 }
@@ -232,22 +243,23 @@ int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
 	else if (ret == 0)
 		return -2;  // timed out
 
-	/* only read from the first ready fd, the others will remain ready
-	 * for when this routine is called again
+	/* Only read from the first ready fd, the others will remain ready for
+	 * when this routine is called again.
 	 */
 	for (i = 0; i < nfds; i++) {
 		if (fds[i].revents != 0) {
 			fds[i].revents = 0;
 			ret = recv(fds[i].fd, msg, sizeof(*msg), 0);
 			if (ret <= 0) {
-				SYSERROR("client failed to recv (monitord died?) %s",
-					 strerror(errno));
+				SYSERROR("Failed to receive message. Did monitord die?: %s.", strerror(errno));
 				return -1;
 			}
 			return ret;
 		}
 	}
-	SYSERROR("no ready fd found?");
+
+	SYSERROR("No ready fd found.");
+
 	return -1;
 }
 
@@ -267,72 +279,81 @@ int lxc_monitor_read(int fd, struct lxc_msg *msg)
 	return lxc_monitor_read_timeout(fd, msg, -1);
 }
 
-
 #define LXC_MONITORD_PATH LIBEXECDIR "/lxc/lxc-monitord"
 
-/* used to spawn a monitord either on startup of a daemon container, or when
- * lxc-monitor starts
+/* Used to spawn a monitord either on startup of a daemon container, or when
+ * lxc-monitor starts.
  */
 int lxc_monitord_spawn(const char *lxcpath)
 {
-	pid_t pid1,pid2;
+	pid_t pid1, pid2;
 	int pipefd[2];
 	char pipefd_str[11];
 
-	char * const args[] = {
-		LXC_MONITORD_PATH,
-		(char *)lxcpath,
-		pipefd_str,
-		NULL,
+	char *const args[] = {
+	    LXC_MONITORD_PATH,
+	    (char *)lxcpath,
+	    pipefd_str,
+	    NULL,
 	};
 
 	/* double fork to avoid zombies when monitord exits */
 	pid1 = fork();
 	if (pid1 < 0) {
-		SYSERROR("failed to fork");
+		SYSERROR("Failed to fork().");
 		return -1;
 	}
 
 	if (pid1) {
+		DEBUG("Going to wait for pid %d.", pid1);
 		if (waitpid(pid1, NULL, 0) != pid1)
 			return -1;
 		return 0;
 	}
 
 	if (pipe(pipefd) < 0) {
-		SYSERROR("failed to create pipe");
+		SYSERROR("Failed to create pipe.");
 		exit(EXIT_FAILURE);
 	}
 
 	pid2 = fork();
 	if (pid2 < 0) {
-		SYSERROR("failed to fork");
+		SYSERROR("Failed to fork().");
 		exit(EXIT_FAILURE);
 	}
+
 	if (pid2) {
 		char c;
-		/* wait for daemon to create socket */
+		/* Wait for daemon to create socket. */
 		close(pipefd[1]);
-		/* sync with child, we're ignoring the return from read
+
+		/* Sync with child, we're ignoring the return from read
 		 * because regardless if it works or not, either way we've
 		 * synced with the child process. the if-empty-statement
 		 * construct is to quiet the warn-unused-result warning.
 		 */
 		if (read(pipefd[0], &c, 1))
 			;
+
 		close(pipefd[0]);
+
 		exit(EXIT_SUCCESS);
 	}
 
 	if (setsid() < 0) {
-		SYSERROR("failed to setsid");
+		SYSERROR("Failed to setsid().");
 		exit(EXIT_FAILURE);
 	}
+
 	lxc_check_inherited(NULL, true, pipefd[1]);
 	if (null_stdfds() < 0)
 		exit(EXIT_FAILURE);
+
 	close(pipefd[0]);
+
 	sprintf(pipefd_str, "%d", pipefd[1]);
+
 	execvp(args[0], args);
+
 	exit(EXIT_FAILURE);
 }

From 8ee3d943c3fc79185ab396c740ea305a94687616 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 05:28:58 +0100
Subject: [PATCH 286/334] monitor: log which pipe fd is currently used

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/monitor.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c
index fab6f55..1afaa5a 100644
--- a/src/lxc/monitor.c
+++ b/src/lxc/monitor.c
@@ -284,11 +284,13 @@ int lxc_monitor_read(int fd, struct lxc_msg *msg)
 /* Used to spawn a monitord either on startup of a daemon container, or when
  * lxc-monitor starts.
  */
+#define __INT_LEN 21
 int lxc_monitord_spawn(const char *lxcpath)
 {
-	pid_t pid1, pid2;
+	int ret;
 	int pipefd[2];
-	char pipefd_str[11];
+	char pipefd_str[__INT_LEN];
+	pid_t pid1, pid2;
 
 	char *const args[] = {
 	    LXC_MONITORD_PATH,
@@ -308,6 +310,7 @@ int lxc_monitord_spawn(const char *lxcpath)
 		DEBUG("Going to wait for pid %d.", pid1);
 		if (waitpid(pid1, NULL, 0) != pid1)
 			return -1;
+		DEBUG("Finished waiting on pid %d.", pid1);
 		return 0;
 	}
 
@@ -351,7 +354,11 @@ int lxc_monitord_spawn(const char *lxcpath)
 
 	close(pipefd[0]);
 
-	sprintf(pipefd_str, "%d", pipefd[1]);
+	ret = snprintf(pipefd_str, __INT_LEN, "%d", pipefd[1]);
+	if (ret < 0 || ret >= __INT_LEN)
+		exit(EXIT_FAILURE);
+
+	DEBUG("Using pipe file descriptor %d for monitord.", pipefd[1]);
 
 	execvp(args[0], args);
 

From 1b0c6b3cea6b7bcf533b8d84f06631fba61491b0 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge at hallyn.com>
Date: Sat, 26 Nov 2016 00:07:15 -0600
Subject: [PATCH 287/334] lvm: supress warnings about leaked files

Closes #1283

Signed-off-by: Serge Hallyn <serge at hallyn.com>
---
 src/lxc/bdev/lxclvm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/lxc/bdev/lxclvm.c b/src/lxc/bdev/lxclvm.c
index 3d41b10..db0e21c 100644
--- a/src/lxc/bdev/lxclvm.c
+++ b/src/lxc/bdev/lxclvm.c
@@ -105,6 +105,7 @@ extern char *dir_new_path(char *src, const char *oldname, const char *name,
 			tp = NULL;
 	}
 
+	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
 	if (!tp)
 	    execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
 	else
@@ -256,6 +257,7 @@ int lvm_snapshot(const char *orig, const char *path, uint64_t size)
 		return -1;
 	}
 
+	(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
 	if (!ret) {
 		ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL);
 	} else {
@@ -356,6 +358,7 @@ int lvm_destroy(struct bdev *orig)
 	if ((pid = fork()) < 0)
 		return -1;
 	if (!pid) {
+		(void)setenv("LVM_SUPPRESS_FD_WARNINGS", "1", 1);
 		execlp("lvremove", "lvremove", "-f", orig->src, (char *)NULL);
 		exit(EXIT_FAILURE);
 	}

From 047fbbf56cfc3db61879c72c1dfffe64f68f0399 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 07:07:25 +0100
Subject: [PATCH 288/334] configure: remove -Werror=vla

Because we include a header that uses a vla (/me scoffs at header).

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 5a6b084..2c0d9d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -655,7 +655,7 @@ LXC_CHECK_TLS
 if test "x$GCC" = "xyes"; then
 	CFLAGS="$CFLAGS -Wall"
 	if test "x$enable_werror" = "xyes"; then
-		CFLAGS="$CFLAGS -Werror -Werror=vla"
+		CFLAGS="$CFLAGS -Werror"
 	fi
 fi
 

From 8a76c27097d26f4457ea8e4e7e7b724ab44e4082 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 07:40:59 +0100
Subject: [PATCH 289/334] monitor: add more logging

Execing lxc-monitord is quite a crucial step so let's be very obsessive about
logging possible errors to guide us in debugging.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/monitor.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c
index 1afaa5a..793fbde 100644
--- a/src/lxc/monitor.c
+++ b/src/lxc/monitor.c
@@ -349,18 +349,23 @@ int lxc_monitord_spawn(const char *lxcpath)
 	}
 
 	lxc_check_inherited(NULL, true, pipefd[1]);
-	if (null_stdfds() < 0)
+	if (null_stdfds() < 0) {
+		SYSERROR("Failed to dup2() standard file descriptors to /dev/null.");
 		exit(EXIT_FAILURE);
+	}
 
 	close(pipefd[0]);
 
 	ret = snprintf(pipefd_str, __INT_LEN, "%d", pipefd[1]);
-	if (ret < 0 || ret >= __INT_LEN)
+	if (ret < 0 || ret >= __INT_LEN) {
+		ERROR("Failed to create pid argument to pass to monitord.");
 		exit(EXIT_FAILURE);
+	}
 
 	DEBUG("Using pipe file descriptor %d for monitord.", pipefd[1]);
 
 	execvp(args[0], args);
+	ERROR("Failed to exec lxc-monitord.");
 
 	exit(EXIT_FAILURE);
 }

From 0ecc9191be519f5b978dc17b4c55228bf9882da8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 09:16:25 +0100
Subject: [PATCH 290/334] commands: improve logging

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 90 ++++++++++++++++++++++++++----------------------------
 1 file changed, 44 insertions(+), 46 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index a807da3..b17879b 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -168,8 +168,8 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
 
 	ret = lxc_abstract_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
 	if (ret < 0) {
-		WARN("command %s failed to receive response",
-		     lxc_cmd_str(cmd->req.cmd));
+		WARN("Command %s failed to receive response: %s.",
+		     lxc_cmd_str(cmd->req.cmd), strerror(errno));
 		return -1;
 	}
 
@@ -184,7 +184,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
 
 		rspdata = malloc(sizeof(*rspdata));
 		if (!rspdata) {
-			ERROR("command %s couldn't allocate response buffer",
+			ERROR("Command %s couldn't allocate response buffer.",
 			      lxc_cmd_str(cmd->req.cmd));
 			return -1;
 		}
@@ -196,7 +196,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
 	if (rsp->datalen == 0)
 		return ret;
 	if (rsp->datalen > LXC_CMD_DATA_MAX) {
-		ERROR("command %s response data %d too long",
+		ERROR("Command %s response data %d too long.",
 		      lxc_cmd_str(cmd->req.cmd), rsp->datalen);
 		errno = EFBIG;
 		return -1;
@@ -204,14 +204,14 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
 
 	rsp->data = malloc(rsp->datalen);
 	if (!rsp->data) {
-		ERROR("command %s unable to allocate response buffer",
+		ERROR("Command %s was unable to allocate response buffer.",
 		      lxc_cmd_str(cmd->req.cmd));
 		return -1;
 	}
 	ret = recv(sock, rsp->data, rsp->datalen, 0);
 	if (ret != rsp->datalen) {
-		ERROR("command %s failed to receive response data",
-		      lxc_cmd_str(cmd->req.cmd));
+		ERROR("Command %s failed to receive response data: %s.",
+		      lxc_cmd_str(cmd->req.cmd), strerror(errno));
 		if (ret >= 0)
 			ret = -1;
 	}
@@ -233,7 +233,7 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
 
 	ret = send(fd, rsp, sizeof(*rsp), 0);
 	if (ret != sizeof(*rsp)) {
-		ERROR("failed to send command response %d %s", ret,
+		ERROR("Failed to send command response %d: %s.", ret,
 		      strerror(errno));
 		return -1;
 	}
@@ -241,8 +241,8 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
 	if (rsp->datalen > 0) {
 		ret = send(fd, rsp->data, rsp->datalen, 0);
 		if (ret != rsp->datalen) {
-			WARN("failed to send command response data %d %s", ret,
-			      strerror(errno));
+			WARN("Failed to send command response data %d: %s.",
+			     ret, strerror(errno));
 			return -1;
 		}
 	}
@@ -293,7 +293,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
 		if (errno == ECONNREFUSED)
 			*stopped = 1;
 		else
-			SYSERROR("command %s failed to connect to '@%s'",
+			SYSERROR("Command %s failed to connect to \"@%s\".",
 				 lxc_cmd_str(cmd->req.cmd), offset);
 		return -1;
 	}
@@ -302,7 +302,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
 	if (ret != sizeof(cmd->req)) {
 		if (errno == EPIPE)
 			goto epipe;
-		SYSERROR("command %s failed to send req to '@%s' %d",
+		SYSERROR("Command %s failed to send req to \"@%s\" %d.",
 			 lxc_cmd_str(cmd->req.cmd), offset, ret);
 		if (ret >=0)
 			ret = -1;
@@ -314,7 +314,7 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
 		if (ret != cmd->req.datalen) {
 			if (errno == EPIPE)
 				goto epipe;
-			SYSERROR("command %s failed to send request data to '@%s' %d",
+			SYSERROR("Command %s failed to send request data to \"@%s\" %d.",
 				 lxc_cmd_str(cmd->req.cmd), offset, ret);
 			if (ret >=0)
 				ret = -1;
@@ -458,14 +458,13 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
 		return NULL;
 
 	if (!ret) {
-		WARN("'%s' has stopped before sending its state", name);
+		WARN("Container \"%s\" has stopped before sending its state.", name);
 		return NULL;
 	}
 
 	if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0) {
-		ERROR("command %s failed for '%s': %s",
-		      lxc_cmd_str(cmd.req.cmd), name,
-		      strerror(-cmd.rsp.ret));
+		ERROR("Command %s failed for container \"%s\": %s.",
+		      lxc_cmd_str(cmd.req.cmd), name, strerror(-cmd.rsp.ret));
 		return NULL;
 	}
 
@@ -571,11 +570,11 @@ lxc_state_t lxc_cmd_get_state(const char *name, const char *lxcpath)
 		return -1;
 
 	if (!ret) {
-		WARN("'%s' has stopped before sending its state", name);
+		WARN("Container \"%s\" has stopped before sending its state.", name);
 		return -1;
 	}
 
-	DEBUG("'%s' is in '%s' state", name,
+	DEBUG("Container \"%s\" is in \"%s\" state.", name,
 	      lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
 	return PTR_TO_INT(cmd.rsp.data);
 }
@@ -607,7 +606,7 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
 	ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
 	if (ret < 0) {
 		if (stopped) {
-			INFO("'%s' is already stopped", name);
+			INFO("Container \"%s\" is already stopped.", name);
 			return 0;
 		}
 		return -1;
@@ -617,11 +616,12 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
 	 * closed
 	 */
 	if (ret > 0) {
-		ERROR("failed to stop '%s': %s", name, strerror(-cmd.rsp.ret));
+		ERROR("Failed to stop container \"%s\": %s.", name,
+		      strerror(-cmd.rsp.ret));
 		return -1;
 	}
 
-	INFO("'%s' has stopped", name);
+	INFO("Container \"%s\" has stopped.", name);
 	return 0;
 }
 
@@ -643,7 +643,7 @@ static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
 		 */
 		if (cgroup_unfreeze(handler))
 			return 0;
-		ERROR("Failed to unfreeze %s:%s", handler->lxcpath, handler->name);
+		ERROR("Failed to unfreeze container \"%s\".", handler->name);
 		rsp.ret = -1;
 	}
 
@@ -705,27 +705,27 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
 		return ret;
 
 	if (cmd.rsp.ret < 0) {
-		ERROR("console access denied: %s", strerror(-cmd.rsp.ret));
+		ERROR("Console access denied: %s.", strerror(-cmd.rsp.ret));
 		ret = -1;
 		goto out;
 	}
 
 	if (ret == 0) {
-		ERROR("console %d invalid,busy or all consoles busy", *ttynum);
+		ERROR("Console %d invalid, busy or all consoles busy.", *ttynum);
 		ret = -1;
 		goto out;
 	}
 
 	rspdata = cmd.rsp.data;
 	if (rspdata->masterfd < 0) {
-		ERROR("unable to allocate fd for tty %d", rspdata->ttynum);
+		ERROR("Unable to allocate fd for tty %d.", rspdata->ttynum);
 		goto out;
 	}
 
 	ret = cmd.rsp.ret;	/* sock fd */
 	*fd = rspdata->masterfd;
 	*ttynum = rspdata->ttynum;
-	INFO("tty %d allocated fd %d sock %d", rspdata->ttynum, *fd, ret);
+	INFO("tty %d allocated fd %d sock %d.", rspdata->ttynum, *fd, ret);
 out:
 	free(cmd.rsp.data);
 	return ret;
@@ -745,7 +745,7 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
 	memset(&rsp, 0, sizeof(rsp));
 	rsp.data = INT_TO_PTR(ttynum);
 	if (lxc_abstract_unix_send_fd(fd, masterfd, &rsp, sizeof(rsp)) < 0) {
-		ERROR("failed to send tty to client");
+		ERROR("Failed to send tty to client.");
 		lxc_console_free(handler->conf, fd);
 		goto out_close;
 	}
@@ -854,7 +854,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
 	};
 
 	if (req->cmd >= LXC_CMD_MAX) {
-		ERROR("bad cmd %d received", req->cmd);
+		ERROR("Undefined command id %d received.", req->cmd);
 		return -1;
 	}
 	return cb[req->cmd](fd, req, handler);
@@ -885,23 +885,23 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
 	}
 
 	if (ret < 0) {
-		SYSERROR("failed to receive data on command socket");
+		SYSERROR("Failed to receive data on command socket.");
 		goto out_close;
 	}
 
 	if (!ret) {
-		DEBUG("peer has disconnected");
+		DEBUG("Peer has disconnected.");
 		goto out_close;
 	}
 
 	if (ret != sizeof(req)) {
-		WARN("partial request, ignored");
+		WARN("Failed to receive full command request. Ignoring request.");
 		ret = -1;
 		goto out_close;
 	}
 
 	if (req.datalen > LXC_CMD_DATA_MAX) {
-		ERROR("cmd data length %d too large", req.datalen);
+		ERROR("Received command data length %d is too large.", req.datalen);
 		ret = -1;
 		goto out_close;
 	}
@@ -912,7 +912,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
 		reqdata = alloca(req.datalen);
 		ret = recv(fd, reqdata, req.datalen, 0);
 		if (ret != req.datalen) {
-			WARN("partial request, ignored");
+			WARN("Failed to receive full command request. Ignoring request.");
 			ret = -1;
 			goto out_close;
 		}
@@ -940,24 +940,24 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
 
 	connection = accept(fd, NULL, 0);
 	if (connection < 0) {
-		SYSERROR("failed to accept connection");
+		SYSERROR("Failed to accept connection to run command.");
 		return -1;
 	}
 
 	if (fcntl(connection, F_SETFD, FD_CLOEXEC)) {
-		SYSERROR("failed to set close-on-exec on incoming connection");
+		SYSERROR("Failed to set close-on-exec on incoming command connection.");
 		goto out_close;
 	}
 
 	if (setsockopt(connection, SOL_SOCKET,
 		       SO_PASSCRED, &opt, sizeof(opt))) {
-		SYSERROR("failed to enable credential on socket");
+		SYSERROR("Failed to enable necessary credentials on command socket.");
 		goto out_close;
 	}
 
 	ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
 	if (ret) {
-		ERROR("failed to add handler");
+		ERROR("Failed to add command handler.");
 		goto out_close;
 	}
 
@@ -988,17 +988,15 @@ int lxc_cmd_init(const char *name, struct lxc_handler *handler,
 
 	fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
 	if (fd < 0) {
-		ERROR("failed (%d) to create the command service point %s", errno, offset);
-		if (errno == EADDRINUSE) {
-			ERROR("##");
-			ERROR("# The container appears to be already running!");
-			ERROR("##");
-		}
+		ERROR("Failed to create the command service point %s: %s.",
+		      offset, strerror(errno));
+		if (errno == EADDRINUSE)
+			ERROR("Container \"%s\" appears to be already running!", name);
 		return -1;
 	}
 
 	if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
-		SYSERROR("failed to set sigfd to close-on-exec");
+		SYSERROR("Failed to set FD_CLOEXEC on signal file descriptor.");
 		close(fd);
 		return -1;
 	}
@@ -1015,7 +1013,7 @@ int lxc_cmd_mainloop_add(const char *name,
 
 	ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
 	if (ret) {
-		ERROR("failed to add handler for command socket");
+		ERROR("Failed to add handler for command socket.");
 		close(fd);
 	}
 

From 7c51e617c9bee01b8b6e73e217edd549c8dc5bab Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 26 Nov 2016 19:39:44 +0100
Subject: [PATCH 291/334] lxc_monitord: improve log + set log level to DEBUG

Setting loglevel to DEBUG will allow us to retrieve more useful information in
case something goes wrong. The total size of the log will not increase
significantly.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/lxc_monitord.c | 103 ++++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 53 deletions(-)

diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
index 61c8411..2500571 100644
--- a/src/lxc/lxc_monitord.c
+++ b/src/lxc/lxc_monitord.c
@@ -22,21 +22,21 @@
  */
 
 #define _GNU_SOURCE
-#include <stdio.h>
-#include <signal.h>
 #include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
 #include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <netinet/in.h>
 #include <sys/epoll.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/un.h>
-#include <netinet/in.h>
-#include <net/if.h>
 
 #include "af_unix.h"
 #include "log.h"
@@ -85,14 +85,14 @@ static int lxc_monitord_fifo_create(struct lxc_monitor *mon)
 
 	ret = mknod(fifo_path, S_IFIFO|S_IRUSR|S_IWUSR, 0);
 	if (ret < 0 && errno != EEXIST) {
-		INFO("failed to mknod monitor fifo %s %s", fifo_path, strerror(errno));
+		INFO("Failed to mknod monitor fifo %s: %s.", fifo_path, strerror(errno));
 		return -1;
 	}
 
 	mon->fifofd = open(fifo_path, O_RDWR);
 	if (mon->fifofd < 0) {
 		unlink(fifo_path);
-		ERROR("failed to open monitor fifo");
+		ERROR("Failed to open monitor fifo.");
 		return -1;
 	}
 
@@ -102,7 +102,7 @@ static int lxc_monitord_fifo_create(struct lxc_monitor *mon)
 	lk.l_len = 0;
 	if (fcntl(mon->fifofd, F_SETLK, &lk) != 0) {
 		/* another lxc-monitord is already running, don't start up */
-		DEBUG("lxc-monitord already running on lxcpath %s", mon->lxcpath);
+		DEBUG("lxc-monitord already running on lxcpath %s.", mon->lxcpath);
 		close(mon->fifofd);
 		return -1;
 	}
@@ -126,7 +126,7 @@ static void lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd) {
 	int i;
 
 	if (lxc_mainloop_del_handler(&mon->descr, fd))
-		CRIT("fd:%d not found in mainloop", fd);
+		CRIT("File descriptor %d not found in mainloop.", fd);
 	close(fd);
 
 	for (i = 0; i < mon->clientfds_cnt; i++) {
@@ -134,7 +134,7 @@ static void lxc_monitord_sockfd_remove(struct lxc_monitor *mon, int fd) {
 			break;
 	}
 	if (i >= mon->clientfds_cnt) {
-		CRIT("fd:%d not found in clients array", fd);
+		CRIT("File descriptor %d not found in clients array.", fd);
 		lxc_monitord_cleanup();
 		exit(EXIT_FAILURE);
 	}
@@ -174,35 +174,34 @@ static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data,
 	ret = -1;
 	clientfd = accept(fd, NULL, 0);
 	if (clientfd < 0) {
-		SYSERROR("failed to accept connection");
+		SYSERROR("Failed to accept connection for client file descriptor %d.", fd);
 		goto out;
 	}
 
 	if (fcntl(clientfd, F_SETFD, FD_CLOEXEC)) {
-		SYSERROR("failed to set close-on-exec on incoming connection");
+		SYSERROR("Failed to set FD_CLOEXEC on client socket connection %d.", clientfd);
 		goto err1;
 	}
 
 	if (getsockopt(clientfd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz))
 	{
-		ERROR("failed to get credentials on socket");
+		ERROR("Failed to get credentials on client socket connection %d.", clientfd);
 		goto err1;
 	}
 	if (cred.uid && cred.uid != geteuid()) {
-		WARN("monitor denied for uid:%d", cred.uid);
+		WARN("Monitor denied for uid %d on client socket connection %d.", cred.uid, clientfd);
 		ret = -EACCES;
 		goto err1;
 	}
 
 	if (mon->clientfds_cnt + 1 > mon->clientfds_size) {
 		int *clientfds;
-		DEBUG("realloc space for %d clientfds",
-		      mon->clientfds_size + CLIENTFDS_CHUNK);
 		clientfds = realloc(mon->clientfds,
-				    (mon->clientfds_size + CLIENTFDS_CHUNK) *
-				     sizeof(mon->clientfds[0]));
+				    (mon->clientfds_size + CLIENTFDS_CHUNK) * sizeof(mon->clientfds[0]));
 		if (clientfds == NULL) {
-			ERROR("failed to realloc memory for clientfds");
+			ERROR("Failed to realloc memory for %d client file "
+			      "descriptors.",
+			      mon->clientfds_size + CLIENTFDS_CHUNK);
 			goto err1;
 		}
 		mon->clientfds = clientfds;
@@ -212,12 +211,12 @@ static int lxc_monitord_sock_accept(int fd, uint32_t events, void *data,
 	ret = lxc_mainloop_add_handler(&mon->descr, clientfd,
 				       lxc_monitord_sock_handler, mon);
 	if (ret) {
-		ERROR("failed to add socket handler");
+		ERROR("Failed to add socket handler.");
 		goto err1;
 	}
 
 	mon->clientfds[mon->clientfds_cnt++] = clientfd;
-	INFO("accepted client fd:%d clients:%d", clientfd, mon->clientfds_cnt);
+	INFO("Accepted client file descriptor %d. Number of accepted file descriptors is now %d.", clientfd, mon->clientfds_cnt);
 	goto out;
 
 err1:
@@ -236,7 +235,7 @@ static int lxc_monitord_sock_create(struct lxc_monitor *mon)
 
 	fd = lxc_abstract_unix_open(addr.sun_path, SOCK_STREAM, O_TRUNC);
 	if (fd < 0) {
-		ERROR("failed to open unix socket : %s", strerror(errno));
+		ERROR("Failed to open unix socket: %s.", strerror(errno));
 		return -1;
 	}
 
@@ -295,17 +294,15 @@ static int lxc_monitord_fifo_handler(int fd, uint32_t events, void *data,
 
 	ret = read(fd, &msglxc, sizeof(msglxc));
 	if (ret != sizeof(msglxc)) {
-		SYSERROR("read fifo failed : %s", strerror(errno));
+		SYSERROR("Reading from fifo failed: %s.", strerror(errno));
 		return 1;
 	}
 
 	for (i = 0; i < mon->clientfds_cnt; i++) {
-		DEBUG("writing client fd:%d", mon->clientfds[i]);
 		ret = write(mon->clientfds[i], &msglxc, sizeof(msglxc));
-		if (ret < 0) {
-			ERROR("write failed to client sock:%d %d %s",
-			      mon->clientfds[i], errno, strerror(errno));
-		}
+		if (ret < 0)
+			ERROR("Failed to send message to client file descriptor %d: %s.",
+			      mon->clientfds[i], strerror(errno));
 	}
 
 	return 0;
@@ -318,14 +315,14 @@ static int lxc_monitord_mainloop_add(struct lxc_monitor *mon)
 	ret = lxc_mainloop_add_handler(&mon->descr, mon->fifofd,
 				       lxc_monitord_fifo_handler, mon);
 	if (ret < 0) {
-		ERROR("failed to add to mainloop monitor handler for fifo");
+		ERROR("Failed to add to mainloop monitor handler for fifo.");
 		return -1;
 	}
 
 	ret = lxc_mainloop_add_handler(&mon->descr, mon->listenfd,
 				       lxc_monitord_sock_accept, mon);
 	if (ret < 0) {
-		ERROR("failed to add to mainloop monitor handler for listen socket");
+		ERROR("Failed to add to mainloop monitor handler for listen socket.");
 		return -1;
 	}
 
@@ -339,17 +336,17 @@ static void lxc_monitord_cleanup(void)
 
 static void lxc_monitord_sig_handler(int sig)
 {
-	INFO("caught signal %d", sig);
+	INFO("Caught signal %d.", sig);
 	lxc_monitord_cleanup();
 	exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
 {
-	int ret,pipefd;
-	char *lxcpath = argv[1];
+	int ret, pipefd;
 	char logpath[PATH_MAX];
 	sigset_t mask;
+	char *lxcpath = argv[1];
 
 	if (argc != 3) {
 		fprintf(stderr,
@@ -360,13 +357,13 @@ int main(int argc, char *argv[])
 	}
 
 	ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log",
-		       (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH ) );
+		       (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH ));
 	if (ret < 0 || ret >= sizeof(logpath))
 		exit(EXIT_FAILURE);
 
-	ret = lxc_log_init(NULL, logpath, "NOTICE", "lxc-monitord", 0, lxcpath);
+	ret = lxc_log_init(NULL, logpath, "DEBUG", "lxc-monitord", 0, lxcpath);
 	if (ret)
-		INFO("Failed to open log file %s, log will be lost", lxcpath);
+		INFO("Failed to open log file %s, log will be lost.", lxcpath);
 	lxc_log_options_no_override();
 
 	if (lxc_safe_int(argv[2], &pipefd) < 0)
@@ -378,7 +375,7 @@ int main(int argc, char *argv[])
 	    sigdelset(&mask, SIGBUS)  ||
 	    sigdelset(&mask, SIGTERM) ||
 	    sigprocmask(SIG_BLOCK, &mask, NULL)) {
-		SYSERROR("failed to set signal mask");
+		SYSERROR("Failed to set signal mask.");
 		exit(EXIT_FAILURE);
 	}
 
@@ -391,12 +388,12 @@ int main(int argc, char *argv[])
 	memset(&mon, 0, sizeof(mon));
 	mon.lxcpath = lxcpath;
 	if (lxc_mainloop_open(&mon.descr)) {
-		ERROR("failed to create mainloop");
-		goto out;
+		ERROR("Failed to create mainloop.");
+		goto on_error;
 	}
 
 	if (lxc_monitord_create(&mon)) {
-		goto out;
+		goto on_error;
 	}
 
 	/* sync with parent, we're ignoring the return from write
@@ -410,16 +407,16 @@ int main(int argc, char *argv[])
 	close(pipefd);
 
 	if (lxc_monitord_mainloop_add(&mon)) {
-		ERROR("failed to add mainloop handlers");
-		goto out;
+		ERROR("Failed to add mainloop handlers.");
+		goto on_error;
 	}
 
-	NOTICE("pid:%d monitoring lxcpath %s", getpid(), mon.lxcpath);
-	for(;;) {
+	NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s.",
+	       getpid(), mon.lxcpath);
+	for (;;) {
 		ret = lxc_mainloop(&mon.descr, 1000 * 30);
-		if (mon.clientfds_cnt <= 0)
-		{
-			NOTICE("no remaining clients, exiting");
+		if (mon.clientfds_cnt <= 0) {
+			NOTICE("No remaining clients. lxc-monitord is exiting.");
 			break;
 		}
 	}
@@ -427,7 +424,7 @@ int main(int argc, char *argv[])
 	lxc_mainloop_close(&mon.descr);
 	lxc_monitord_cleanup();
 	ret = EXIT_SUCCESS;
-	NOTICE("monitor exiting");
-out:
+
+on_error:
 	exit(ret);
 }

From 94b5d51b779a2961ae145a3117453f458972407f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 27 Nov 2016 01:43:37 +0100
Subject: [PATCH 292/334] lxc_monitord: make lxc-monitord async signal safe

Before lxc_monitord called lxc_monitord_cleanup() from a signal handler.  This
function calls a bunch of async signal unsafe functions and basically begs for
deadlocks. This commit switches lxc-monitord to using sigsetjmp() and
siglongjmp() in the signal handler to jump to a cleanup label that call
lxc_monitord_cleanup(). In this way, we avoid using async signal unsafe
functions.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/lxc_monitord.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
index 2500571..2fbb357 100644
--- a/src/lxc/lxc_monitord.c
+++ b/src/lxc/lxc_monitord.c
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <net/if.h>
 #include <netinet/in.h>
+#include <setjmp.h>
 #include <sys/epoll.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -48,6 +49,8 @@
 
 lxc_log_define(lxc_monitord, lxc);
 
+sigjmp_buf mark;
+
 static void lxc_monitord_cleanup(void);
 
 /*
@@ -336,9 +339,7 @@ static void lxc_monitord_cleanup(void)
 
 static void lxc_monitord_sig_handler(int sig)
 {
-	INFO("Caught signal %d.", sig);
-	lxc_monitord_cleanup();
-	exit(EXIT_SUCCESS);
+	siglongjmp(mark, 1);
 }
 
 int main(int argc, char *argv[])
@@ -384,6 +385,9 @@ int main(int argc, char *argv[])
 	signal(SIGBUS,  lxc_monitord_sig_handler);
 	signal(SIGTERM, lxc_monitord_sig_handler);
 
+	if (sigsetjmp(mark, 1) != 0)
+		goto on_signal;
+
 	ret = EXIT_FAILURE;
 	memset(&mon, 0, sizeof(mon));
 	mon.lxcpath = lxcpath;
@@ -427,4 +431,8 @@ int main(int argc, char *argv[])
 
 on_error:
 	exit(ret);
+
+on_signal:
+	lxc_monitord_cleanup();
+	exit(EXIT_SUCCESS);
 }

From f6e8a2918e9cc551df80364b1e5cfd4ce10a4eab Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 27 Nov 2016 04:44:06 +0100
Subject: [PATCH 293/334] conf: remove thread-unsafe strsignal + improve log

The thread-unsafe functions strsignal() is called in run_buffer() which in turn
is called in run_buffer_argv() which is responsible for running __all__ lxc
hooks. This is pretty dangerous for multi-threaded users like LXD.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 52 ++++++++++++++++++++++++++--------------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index f40da30..9bc8770 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -375,32 +375,31 @@ static int run_buffer(char *buffer)
 
 	f = lxc_popen(buffer);
 	if (!f) {
-		SYSERROR("popen failed");
+		SYSERROR("Failed to popen() %s.", buffer);
 		return -1;
 	}
 
 	output = malloc(LXC_LOG_BUFFER_SIZE);
 	if (!output) {
-		ERROR("failed to allocate memory for script output");
+		ERROR("Failed to allocate memory for %s.", buffer);
 		lxc_pclose(f);
 		return -1;
 	}
 
-	while(fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
-		DEBUG("script output: %s", output);
+	while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
+		DEBUG("Script %s with output: %s.", buffer, output);
 
 	free(output);
 
 	ret = lxc_pclose(f);
 	if (ret == -1) {
-		SYSERROR("Script exited on error");
+		SYSERROR("Script exited with error.");
 		return -1;
 	} else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) {
-		ERROR("Script exited with status %d", WEXITSTATUS(ret));
+		ERROR("Script exited with status %d.", WEXITSTATUS(ret));
 		return -1;
 	} else if (WIFSIGNALED(ret)) {
-		ERROR("Script terminated by signal %d (%s)", WTERMSIG(ret),
-		      strsignal(WTERMSIG(ret)));
+		ERROR("Script terminated by signal %d.", WTERMSIG(ret));
 		return -1;
 	}
 
@@ -408,17 +407,17 @@ static int run_buffer(char *buffer)
 }
 
 static int run_script_argv(const char *name, const char *section,
-		      const char *script, const char *hook, const char *lxcpath,
-		      char **argsin)
+			   const char *script, const char *hook,
+			   const char *lxcpath, char **argsin)
 {
 	int ret, i;
 	char *buffer;
 	size_t size = 0;
 
-	INFO("Executing script '%s' for container '%s', config section '%s'",
+	INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".",
 	     script, name, section);
 
-	for (i=0; argsin && argsin[i]; i++)
+	for (i = 0; argsin && argsin[i]; i++)
 		size += strlen(argsin[i]) + 1;
 
 	size += strlen(hook) + 1;
@@ -433,22 +432,23 @@ static int run_script_argv(const char *name, const char *section,
 
 	buffer = alloca(size);
 	if (!buffer) {
-		ERROR("failed to allocate memory");
+		ERROR("Failed to allocate memory.");
 		return -1;
 	}
 
-	ret = snprintf(buffer, size, "%s %s %s %s", script, name, section, hook);
-	if (ret < 0 || ret >= size) {
-		ERROR("Script name too long");
+	ret =
+	    snprintf(buffer, size, "%s %s %s %s", script, name, section, hook);
+	if (ret < 0 || (size_t)ret >= size) {
+		ERROR("Script name too long.");
 		return -1;
 	}
 
-	for (i=0; argsin && argsin[i]; i++) {
-		int len = size-ret;
+	for (i = 0; argsin && argsin[i]; i++) {
+		int len = size - ret;
 		int rc;
 		rc = snprintf(buffer + ret, len, " %s", argsin[i]);
 		if (rc < 0 || rc >= len) {
-			ERROR("Script args too long");
+			ERROR("Script args too long.");
 			return -1;
 		}
 		ret += rc;
@@ -457,15 +457,15 @@ static int run_script_argv(const char *name, const char *section,
 	return run_buffer(buffer);
 }
 
-static int run_script(const char *name, const char *section,
-		      const char *script, ...)
+static int run_script(const char *name, const char *section, const char *script,
+		      ...)
 {
 	int ret;
 	char *buffer, *p;
 	size_t size = 0;
 	va_list ap;
 
-	INFO("Executing script '%s' for container '%s', config section '%s'",
+	INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".",
 	     script, name, section);
 
 	va_start(ap, script);
@@ -483,23 +483,23 @@ static int run_script(const char *name, const char *section,
 
 	buffer = alloca(size);
 	if (!buffer) {
-		ERROR("failed to allocate memory");
+		ERROR("Failed to allocate memory.");
 		return -1;
 	}
 
 	ret = snprintf(buffer, size, "%s %s %s", script, name, section);
 	if (ret < 0 || ret >= size) {
-		ERROR("Script name too long");
+		ERROR("Script name too long.");
 		return -1;
 	}
 
 	va_start(ap, script);
 	while ((p = va_arg(ap, char *))) {
-		int len = size-ret;
+		int len = size - ret;
 		int rc;
 		rc = snprintf(buffer + ret, len, " %s", p);
 		if (rc < 0 || rc >= len) {
-			ERROR("Script args too long");
+			ERROR("Script args too long.");
 			return -1;
 		}
 		ret += rc;

From b101fb9b7ca3c9f1b425e2eb6fe2398832f8dbd9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 27 Nov 2016 06:01:36 +0100
Subject: [PATCH 294/334] lxccontainer: log failure to send sig to init pid

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/lxccontainer.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 3a9e1e3..d96d23e 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1582,8 +1582,10 @@ static bool do_lxcapi_reboot(struct lxc_container *c)
 		return false;
 	if (c->lxc_conf && c->lxc_conf->rebootsignal)
 		rebootsignal = c->lxc_conf->rebootsignal;
-	if (kill(pid, rebootsignal) < 0)
+	if (kill(pid, rebootsignal) < 0) {
+		WARN("Could not send signal %d to pid %d.", rebootsignal, pid);
 		return false;
+	}
 	return true;
 
 }
@@ -1614,7 +1616,9 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 
 	INFO("Using signal number '%d' as halt signal.", haltsignal);
 
-	kill(pid, haltsignal);
+	if (kill(pid, haltsignal) < 0)
+		WARN("Could not send signal %d to pid %d.", haltsignal, pid);
+
 	retv = do_lxcapi_wait(c, "STOPPED", timeout);
 	return retv;
 }

From 03fb1aaaf66aca61eb1340892d9b429dfa455030 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 27 Nov 2016 23:41:06 +0100
Subject: [PATCH 295/334] utils: add macro __LXC_NUMSTRLEN

This macro can be used to set or allocate a string buffer that can hold any
64bit representable number.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/utils.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 0d63bb6..3d1ecee 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -35,6 +35,10 @@
 
 #include "initutils.h"
 
+/* Useful macros */
+/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
+#define __LXC_NUMSTRLEN 21
+
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude);
 extern int get_u16(unsigned short *val, const char *arg, int base);

From 624cec1cf1e69c506144c1b43a755a0b250173d0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 27 Nov 2016 23:42:11 +0100
Subject: [PATCH 296/334] log: drop all timezone conversion functions

Our log functions need to make extra sure that they are thread-safe. We had
some problems with that before. This especially involves time-conversion
functions. I don't want to find any localtime() or gmtime() functions or
relatives in here. Not even localtime_r() or gmtime_r() or relatives. They all
fiddle with global variables and locking in various libcs. They cause deadlocks
when liblxc is used multi-threaded and no matter how smart you think you are,
you __will__ cause trouble using them.
(As a short example how this can cause trouble: LXD uses forkstart to fork off
a new process that runs the container. At the same time the go runtime LXD
relies on does its own multi-threading thing which we can't control. The
fork()ing + threading then seems to mess with the locking states in these time
functions causing deadlocks.)
The current solution is to be good old unix people and use the Epoch as our
reference point and simply use the seconds and nanoseconds that have past since
then. This relies on clock_gettime() which is explicitly marked MT-Safe with no
restrictions! This way, anyone who is really strongly invested in getting the
actual time the log entry was created, can just convert it for themselves. Our
logging is mostly done for debugging purposes so don't try to make it pretty.
Pretty might cost you thread-safety.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 106 +++++++++++++++++++++++++---------------------------------
 src/lxc/log.h |   8 +++--
 2 files changed, 51 insertions(+), 63 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 94a5179..fb86d34 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -40,21 +40,11 @@
 #include "caps.h"
 #include "utils.h"
 
-#define LXC_LOG_DATEFOMAT_SIZE  15
-
-#ifndef HAVE_GETTID
-static inline pid_t gettid(void)
-{
-#ifdef __NR_gettid
-	return (pid_t)syscall(SYS_gettid);
-#else
-	errno = ENOSYS;
-	return -1;
-#endif
-}
-#else
-extern pid_t gettid(void);
-#endif
+/* We're logging in seconds and nanoseconds. Assuming that the underlying
+ * datatype is currently at maximum a 64bit integer, we have a date string that
+ * is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42.
+ */
+#define LXC_LOG_TIME_SIZE  ((__LXC_NUMSTRLEN) * 2)
 
 int lxc_log_fd = -1;
 int lxc_quiet_specified;
@@ -81,15 +71,34 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
 }
 
 /*---------------------------------------------------------------------------*/
+/* This function needs to make extra sure that it is thread-safe. We had some
+ * problems with that before. This especially involves time-conversion
+ * functions. I don't want to find any localtime() or gmtime() functions or
+ * relatives in here. Not even localtime_r() or gmtime_r() or relatives. They
+ * all fiddle with global variables and locking in various libcs. They cause
+ * deadlocks when liblxc is used multi-threaded and no matter how smart you
+ * think you are, you __will__ cause trouble using them.
+ * (As a short example how this can cause trouble: LXD uses forkstart to fork
+ * off a new process that runs the container. At the same time the go runtime
+ * LXD relies on does its own multi-threading thing which we can't controll. The
+ * fork()ing + threading then seems to mess with the locking states in these
+ * time functions causing deadlocks.)
+ * The current solution is to be good old unix people and use the Epoch as our
+ * reference point and simply use the seconds and nanoseconds that have past
+ * since then. This relies on clock_gettime() which is explicitly marked MT-Safe
+ * with no restrictions! This way, anyone who is really strongly invested in
+ * getting the actual time the log entry was created, can just convert it for
+ * themselves. Our logging is mostly done for debugging purposes so don't try
+ * to make it pretty. Pretty might cost you thread-safety.
+ */
 static int log_append_logfile(const struct lxc_log_appender *appender,
 			      struct lxc_log_event *event)
 {
-	char date[LXC_LOG_DATEFOMAT_SIZE] = "N/A";
 	char buffer[LXC_LOG_BUFFER_SIZE];
-	struct tm newtime;
-	int n;
-	int ms = 0;
+	struct timespec zero_timespec = {0};
+	int ret, n;
 	int fd_to_use = -1;
+	char nanosec[__LXC_NUMSTRLEN];
 
 #ifndef NO_LXC_CONF
 	if (!lxc_log_use_global_fd && current_config)
@@ -102,48 +111,23 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	if (fd_to_use == -1)
 		return 0;
 
-	/* localtime_r() can lead to deadlocks when LXC is used multithreaded
-	 * because it calls __tzset() and __tzconvert() internally. The deadlock
-	 * stems from an interaction between these functions and the functions
-	 * in monitor.c and commands.{c,h}. Some of the latter functions will
-	 * write to the log independent of the container thread that is
-	 * currently running. Since the monitor fork()ed it seems to duplicate
-	 * the mutex states of the time functions mentioned above.
-	 * As a short term fix, I suggest to simply disable receiving the time
-	 * when these monitor.c or command.{c,h} functions are called. This
-	 * should be ok, since the [lxc monitor] will only emit a few messages
-	 * and thread-safety is currently more important than beautiful logs.
-	 * The rest of the log stays the same as it was before.
-	 */
-	if (getpid() == gettid()) {
-		if (!localtime_r(&event->timestamp.tv_sec, &newtime))
-			return 0;
-		strftime(date, sizeof(date), "%Y%m%d%H%M%S", &newtime);
-		ms = event->timestamp.tv_usec / 1000;
-		n = snprintf(buffer, sizeof(buffer),
-				"%15s%s%s %14s.%03d %-8s %s - %s:%s:%d - ",
-				log_prefix,
-				log_vmname ? " " : "",
-				log_vmname ? log_vmname : "",
-				date,
-				ms,
-				lxc_log_priority_to_string(event->priority),
-				event->category,
-				event->locinfo->file, event->locinfo->func,
-				event->locinfo->line);
-	} else {
-		n = snprintf(buffer, sizeof(buffer),
-				"%15s%s%s %-14s %3s %-8s %s - %s:%s:%d - ",
-				log_prefix,
-				log_vmname ? " " : "",
-				log_vmname ? log_vmname : "",
-				date,
-				"",
-				lxc_log_priority_to_string(event->priority),
-				event->category,
-				event->locinfo->file, event->locinfo->func,
-				event->locinfo->line);
-	}
+	ret = snprintf(nanosec, __LXC_NUMSTRLEN, "%ld", event->timestamp.tv_nsec);
+	if (ret < 0 || ret >= LXC_LOG_TIME_SIZE)
+		return 0;
+
+	n = snprintf(buffer, sizeof(buffer),
+			"%15s%s%s [ %.0f.%.6s ] %-8s %s - %s:%s:%d - ",
+			log_prefix,
+			log_vmname ? " " : "",
+			log_vmname ? log_vmname : "",
+			/* sec_since_epoch: Safely convert time_t type to
+			 * double. */
+			difftime(event->timestamp.tv_sec, zero_timespec.tv_sec),
+			nanosec,
+			lxc_log_priority_to_string(event->priority),
+			event->category,
+			event->locinfo->file, event->locinfo->func,
+			event->locinfo->line);
 
 	if (n < 0)
 		return n;
diff --git a/src/lxc/log.h b/src/lxc/log.h
index a1df3c9..c873e4e 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <strings.h>
 #include <stdbool.h>
+#include <time.h>
 
 #include "conf.h"
 
@@ -81,7 +82,7 @@ struct lxc_log_locinfo {
 struct lxc_log_event {
 	const char*		category;
 	int			priority;
-	struct timeval		timestamp;
+	struct timespec		timestamp;
 	struct lxc_log_locinfo	*locinfo;
 	const char		*fmt;
 	va_list			*vap;
@@ -216,7 +217,10 @@ ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo,	\
 		};							\
 		va_list va_ref;						\
 									\
-		gettimeofday(&evt.timestamp, NULL);			\
+		/* clock_gettime() is explicitly marked as MT-Safe	\
+		 * without restrictions. So let's use it for our	\
+		 * logging stamps. */					\
+		clock_gettime(CLOCK_REALTIME, &evt.timestamp);		\
 									\
 		va_start(va_ref, format);				\
 		evt.vap = &va_ref;					\

From 2bfafb07323e6111bc8a73d8868f9ab197289ea1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 28 Nov 2016 22:08:37 +0100
Subject: [PATCH 297/334] log: add lxc_unix_epoch_to_utc()

Converts a unix time Epoch given by a struct timespec to a UTC string useable
in our logging functions. Maybe expanded to allow for more generic formatting.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index fb86d34..0fdd1fa 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -22,9 +22,12 @@
  */
 
 #define _GNU_SOURCE
+#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
 #include <assert.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -71,6 +74,44 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
 }
 
 /*---------------------------------------------------------------------------*/
+int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time)
+{
+	int64_t days, z, era, doe, yoe, year, doy, mp, day, month, d_in_s,
+	    hours, h_in_s, minutes, seconds;
+	char nanosec[__LXC_NUMSTRLEN];
+	int ret;
+
+	/* See https://howardhinnant.github.io/date_algorithms.html for an
+	 * explanation of the algorithm used here.
+	 */
+	days = time->tv_sec / 86400;
+	z = days + 719468;
+	era = (z >= 0 ? z : z - 146096) / 146097;
+	doe = (z - era * 146097);
+	yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
+	year = (yoe) + era * 400;
+	doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
+	mp = (5 * doy + 2) / 153;
+	day = doy - (153 * mp + 2) / 5 + 1;
+	month = mp + (mp < 10 ? 3 : -9);
+	d_in_s = days * 86400;
+	hours = (time->tv_sec - d_in_s) / 3600;
+	h_in_s = hours * 3600;
+	minutes = (time->tv_sec - d_in_s - h_in_s) / 60;
+	seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
+
+	ret = snprintf(nanosec, __LXC_NUMSTRLEN, "%ld", time->tv_nsec);
+	if (ret < 0 || ret >= __LXC_NUMSTRLEN)
+		return -1;
+	ret = snprintf(buf, bufsize, "%" PRId64 "%" PRId64 "%" PRId64 "%" PRId64
+				     "%" PRId64 "%" PRId64 ".%.3s",
+		       year, month, day, hours, minutes, seconds, nanosec);
+	if (ret < 0 || (size_t)ret >= bufsize)
+		return -1;
+
+	return 0;
+}
+
 /* This function needs to make extra sure that it is thread-safe. We had some
  * problems with that before. This especially involves time-conversion
  * functions. I don't want to find any localtime() or gmtime() functions or

From 1d3fef81ba303a1fa76c0a3f933d74285d6f8347 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 28 Nov 2016 22:19:02 +0100
Subject: [PATCH 298/334] log: use lxc_unix_epoch_to_utc()

This allows us to generate nice timestamps in a thread-safe manner without
relying on locale touching functions from any libc.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 0fdd1fa..a8de7ba 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -136,10 +136,9 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 			      struct lxc_log_event *event)
 {
 	char buffer[LXC_LOG_BUFFER_SIZE];
-	struct timespec zero_timespec = {0};
-	int ret, n;
+	char date_time[LXC_LOG_TIME_SIZE];
+	int n;
 	int fd_to_use = -1;
-	char nanosec[__LXC_NUMSTRLEN];
 
 #ifndef NO_LXC_CONF
 	if (!lxc_log_use_global_fd && current_config)
@@ -152,19 +151,15 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 	if (fd_to_use == -1)
 		return 0;
 
-	ret = snprintf(nanosec, __LXC_NUMSTRLEN, "%ld", event->timestamp.tv_nsec);
-	if (ret < 0 || ret >= LXC_LOG_TIME_SIZE)
+	if (lxc_unix_epoch_to_utc(date_time, LXC_LOG_TIME_SIZE, &event->timestamp) < 0)
 		return 0;
 
 	n = snprintf(buffer, sizeof(buffer),
-			"%15s%s%s [ %.0f.%.6s ] %-8s %s - %s:%s:%d - ",
+			"%15s%s%s %s %-8s %s - %s:%s:%d - ",
 			log_prefix,
 			log_vmname ? " " : "",
 			log_vmname ? log_vmname : "",
-			/* sec_since_epoch: Safely convert time_t type to
-			 * double. */
-			difftime(event->timestamp.tv_sec, zero_timespec.tv_sec),
-			nanosec,
+			date_time,
 			lxc_log_priority_to_string(event->priority),
 			event->category,
 			event->locinfo->file, event->locinfo->func,

From bb1957a5af68b71e01c357541c756a92c3224c90 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 29 Nov 2016 01:26:25 +0100
Subject: [PATCH 299/334] log: annotate lxc_unix_epoch_to_utc()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 59 insertions(+), 5 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index a8de7ba..f9bc0cc 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -76,33 +76,87 @@ static int log_append_stderr(const struct lxc_log_appender *appender,
 /*---------------------------------------------------------------------------*/
 int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time)
 {
-	int64_t days, z, era, doe, yoe, year, doy, mp, day, month, d_in_s,
-	    hours, h_in_s, minutes, seconds;
+	int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month,
+	    d_in_s, hours, h_in_s, minutes, seconds;
 	char nanosec[__LXC_NUMSTRLEN];
 	int ret;
 
 	/* See https://howardhinnant.github.io/date_algorithms.html for an
 	 * explanation of the algorithm used here.
 	 */
-	days = time->tv_sec / 86400;
-	z = days + 719468;
+
+	/* Convert Epoch in seconds to number of days. */
+	epoch_to_days = time->tv_sec / 86400;
+
+	/* Shift the Epoch from 1970-01-01 to 0000-03-01. */
+	z = epoch_to_days + 719468;
+
+	/* compute the era from the serial date by simply dividing by the number
+	 * of days in an era (146097).
+	 */
 	era = (z >= 0 ? z : z - 146096) / 146097;
+
+	/* The day-of-era (doe) can then be found by subtracting the era number
+	 * times the number of days per era, from the serial date.
+	 */
 	doe = (z - era * 146097);
+
+	/* From the day-of-era (doe), the year-of-era (yoe, range [0, 399]) can
+	 * be computed.
+	 */
 	yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
+
+	/* Given year-of-era, and era, one can now compute the year. */
 	year = (yoe) + era * 400;
+
+	/* Also the day-of-year, again with the year beginning on Mar. 1, can be
+	 * computed from the day-of-era and year-of-era.
+	 */
 	doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
+
+	/* Given day-of-year, find the month number. */
 	mp = (5 * doy + 2) / 153;
+
+	/* From day-of-year and month-of-year we can now easily compute
+	 * day-of-month.
+	 */
 	day = doy - (153 * mp + 2) / 5 + 1;
+
+	/* Transform the month number from the [0, 11] / [Mar, Feb] system to
+	 * the civil system: [1, 12] to find the correct month.
+	 */
 	month = mp + (mp < 10 ? 3 : -9);
-	d_in_s = days * 86400;
+
+	/* Transform days in the epoch to seconds. */
+	d_in_s = epoch_to_days * 86400;
+
+	/* To find the current hour simply substract the Epoch_to_days from the
+	 * total Epoch and divide by the number of seconds in an hour.
+	 */
 	hours = (time->tv_sec - d_in_s) / 3600;
+
+	/* Transform hours to seconds. */
 	h_in_s = hours * 3600;
+
+	/* Calculate minutes by substracting the seconds for all days in the
+	 * epoch and for all hours in the epoch and divide by the number of
+	 * minutes in an hour.
+	 */
 	minutes = (time->tv_sec - d_in_s - h_in_s) / 60;
+
+	/* Calculate the seconds by substracting the seconds for all days in the
+	 * epoch, hours in the epoch and minutes in the epoch.
+	 */
 	seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
 
+	/* Make string from nanoseconds. */
 	ret = snprintf(nanosec, __LXC_NUMSTRLEN, "%ld", time->tv_nsec);
 	if (ret < 0 || ret >= __LXC_NUMSTRLEN)
 		return -1;
+
+	/* Create final timestamp for the log and shorten nanoseconds to 3
+	 * digit precision.
+	 */
 	ret = snprintf(buf, bufsize, "%" PRId64 "%" PRId64 "%" PRId64 "%" PRId64
 				     "%" PRId64 "%" PRId64 ".%.3s",
 		       year, month, day, hours, minutes, seconds, nanosec);

From 8b79a8fec4127c754509d65faae1fe7f09515365 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 29 Nov 2016 07:28:19 +0100
Subject: [PATCH 300/334] tree-wide: random macro cleanups

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/attach.c               |  2 +-
 src/lxc/bdev/bdev.c            |  2 +-
 src/lxc/bdev/bdev.h            |  2 +-
 src/lxc/cgroups/cgfsng.c       | 10 +++-------
 src/lxc/commands.h             |  6 +++---
 src/lxc/conf.c                 |  8 +++-----
 src/lxc/genl.c                 |  6 +++---
 src/lxc/log.c                  |  8 ++++----
 src/lxc/monitor.c              |  7 +++----
 src/lxc/nl.h                   |  3 +--
 src/lxc/tools/lxc_init.c       |  2 +-
 src/lxc/tools/lxc_ls.c         |  1 -
 src/lxc/tools/lxc_start.c      |  6 +++---
 src/lxc/tools/lxc_stop.c       |  4 ++--
 src/lxc/tools/lxc_usernsexec.c |  2 +-
 src/lxc/utils.c                | 17 ++++++++---------
 src/lxc/utils.h                |  3 ++-
 src/tests/concurrent.c         |  2 +-
 src/tests/lxc-test-utils.c     |  2 +-
 19 files changed, 42 insertions(+), 51 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index dd2b4c3..ee75f3d 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -79,7 +79,7 @@
 lxc_log_define(lxc_attach, lxc);
 
 /* /proc/pid-to-str/current\0 = (5 + 21 + 7 + 1) */
-#define __LSMATTRLEN (5 + 21 + 7 + 1)
+#define __LSMATTRLEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
 static int lsm_openat(int procfd, pid_t pid, int on_exec)
 {
 	int ret = -1;
diff --git a/src/lxc/bdev/bdev.c b/src/lxc/bdev/bdev.c
index 1534cc9..3526ed5 100644
--- a/src/lxc/bdev/bdev.c
+++ b/src/lxc/bdev/bdev.c
@@ -68,7 +68,7 @@
 #include "utils.h"
 
 #ifndef BLKGETSIZE64
-#define BLKGETSIZE64 _IOR(0x12,114,size_t)
+#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
 #endif
 
 lxc_log_define(bdev, lxc);
diff --git a/src/lxc/bdev/bdev.h b/src/lxc/bdev/bdev.h
index 3f21e84..d8083cb 100644
--- a/src/lxc/bdev/bdev.h
+++ b/src/lxc/bdev/bdev.h
@@ -47,7 +47,7 @@
 #endif
 
 #ifndef MS_SLAVE
-#define MS_SLAVE (1<<19)
+#define MS_SLAVE (1 << 19)
 #endif
 
 #ifndef MS_RELATIME
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index d3215d7..2b772e2 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -357,22 +357,18 @@ static uint32_t *lxc_cpumask(char *buf, size_t nbits)
 	return bitarr;
 }
 
-/* The largest integer that can fit into long int is 2^64. This is a
- * 20-digit number.
- */
-#define __IN_TO_STR_LEN 21
 /* Turn cpumask into simple, comma-separated cpulist. */
 static char *lxc_cpumask_to_cpulist(uint32_t *bitarr, size_t nbits)
 {
 	size_t i;
 	int ret;
-	char numstr[__IN_TO_STR_LEN] = {0};
+	char numstr[LXC_NUMSTRLEN64] = {0};
 	char **cpulist = NULL;
 
 	for (i = 0; i <= nbits; i++) {
 		if (is_set(i, bitarr)) {
-			ret = snprintf(numstr, __IN_TO_STR_LEN, "%zu", i);
-			if (ret < 0 || (size_t)ret >= __IN_TO_STR_LEN) {
+			ret = snprintf(numstr, LXC_NUMSTRLEN64, "%zu", i);
+			if (ret < 0 || (size_t)ret >= LXC_NUMSTRLEN64) {
 				lxc_free_array((void **)cpulist, free);
 				return NULL;
 			}
diff --git a/src/lxc/commands.h b/src/lxc/commands.h
index e11a139..184eefa 100644
--- a/src/lxc/commands.h
+++ b/src/lxc/commands.h
@@ -26,11 +26,11 @@
 
 #include "state.h"
 
-#define LXC_CMD_DATA_MAX (MAXPATHLEN*2)
+#define LXC_CMD_DATA_MAX (MAXPATHLEN * 2)
 
 /* https://developer.gnome.org/glib/2.28/glib-Type-Conversion-Macros.html */
-#define INT_TO_PTR(n) ((void *) (long) (n))
-#define PTR_TO_INT(p) ((int) (long) (p))
+#define INT_TO_PTR(n) ((void *)(long)(n))
+#define PTR_TO_INT(p) ((int)(long)(p))
 
 typedef enum {
 	LXC_CMD_CONSOLE,
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 9bc8770..4d5a0ff 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -99,8 +99,6 @@
 
 lxc_log_define(lxc_conf, lxc);
 
-#define LINELEN 4096
-
 #if HAVE_SYS_CAPABILITY_H
 #ifndef CAP_SETFCAP
 #define CAP_SETFCAP 31
@@ -1281,7 +1279,7 @@ static int setup_rootfs(struct lxc_conf *conf)
 
 int prepare_ramfs_root(char *root)
 {
-	char buf[LINELEN], *p;
+	char buf[LXC_LINELEN], *p;
 	char nroot[PATH_MAX];
 	FILE *f;
 	int i;
@@ -1326,7 +1324,7 @@ int prepare_ramfs_root(char *root)
 			SYSERROR("Unable to open /proc/self/mountinfo");
 			return -1;
 		}
-		while (fgets(buf, LINELEN, f)) {
+		while (fgets(buf, LXC_LINELEN, f)) {
 			for (p = buf, i=0; p && i < 4; i++)
 				p = strchr(p+1, ' ');
 			if (!p)
@@ -3042,7 +3040,7 @@ bool lxc_delete_network(struct lxc_handler *handler)
 #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
 
 /* lxc-user-nic returns "interface_name:interface_name\n" */
-#define MAX_BUFFER_SIZE IFNAMSIZ*2 + 2
+#define MAX_BUFFER_SIZE IFNAMSIZ * 2 + 2
 static int unpriv_assign_nic(const char *lxcpath, char *lxcname,
 			     struct lxc_netdev *netdev, pid_t pid)
 {
diff --git a/src/lxc/genl.c b/src/lxc/genl.c
index b5a582e..6afaf40 100644
--- a/src/lxc/genl.c
+++ b/src/lxc/genl.c
@@ -44,7 +44,7 @@ static int genetlink_resolve_family(const char *family)
 	request = genlmsg_alloc(GENLMSG_GOOD_SIZE);
 	if (!request)
 		return -ENOMEM;
-		
+
 	reply = genlmsg_alloc(GENLMSG_GOOD_SIZE);
 	if (!reply) {
 		genlmsg_free(request);
@@ -86,10 +86,10 @@ static int genetlink_resolve_family(const char *family)
 	len -= NLMSG_LENGTH(GENL_HDRLEN);
 	if (len < 0)
 		goto out_close;
-	
+
 	attr = (struct nlattr *)GENLMSG_DATA(reply);
 	attr = (struct nlattr *)((char *)attr + NLA_ALIGN(attr->nla_len));
-	
+
 	ret = -ENOMSG;
 	if (attr->nla_type != CTRL_ATTR_FAMILY_ID)
 		goto out_close;
diff --git a/src/lxc/log.c b/src/lxc/log.c
index f9bc0cc..8d9a0f3 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -47,7 +47,7 @@
  * datatype is currently at maximum a 64bit integer, we have a date string that
  * is of maximum length (2^64 - 1) * 2 = (21 + 21) = 42.
  */
-#define LXC_LOG_TIME_SIZE  ((__LXC_NUMSTRLEN) * 2)
+#define LXC_LOG_TIME_SIZE ((LXC_NUMSTRLEN64)*2)
 
 int lxc_log_fd = -1;
 int lxc_quiet_specified;
@@ -78,7 +78,7 @@ int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time
 {
 	int64_t epoch_to_days, z, era, doe, yoe, year, doy, mp, day, month,
 	    d_in_s, hours, h_in_s, minutes, seconds;
-	char nanosec[__LXC_NUMSTRLEN];
+	char nanosec[LXC_NUMSTRLEN64];
 	int ret;
 
 	/* See https://howardhinnant.github.io/date_algorithms.html for an
@@ -150,8 +150,8 @@ int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time
 	seconds = (time->tv_sec - d_in_s - h_in_s - (minutes * 60));
 
 	/* Make string from nanoseconds. */
-	ret = snprintf(nanosec, __LXC_NUMSTRLEN, "%ld", time->tv_nsec);
-	if (ret < 0 || ret >= __LXC_NUMSTRLEN)
+	ret = snprintf(nanosec, LXC_NUMSTRLEN64, "%ld", time->tv_nsec);
+	if (ret < 0 || ret >= LXC_NUMSTRLEN64)
 		return -1;
 
 	/* Create final timestamp for the log and shorten nanoseconds to 3
diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c
index 793fbde..483e06b 100644
--- a/src/lxc/monitor.c
+++ b/src/lxc/monitor.c
@@ -284,12 +284,11 @@ int lxc_monitor_read(int fd, struct lxc_msg *msg)
 /* Used to spawn a monitord either on startup of a daemon container, or when
  * lxc-monitor starts.
  */
-#define __INT_LEN 21
 int lxc_monitord_spawn(const char *lxcpath)
 {
 	int ret;
 	int pipefd[2];
-	char pipefd_str[__INT_LEN];
+	char pipefd_str[LXC_NUMSTRLEN64];
 	pid_t pid1, pid2;
 
 	char *const args[] = {
@@ -356,8 +355,8 @@ int lxc_monitord_spawn(const char *lxcpath)
 
 	close(pipefd[0]);
 
-	ret = snprintf(pipefd_str, __INT_LEN, "%d", pipefd[1]);
-	if (ret < 0 || ret >= __INT_LEN) {
+	ret = snprintf(pipefd_str, LXC_NUMSTRLEN64, "%d", pipefd[1]);
+	if (ret < 0 || ret >= LXC_NUMSTRLEN64) {
 		ERROR("Failed to create pid argument to pass to monitord.");
 		exit(EXIT_FAILURE);
 	}
diff --git a/src/lxc/nl.h b/src/lxc/nl.h
index d347835..0bf62d5 100644
--- a/src/lxc/nl.h
+++ b/src/lxc/nl.h
@@ -30,8 +30,7 @@
 #define PAGE_SIZE 4096
 #endif
 #define NLMSG_GOOD_SIZE (2*PAGE_SIZE)
-#define NLMSG_TAIL(nmsg) \
-        ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+#define NLMSG_TAIL(nmsg) ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
 #define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
 #define NLA_NEXT_ATTR(attr) ((void *)((char *)attr) + NLA_ALIGN(attr->nla_len))
 
diff --git a/src/lxc/tools/lxc_init.c b/src/lxc/tools/lxc_init.c
index 5dd29af..1aaa96c 100644
--- a/src/lxc/tools/lxc_init.c
+++ b/src/lxc/tools/lxc_init.c
@@ -21,6 +21,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -30,7 +31,6 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#define _GNU_SOURCE
 #include <getopt.h>
 
 #include "log.h"
diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index b5ddeef..363d3d2 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -43,7 +43,6 @@
 
 lxc_log_define(lxc_ls, lxc);
 
-#define LINELEN 1024
 /* Per default we only allow five levels of recursion to protect the stack at
  * least a little bit. */
 #define MAX_NESTLVL 5
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index eaa8da4..984a28f 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -50,9 +50,9 @@
 #include "confile.h"
 #include "arguments.h"
 
-#define OPT_SHARE_NET OPT_USAGE+1
-#define OPT_SHARE_IPC OPT_USAGE+2
-#define OPT_SHARE_UTS OPT_USAGE+3
+#define OPT_SHARE_NET OPT_USAGE + 1
+#define OPT_SHARE_IPC OPT_USAGE + 2
+#define OPT_SHARE_UTS OPT_USAGE + 3
 
 lxc_log_define(lxc_start_ui, lxc);
 
diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c
index 64b742d..e2d64fb 100644
--- a/src/lxc/tools/lxc_stop.c
+++ b/src/lxc/tools/lxc_stop.c
@@ -33,8 +33,8 @@
 #include "commands.h"
 #include "utils.h"
 
-#define OPT_NO_LOCK OPT_USAGE+1
-#define OPT_NO_KILL OPT_USAGE+2
+#define OPT_NO_LOCK OPT_USAGE + 1
+#define OPT_NO_KILL OPT_USAGE + 2
 
 lxc_log_define(lxc_stop_ui, lxc);
 
diff --git a/src/lxc/tools/lxc_usernsexec.c b/src/lxc/tools/lxc_usernsexec.c
index 9905d53..7fd2aca 100644
--- a/src/lxc/tools/lxc_usernsexec.c
+++ b/src/lxc/tools/lxc_usernsexec.c
@@ -50,7 +50,7 @@
 #endif
 
 #ifndef MS_SLAVE
-#define MS_SLAVE (1<<19)
+#define MS_SLAVE (1 << 19)
 #endif
 
 int unshare(int flags);
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 7ddf1db..7c2098e 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1093,10 +1093,9 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
  * is MS_SHARED, but not '/', then you're out of luck - figuring that
  * out would be too much work to be worth it.
  */
-#define LINELEN 4096
 int detect_shared_rootfs(void)
 {
-	char buf[LINELEN], *p;
+	char buf[LXC_LINELEN], *p;
 	FILE *f;
 	int i;
 	char *p2;
@@ -1104,18 +1103,18 @@ int detect_shared_rootfs(void)
 	f = fopen("/proc/self/mountinfo", "r");
 	if (!f)
 		return 0;
-	while (fgets(buf, LINELEN, f)) {
-		for (p = buf, i=0; p && i < 4; i++)
-			p = strchr(p+1, ' ');
+	while (fgets(buf, LXC_LINELEN, f)) {
+		for (p = buf, i = 0; p && i < 4; i++)
+			p = strchr(p + 1, ' ');
 		if (!p)
 			continue;
-		p2 = strchr(p+1, ' ');
+		p2 = strchr(p + 1, ' ');
 		if (!p2)
 			continue;
 		*p2 = '\0';
-		if (strcmp(p+1, "/") == 0) {
+		if (strcmp(p + 1, "/") == 0) {
 			// this is '/'.  is it shared?
-			p = strchr(p2+1, ' ');
+			p = strchr(p2 + 1, ' ');
 			if (p && strstr(p, "shared:")) {
 				fclose(f);
 				return 1;
@@ -1897,7 +1896,7 @@ int lxc_strmunmap(void *addr, size_t length)
 
 /* Check whether a signal is blocked by a process. */
 /* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
-#define __PROC_STATUS_LEN (5 + 21 + 7 + 1)
+#define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
 bool task_blocking_signal(pid_t pid, int signal)
 {
 	bool bret = false;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 3d1ecee..b7dcd5d 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -37,7 +37,8 @@
 
 /* Useful macros */
 /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
-#define __LXC_NUMSTRLEN 21
+#define LXC_NUMSTRLEN64 21
+#define LXC_LINELEN 4096
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude);
diff --git a/src/tests/concurrent.c b/src/tests/concurrent.c
index e6899ad..bfefa48 100644
--- a/src/tests/concurrent.c
+++ b/src/tests/concurrent.c
@@ -16,13 +16,13 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#define _GNU_SOURCE
 #include <limits.h>
 #include <stdio.h>
 #include <pthread.h>
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
-#define _GNU_SOURCE
 #include <getopt.h>
 
 #include <lxc/lxccontainer.h>
diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 800c029..d4363b8 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -71,7 +71,7 @@ void test_lxc_deslashify(void)
 }
 
 /* /proc/int_as_str/ns/mnt\0 = (5 + 21 + 7 + 1) */
-#define __MNTNS_LEN (5 + 21 + 7 + 1)
+#define __MNTNS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
 void test_detect_ramfs_rootfs(void)
 {
 	size_t i;

From 5267c49f0d845b1c5a2e676f7167eaeeb02728b1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 29 Nov 2016 07:50:29 +0100
Subject: [PATCH 301/334] log: make sure that date is correctly formatted

- single digit months, days, hours, minutes, and seconds should always be
  preceded by a 0.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 8d9a0f3..1e510b8 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -157,8 +157,9 @@ int lxc_unix_epoch_to_utc(char *buf, size_t bufsize, const struct timespec *time
 	/* Create final timestamp for the log and shorten nanoseconds to 3
 	 * digit precision.
 	 */
-	ret = snprintf(buf, bufsize, "%" PRId64 "%" PRId64 "%" PRId64 "%" PRId64
-				     "%" PRId64 "%" PRId64 ".%.3s",
+	ret = snprintf(buf, bufsize,
+		       "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64
+		       "%02" PRId64 "%02" PRId64 ".%.3s",
 		       year, month, day, hours, minutes, seconds, nanosec);
 	if (ret < 0 || (size_t)ret >= bufsize)
 		return -1;

From 47378d53894dedd49744ee3a16facadbdea54723 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 29 Nov 2016 05:42:47 +0100
Subject: [PATCH 302/334] monitord: close mainloop on exit if we opened it

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/lxc_monitord.c | 20 +++++++++++---------
 src/lxc/mainloop.c     |  1 -
 src/lxc/monitor.c      |  2 ++
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
index 2fbb357..62e2121 100644
--- a/src/lxc/lxc_monitord.c
+++ b/src/lxc/lxc_monitord.c
@@ -348,6 +348,8 @@ int main(int argc, char *argv[])
 	char logpath[PATH_MAX];
 	sigset_t mask;
 	char *lxcpath = argv[1];
+	bool mainloop_opened = false;
+	bool monitord_created = false;
 
 	if (argc != 3) {
 		fprintf(stderr,
@@ -395,10 +397,11 @@ int main(int argc, char *argv[])
 		ERROR("Failed to create mainloop.");
 		goto on_error;
 	}
+	mainloop_opened = true;
 
-	if (lxc_monitord_create(&mon)) {
+	if (lxc_monitord_create(&mon))
 		goto on_error;
-	}
+	monitord_created = true;
 
 	/* sync with parent, we're ignoring the return from write
 	 * because regardless if it works or not, the following
@@ -425,14 +428,13 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	lxc_mainloop_close(&mon.descr);
-	lxc_monitord_cleanup();
+on_signal:
 	ret = EXIT_SUCCESS;
-
 on_error:
-	exit(ret);
+	if (monitord_created)
+		lxc_monitord_cleanup();
+	if (mainloop_opened)
+		lxc_mainloop_close(&mon.descr);
 
-on_signal:
-	lxc_monitord_cleanup();
-	exit(EXIT_SUCCESS);
+	exit(ret);
 }
diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c
index 85b3ab9..ab9c27d 100644
--- a/src/lxc/mainloop.c
+++ b/src/lxc/mainloop.c
@@ -161,4 +161,3 @@ int lxc_mainloop_close(struct lxc_epoll_descr *descr)
 
 	return close(descr->epfd);
 }
-
diff --git a/src/lxc/monitor.c b/src/lxc/monitor.c
index 483e06b..d9b3e21 100644
--- a/src/lxc/monitor.c
+++ b/src/lxc/monitor.c
@@ -325,6 +325,7 @@ int lxc_monitord_spawn(const char *lxcpath)
 	}
 
 	if (pid2) {
+		DEBUG("Trying to sync with child process.");
 		char c;
 		/* Wait for daemon to create socket. */
 		close(pipefd[1]);
@@ -339,6 +340,7 @@ int lxc_monitord_spawn(const char *lxcpath)
 
 		close(pipefd[0]);
 
+		DEBUG("Sucessfully synced with child process.");
 		exit(EXIT_SUCCESS);
 	}
 

From b5705aa2ffec5366ce476c64704885674ed4fa02 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 29 Nov 2016 18:42:22 +0100
Subject: [PATCH 303/334] state: use async signal safe fun in lxc_wait()

gettimeofday() is not async signal safe. So let's switch to clock_gettime() to
be on the safe side.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/state.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/lxc/state.c b/src/lxc/state.c
index db833b0..7c1835b 100644
--- a/src/lxc/state.c
+++ b/src/lxc/state.c
@@ -20,25 +20,27 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
-#include <errno.h>
+#include <time.h>
 #include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/file.h>
 #include <sys/param.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
-#include <sys/file.h>
+#include <sys/types.h>
 
-#include "lxc.h"
-#include "log.h"
-#include "start.h"
 #include "cgroup.h"
-#include "monitor.h"
 #include "commands.h"
 #include "config.h"
+#include "log.h"
+#include "lxc.h"
+#include "monitor.h"
+#include "start.h"
 
 lxc_log_define(lxc_state, lxc);
 
@@ -103,11 +105,12 @@ static int fillwaitedstates(const char *strstates, int *states)
 	return 0;
 }
 
-extern int lxc_wait(const char *lxcname, const char *states, int timeout, const char *lxcpath)
+extern int lxc_wait(const char *lxcname, const char *states, int timeout,
+		    const char *lxcpath)
 {
 	struct lxc_msg msg;
 	int state, ret;
-	int s[MAX_STATE] = { }, fd;
+	int s[MAX_STATE] = {0}, fd;
 
 	if (fillwaitedstates(states, s))
 		return -1;
@@ -133,16 +136,16 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, const
 	}
 
 	for (;;) {
-		int elapsed_time, curtime = 0;
-		struct timeval tv;
+		int64_t elapsed_time, curtime = 0;
+		struct timespec tspec;
 		int stop = 0;
 		int retval;
 
 		if (timeout != -1) {
-			retval = gettimeofday(&tv, NULL);
+			retval = clock_gettime(CLOCK_REALTIME, &tspec);
 			if (retval)
 				goto out_close;
-			curtime = tv.tv_sec;
+			curtime = tspec.tv_sec;
 		}
 		if (lxc_monitor_read_timeout(fd, &msg, timeout) < 0) {
 			/* try again if select interrupted by signal */
@@ -151,10 +154,10 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, const
 		}
 
 		if (timeout != -1) {
-			retval = gettimeofday(&tv, NULL);
+			retval = clock_gettime(CLOCK_REALTIME, &tspec);
 			if (retval)
 				goto out_close;
-			elapsed_time = tv.tv_sec - curtime;
+			elapsed_time = tspec.tv_sec - curtime;
 			if (timeout - elapsed_time <= 0)
 				stop = 1;
 			timeout -= elapsed_time;
@@ -170,11 +173,8 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, const
 
 		switch (msg.type) {
 		case lxc_msg_state:
-			if (msg.value < 0 || msg.value >= MAX_STATE) {
-				ERROR("Receive an invalid state number '%d'",
-					msg.value);
+			if (msg.value < 0 || msg.value >= MAX_STATE)
 				goto out_close;
-			}
 
 			if (s[msg.value]) {
 				ret = 0;

From 6cd073a250a1d1a16beacaa5cb5e6512d3021482 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 30 Nov 2016 23:43:45 -0500
Subject: [PATCH 304/334] Fix log.c for stable-2.0 logging style
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/lxc/log.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/lxc/log.c b/src/lxc/log.c
index 1e510b8..59e659a 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -210,10 +210,8 @@ static int log_append_logfile(const struct lxc_log_appender *appender,
 		return 0;
 
 	n = snprintf(buffer, sizeof(buffer),
-			"%15s%s%s %s %-8s %s - %s:%s:%d - ",
+			"%15s %s %-8s %s - %s:%s:%d - ",
 			log_prefix,
-			log_vmname ? " " : "",
-			log_vmname ? log_vmname : "",
 			date_time,
 			lxc_log_priority_to_string(event->priority),
 			event->category,

From d686e939b58675aba80a59c2b8e931c3e92776f9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 24 Nov 2016 08:16:59 +0100
Subject: [PATCH 305/334] attach: non-functional changes

- improve logging
- simplify functions

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/attach.c | 489 +++++++++++++++++++++++++++----------------------------
 1 file changed, 244 insertions(+), 245 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index ee75f3d..2534152 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -138,13 +138,13 @@ static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
 
 		command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
 		if (!command) {
-			SYSERROR("Failed to write apparmor profile");
+			SYSERROR("Failed to write apparmor profile.");
 			goto out;
 		}
 
 		size = sprintf(command, "changeprofile %s", lsm_label);
 		if (size < 0) {
-			SYSERROR("Failed to write apparmor profile");
+			SYSERROR("Failed to write apparmor profile.");
 			goto out;
 		}
 
@@ -155,12 +155,12 @@ static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
 		INFO("Set LSM label to: %s.", command);
 	} else if (strcmp(name, "SELinux") == 0) {
 		if (write(lsm_labelfd, lsm_label, strlen(lsm_label) + 1) < 0) {
-			SYSERROR("Unable to set LSM label");
+			SYSERROR("Unable to set LSM label: %s.", lsm_label);
 			goto out;
 		}
 		INFO("Set LSM label to: %s.", lsm_label);
 	} else {
-		ERROR("Unable to restore label for unknown LSM: %s", name);
+		ERROR("Unable to restore label for unknown LSM: %s.", name);
 		goto out;
 	}
 	fret = 0;
@@ -174,34 +174,40 @@ static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label)
 	return fret;
 }
 
+/* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
+#define __PROC_STATUS_LEN (5 + 21 + 7 + 1)
 static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 {
-	struct lxc_proc_context_info *info = calloc(1, sizeof(*info));
 	FILE *proc_file;
-	char proc_fn[MAXPATHLEN];
+	char proc_fn[__PROC_STATUS_LEN];
+	bool found;
+	int ret;
 	char *line = NULL;
 	size_t line_bufsz = 0;
-	int ret, found;
-
-	if (!info) {
-		SYSERROR("Could not allocate memory.");
-		return NULL;
-	}
+	struct lxc_proc_context_info *info = NULL;
 
-	/* read capabilities */
-	snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", pid);
+	/* Read capabilities. */
+	ret = snprintf(proc_fn, __PROC_STATUS_LEN, "/proc/%d/status", pid);
+	if (ret < 0 || ret >= __PROC_STATUS_LEN)
+		goto on_error;
 
 	proc_file = fopen(proc_fn, "r");
 	if (!proc_file) {
-		SYSERROR("Could not open %s", proc_fn);
-		goto out_error;
+		SYSERROR("Could not open %s.", proc_fn);
+		goto on_error;
+	}
+
+	info = calloc(1, sizeof(*info));
+	if (!info) {
+		SYSERROR("Could not allocate memory.");
+		return NULL;
 	}
 
-	found = 0;
+	found = false;
 	while (getline(&line, &line_bufsz, proc_file) != -1) {
 		ret = sscanf(line, "CapBnd: %llx", &info->capability_mask);
-		if (ret != EOF && ret > 0) {
-			found = 1;
+		if (ret != EOF && ret == 1) {
+			found = true;
 			break;
 		}
 	}
@@ -210,16 +216,16 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 	fclose(proc_file);
 
 	if (!found) {
-		SYSERROR("Could not read capability bounding set from %s", proc_fn);
+		SYSERROR("Could not read capability bounding set from %s.", proc_fn);
 		errno = ENOENT;
-		goto out_error;
+		goto on_error;
 	}
 
 	info->lsm_label = lsm_process_label_get(pid);
 
 	return info;
 
-out_error:
+on_error:
 	free(info);
 	return NULL;
 }
@@ -239,14 +245,12 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 
 
 	if (access("/proc/self/ns", X_OK)) {
-		ERROR("Does this kernel version support 'attach' ?");
+		ERROR("Does this kernel version support namespaces?");
 		return -1;
 	}
 
 	for (i = 0; i < LXC_NS_MAX; i++) {
-		/* ignore if we are not supposed to attach to that
-		 * namespace
-		 */
+		/* Ignore if we are not supposed to attach to that namespace. */
 		if (which != -1 && !(which & ns_info[i].clone_flag)) {
 			fd[i] = -1;
 			continue;
@@ -256,14 +260,14 @@ static int lxc_attach_to_ns(pid_t pid, int which)
 		if (fd[i] < 0) {
 			saved_errno = errno;
 
-			/* close all already opened file descriptors before
-			 * we return an error, so we don't leak them
+			/* Close all already opened file descriptors before we
+			 * return an error, so we don't leak them.
 			 */
 			for (j = 0; j < i; j++)
 				close(fd[j]);
 
 			errno = saved_errno;
-			SYSERROR("failed to open namespace: '%s'.", ns_info[i].proc_name);
+			SYSERROR("Failed to open namespace: \"%s\".", ns_info[i].proc_name);
 			return -1;
 		}
 	}
@@ -297,43 +301,42 @@ static int lxc_attach_remount_sys_proc(void)
 
 	ret = unshare(CLONE_NEWNS);
 	if (ret < 0) {
-		SYSERROR("failed to unshare mount namespace");
+		SYSERROR("Failed to unshare mount namespace.");
 		return -1;
 	}
 
 	if (detect_shared_rootfs()) {
 		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
-			SYSERROR("Failed to make / rslave");
+			SYSERROR("Failed to make / rslave.");
 			ERROR("Continuing...");
 		}
 	}
 
-	/* assume /proc is always mounted, so remount it */
+	/* Assume /proc is always mounted, so remount it. */
 	ret = umount2("/proc", MNT_DETACH);
 	if (ret < 0) {
-		SYSERROR("failed to unmount /proc");
+		SYSERROR("Failed to unmount /proc.");
 		return -1;
 	}
 
 	ret = mount("none", "/proc", "proc", 0, NULL);
 	if (ret < 0) {
-		SYSERROR("failed to remount /proc");
+		SYSERROR("Failed to remount /proc.");
 		return -1;
 	}
 
-	/* try to umount /sys - if it's not a mount point,
-	 * we'll get EINVAL, then we ignore it because it
-	 * may not have been mounted in the first place
+	/* Try to umount /sys. If it's not a mount point, we'll get EINVAL, then
+	 * we ignore it because it may not have been mounted in the first place.
 	 */
 	ret = umount2("/sys", MNT_DETACH);
 	if (ret < 0 && errno != EINVAL) {
-		SYSERROR("failed to unmount /sys");
+		SYSERROR("Failed to unmount /sys.");
 		return -1;
 	} else if (ret == 0) {
-		/* remount it */
+		/* Remount it. */
 		ret = mount("none", "/sys", "sysfs", 0, NULL);
 		if (ret < 0) {
-			SYSERROR("failed to remount /sys");
+			SYSERROR("Failed to remount /sys.");
 			return -1;
 		}
 	}
@@ -351,7 +354,7 @@ static int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
 			continue;
 
 		if (prctl(PR_CAPBSET_DROP, cap, 0, 0, 0)) {
-			SYSERROR("failed to remove capability id %d", cap);
+			SYSERROR("Failed to remove capability id %d.", cap);
 			return -1;
 		}
 	}
@@ -372,8 +375,8 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
 
 			extra_keep_store = calloc(count, sizeof(char *));
 			if (!extra_keep_store) {
-				SYSERROR("failed to allocate memory for storing current "
-				         "environment variable values that will be kept");
+				SYSERROR("Failed to allocate memory for storing current "
+				         "environment variable values that will be kept.");
 				return -1;
 			}
 			for (i = 0; i < count; i++) {
@@ -381,8 +384,8 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
 				if (v) {
 					extra_keep_store[i] = strdup(v);
 					if (!extra_keep_store[i]) {
-						SYSERROR("failed to allocate memory for storing current "
-						         "environment variable values that will be kept");
+						SYSERROR("Failed to allocate memory for storing current "
+						         "environment variable values that will be kept.");
 						while (i > 0)
 							free(extra_keep_store[--i]);
 						free(extra_keep_store);
@@ -391,14 +394,15 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
 					if (strcmp(extra_keep[i], "PATH") == 0)
 						path_kept = 1;
 				}
-				/* calloc sets entire array to zero, so we don't
-				 * need an else */
+				/* Calloc sets entire array to zero, so we don't
+				 * need an else.
+				 */
 			}
 		}
 
 		if (clearenv()) {
 			char **p;
-			SYSERROR("failed to clear environment");
+			SYSERROR("Failed to clear environment.");
 			if (extra_keep_store) {
 				for (p = extra_keep_store; *p; p++)
 					free(*p);
@@ -412,39 +416,40 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
 			for (i = 0; extra_keep[i]; i++) {
 				if (extra_keep_store[i]) {
 					if (setenv(extra_keep[i], extra_keep_store[i], 1) < 0)
-						SYSERROR("Unable to set environment variable");
+						SYSERROR("Unable to set environment variable.");
 				}
 				free(extra_keep_store[i]);
 			}
 			free(extra_keep_store);
 		}
 
-		/* always set a default path; shells and execlp tend
-		 * to be fine without it, but there is a disturbing
-		 * number of C programs out there that just assume
-		 * that getenv("PATH") is never NULL and then die a
-		 * painful segfault death. */
+		/* Always set a default path; shells and execlp tend to be fine
+		 * without it, but there is a disturbing number of C programs
+		 * out there that just assume that getenv("PATH") is never NULL
+		 * and then die a painful segfault death.
+		 */
 		if (!path_kept)
 			setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1);
 	}
 
 	if (putenv("container=lxc")) {
-		SYSERROR("failed to set environment variable");
+		SYSERROR("Failed to set environment variable.");
 		return -1;
 	}
 
-	/* set extra environment variables */
+	/* Set extra environment variables. */
 	if (extra_env) {
 		for (; *extra_env; extra_env++) {
-			/* duplicate the string, just to be on
-			 * the safe side, because putenv does not
-			 * do it for us */
+			/* Duplicate the string, just to be on the safe side,
+			 * because putenv does not do it for us.
+			 */
 			char *p = strdup(*extra_env);
-			/* we just assume the user knows what they
-			 * are doing, so we don't do any checks */
+			/* We just assume the user knows what they are doing, so
+			 * we don't do any checks.
+			 */
 			if (!p) {
-				SYSERROR("failed to allocate memory for additional environment "
-				         "variables");
+				SYSERROR("Failed to allocate memory for additional environment "
+				         "variables.");
 				return -1;
 			}
 			putenv(p);
@@ -456,16 +461,14 @@ static int lxc_attach_set_environment(enum lxc_attach_env_policy_t policy, char*
 
 static char *lxc_attach_getpwshell(uid_t uid)
 {
-	/* local variables */
 	pid_t pid;
 	int pipes[2];
 	int ret;
 	int fd;
 	char *result = NULL;
 
-	/* we need to fork off a process that runs the
-	 * getent program, and we need to capture its
-	 * output, so we use a pipe for that purpose
+	/* We need to fork off a process that runs the getent program, and we
+	 * need to capture its output, so we use a pipe for that purpose.
 	 */
 	ret = pipe(pipes);
 	if (ret < 0)
@@ -479,7 +482,6 @@ static char *lxc_attach_getpwshell(uid_t uid)
 	}
 
 	if (pid) {
-		/* parent process */
 		FILE *pipe_f;
 		char *line = NULL;
 		size_t line_bufsz = 0;
@@ -496,19 +498,18 @@ static char *lxc_attach_getpwshell(uid_t uid)
 			char *endptr = NULL;
 			int i;
 
-			/* if we already found something, just continue
-			 * to read until the pipe doesn't deliver any more
-			 * data, but don't modify the existing data
-			 * structure
+			/* If we already found something, just continue to read
+			 * until the pipe doesn't deliver any more data, but
+			 * don't modify the existing data structure.
 			 */
 			if (found)
 				continue;
 
-			/* trim line on the right hand side */
+			/* Trim line on the right hand side. */
 			for (i = strlen(line); i > 0 && (line[i - 1] == '\n' || line[i - 1] == '\r'); --i)
 				line[i - 1] = '\0';
 
-			/* split into tokens: first user name */
+			/* Split into tokens: first: user name. */
 			token = strtok_r(line, ":", &saveptr);
 			if (!token)
 				continue;
@@ -535,7 +536,7 @@ static char *lxc_attach_getpwshell(uid_t uid)
 			free(result);
 			result = strdup(token);
 
-			/* sanity check that there are no fields after that */
+			/* Sanity check that there are no fields after that. */
 			token = strtok_r(NULL, ":", &saveptr);
 			if (token)
 				continue;
@@ -552,9 +553,9 @@ static char *lxc_attach_getpwshell(uid_t uid)
 			return NULL;
 		}
 
-		/* some sanity checks: if anything even hinted at going
-		 * wrong: we can't be sure we have a valid result, so
-		 * we assume we don't
+		/* Some sanity checks. If anything even hinted at going wrong,
+		 * we can't be sure we have a valid result, so we assume we
+		 * don't.
 		 */
 
 		if (!WIFEXITED(status))
@@ -568,7 +569,6 @@ static char *lxc_attach_getpwshell(uid_t uid)
 
 		return result;
 	} else {
-		/* child process */
 		char uid_buf[32];
 		char *arguments[] = {
 			"getent",
@@ -579,12 +579,12 @@ static char *lxc_attach_getpwshell(uid_t uid)
 
 		close(pipes[0]);
 
-		/* we want to capture stdout */
+		/* We want to capture stdout. */
 		dup2(pipes[1], 1);
 		close(pipes[1]);
 
-		/* get rid of stdin/stderr, so we try to associate it
-		 * with /dev/null
+		/* Get rid of stdin/stderr, so we try to associate it with
+		 * /dev/null.
 		 */
 		fd = open("/dev/null", O_RDWR);
 		if (fd < 0) {
@@ -596,12 +596,12 @@ static char *lxc_attach_getpwshell(uid_t uid)
 			close(fd);
 		}
 
-		/* finish argument list */
+		/* Finish argument list. */
 		ret = snprintf(uid_buf, sizeof(uid_buf), "%ld", (long) uid);
 		if (ret <= 0)
 			exit(-1);
 
-		/* try to run getent program */
+		/* Try to run getent program. */
 		(void) execvp("getent", arguments);
 		exit(-1);
 	}
@@ -610,31 +610,31 @@ static char *lxc_attach_getpwshell(uid_t uid)
 static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
 {
 	FILE *proc_file;
-	char proc_fn[MAXPATHLEN];
+	char proc_fn[__PROC_STATUS_LEN];
+	int ret;
 	char *line = NULL;
 	size_t line_bufsz = 0;
-	int ret;
 	long value = -1;
 	uid_t uid = (uid_t)-1;
 	gid_t gid = (gid_t)-1;
 
-	/* read capabilities */
-	snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", 1);
+	/* Read capabilities. */
+	snprintf(proc_fn, __PROC_STATUS_LEN, "/proc/%d/status", 1);
 
 	proc_file = fopen(proc_fn, "r");
 	if (!proc_file)
 		return;
 
 	while (getline(&line, &line_bufsz, proc_file) != -1) {
-		/* format is: real, effective, saved set user, fs
-		 * we only care about real uid
+		/* Format is: real, effective, saved set user, fs we only care
+		 * about real uid.
 		 */
 		ret = sscanf(line, "Uid: %ld", &value);
-		if (ret != EOF && ret > 0) {
+		if (ret != EOF && ret == 1) {
 			uid = (uid_t) value;
 		} else {
 			ret = sscanf(line, "Gid: %ld", &value);
-			if (ret != EOF && ret > 0)
+			if (ret != EOF && ret == 1)
 				gid = (gid_t) value;
 		}
 		if (uid != (uid_t)-1 && gid != (gid_t)-1)
@@ -644,14 +644,15 @@ static void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
 	fclose(proc_file);
 	free(line);
 
-	/* only override arguments if we found something */
+	/* Only override arguments if we found something. */
 	if (uid != (uid_t)-1)
 		*init_uid = uid;
 	if (gid != (gid_t)-1)
 		*init_gid = gid;
 
 	/* TODO: we should also parse supplementary groups and use
-	 * setgroups() to set them */
+	 * setgroups() to set them.
+	 */
 }
 
 struct attach_clone_payload {
@@ -664,10 +665,10 @@ struct attach_clone_payload {
 
 static int attach_child_main(void* data);
 
-/* help the optimizer along if it doesn't know that exit always exits */
+/* Help the optimizer along if it doesn't know that exit always exits. */
 #define rexit(c)  do { int __c = (c); _exit(__c); return __c; } while(0)
 
-/* define default options if no options are supplied by the user */
+/* Define default options if no options are supplied by the user. */
 static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_DEFAULT;
 
 static bool fetch_seccomp(const char *name, const char *lxcpath,
@@ -689,22 +690,22 @@ static bool fetch_seccomp(const char *name, const char *lxcpath,
 		return false;
 	}
 
-	/* Fetch the current profile path over the cmd interface */
+	/* Fetch the current profile path over the cmd interface. */
 	path = c->get_running_config_item(c, "lxc.seccomp");
 	if (!path) {
 		return true;
 	}
 
-	/* Copy the value into the new lxc_conf */
+	/* Copy the value into the new lxc_conf. */
 	if (!c->set_config_item(c, "lxc.seccomp", path)) {
 		free(path);
 		return false;
 	}
 	free(path);
 
-	/* Attempt to parse the resulting config */
+	/* Attempt to parse the resulting config. */
 	if (lxc_read_seccomp_config(c->lxc_conf) < 0) {
-		ERROR("Error reading seccomp policy");
+		ERROR("Error reading seccomp policy.");
 		return false;
 	}
 
@@ -738,57 +739,59 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
 	init_pid = lxc_cmd_get_init_pid(name, lxcpath);
 	if (init_pid < 0) {
-		ERROR("failed to get the init pid");
+		ERROR("Failed to get init pid.");
 		return -1;
 	}
 
 	init_ctx = lxc_proc_get_context_info(init_pid);
 	if (!init_ctx) {
-		ERROR("failed to get context of the init process, pid = %ld", (long)init_pid);
+		ERROR("Failed to get context of init process: %ld.",
+		      (long)init_pid);
 		return -1;
 	}
 
 	personality = get_personality(name, lxcpath);
 	if (init_ctx->personality < 0) {
-		ERROR("Failed to get personality of the container");
+		ERROR("Failed to get personality of the container.");
 		lxc_proc_put_context_info(init_ctx);
 		return -1;
 	}
 	init_ctx->personality = personality;
 
 	if (!fetch_seccomp(name, lxcpath, init_ctx, options))
-		WARN("Failed to get seccomp policy");
+		WARN("Failed to get seccomp policy.");
 
 	cwd = getcwd(NULL, 0);
 
-	/* determine which namespaces the container was created with
-	 * by asking lxc-start, if necessary
+	/* Determine which namespaces the container was created with
+	 * by asking lxc-start, if necessary.
 	 */
 	if (options->namespaces == -1) {
 		options->namespaces = lxc_cmd_get_clone_flags(name, lxcpath);
 		/* call failed */
 		if (options->namespaces == -1) {
-			ERROR("failed to automatically determine the "
-			      "namespaces which the container unshared");
+			ERROR("Failed to automatically determine the "
+			      "namespaces which the container uses.");
 			free(cwd);
 			lxc_proc_put_context_info(init_ctx);
 			return -1;
 		}
 	}
 
-	/* create a socket pair for IPC communication; set SOCK_CLOEXEC in order
-	 * to make sure we don't irritate other threads that want to fork+exec away
+	/* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
+	 * to make sure we don't irritate other threads that want to fork+exec
+	 * away
 	 *
 	 * IMPORTANT: if the initial process is multithreaded and another call
 	 * just fork()s away without exec'ing directly after, the socket fd will
 	 * exist in the forked process from the other thread and any close() in
-	 * our own child process will not really cause the socket to close properly,
-	 * potentiall causing the parent to hang.
+	 * our own child process will not really cause the socket to close
+	 * properly, potentiall causing the parent to hang.
 	 *
 	 * For this reason, while IPC is still active, we have to use shutdown()
-	 * if the child exits prematurely in order to signal that the socket
-	 * is closed and cannot assume that the child exiting will automatically
-	 * do that.
+	 * if the child exits prematurely in order to signal that the socket is
+	 * closed and cannot assume that the child exiting will automatically do
+	 * that.
 	 *
 	 * IPC mechanism: (X is receiver)
 	 *   initial process        intermediate          attached
@@ -810,28 +813,26 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	 */
 	ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
 	if (ret < 0) {
-		SYSERROR("could not set up required IPC mechanism for attaching");
+		SYSERROR("Could not set up required IPC mechanism for attaching.");
 		free(cwd);
 		lxc_proc_put_context_info(init_ctx);
 		return -1;
 	}
 
-	/* create intermediate subprocess, three reasons:
-	 *       1. runs all pthread_atfork handlers and the
-	 *          child will no longer be threaded
-	 *          (we can't properly setns() in a threaded process)
-	 *       2. we can't setns() in the child itself, since
-	 *          we want to make sure we are properly attached to
-	 *          the pidns
-	 *       3. also, the initial thread has to put the attached
-	 *          process into the cgroup, which we can only do if
-	 *          we didn't already setns() (otherwise, user
-	 *          namespaces will hate us)
+	/* Create intermediate subprocess, three reasons:
+	 *       1. Runs all pthread_atfork handlers and the child will no
+	 *          longer be threaded (we can't properly setns() in a threaded
+	 *          process).
+	 *       2. We can't setns() in the child itself, since we want to make
+	 *          sure we are properly attached to the pidns.
+	 *       3. Also, the initial thread has to put the attached process
+	 *          into the cgroup, which we can only do if we didn't already
+	 *          setns() (otherwise, user namespaces will hate us).
 	 */
 	pid = fork();
 
 	if (pid < 0) {
-		SYSERROR("failed to create first subprocess");
+		SYSERROR("Failed to create first subprocess.");
 		free(cwd);
 		lxc_proc_put_context_info(init_ctx);
 		return -1;
@@ -841,16 +842,16 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		int procfd = -1;
 		pid_t to_cleanup_pid = pid;
 
-		/* initial thread, we close the socket that is for the
-		 * subprocesses
+		/* Initial thread, we close the socket that is for the
+		 * subprocesses.
 		 */
 		close(ipc_sockets[1]);
 		free(cwd);
 
-		/* attach to cgroup, if requested */
+		/* Attach to cgroup, if requested. */
 		if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
 			if (!cgroup_attach(name, lxcpath, pid))
-				goto cleanup_error;
+				goto on_error;
 		}
 
 		/* Open /proc before setns() to the containers namespace so we
@@ -859,64 +860,63 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		procfd = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 		if (procfd < 0) {
 			SYSERROR("Unable to open /proc.");
-			goto cleanup_error;
+			goto on_error;
 		}
 
-		/* Let the child process know to go ahead */
+		/* Let the child process know to go ahead. */
 		status = 0;
 		ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
 		if (ret <= 0) {
-			ERROR("error using IPC to notify attached process for initialization (0)");
-			goto cleanup_error;
+			ERROR("Intended to send sequence number 0: %s.",
+			      strerror(errno));
+			goto on_error;
 		}
 
-		/* get pid from intermediate process */
+		/* Get pid of attached process from intermediate process. */
 		ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL);
 		if (ret <= 0) {
 			if (ret != 0)
-				ERROR("error using IPC to receive notification "
-						"from attached process (1)");
-			goto cleanup_error;
+				ERROR("Expected to receive pid: %s.", strerror(errno));
+			goto on_error;
 		}
 
-		/* ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313 */
+		/* Ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313. */
 		if (options->stdin_fd == 0) {
 			signal(SIGINT, SIG_IGN);
 			signal(SIGQUIT, SIG_IGN);
 		}
 
-		/* reap intermediate process */
+		/* Reap intermediate process. */
 		ret = wait_for_pid(pid);
 		if (ret < 0)
-			goto cleanup_error;
+			goto on_error;
 
-		/* we will always have to reap the grandchild now */
+		/* We will always have to reap the attached process now. */
 		to_cleanup_pid = attached_pid;
 
-		/* tell attached process it may start initializing */
+		/* Tell attached process it may start initializing. */
 		status = 0;
 		ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
 		if (ret <= 0) {
-			ERROR("error using IPC to notify attached process for initialization (0)");
-			goto cleanup_error;
+			ERROR("Intended to send sequence number 0: %s.", strerror(errno));
+			goto on_error;
 		}
 
-		/* wait for the attached process to finish initializing */
+		/* Wait for the attached process to finish initializing. */
 		expected = 1;
 		ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected);
 		if (ret <= 0) {
 			if (ret != 0)
-				ERROR("error using IPC to receive notification from attached process (1)");
-			goto cleanup_error;
+				ERROR("Expected to receive sequence number 1: %s.", strerror(errno));
+			goto on_error;
 		}
 
-		/* tell attached process we're done */
+		/* Tell attached process we're done. */
 		status = 2;
 		ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
 		if (ret <= 0) {
-			ERROR("Error using IPC to notify attached process for "
-			      "initialization (2): %s.", strerror(errno));
-			goto cleanup_error;
+			ERROR("Intended to send sequence number 2: %s.", strerror(errno));
+			goto on_error;
 		}
 
 		/* Wait for the (grand)child to tell us that it's ready to set
@@ -925,9 +925,9 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		expected = 3;
 		ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected);
 		if (ret <= 0) {
-			ERROR("Error using IPC for the child to tell us to open LSM fd (3): %s.",
-					strerror(errno));
-			goto cleanup_error;
+			ERROR("Expected to receive sequence number 3: %s.",
+			      strerror(errno));
+			goto on_error;
 		}
 
 		/* Open LSM fd and send it to child. */
@@ -937,33 +937,32 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 			/* Open fd for the LSM security module. */
 			labelfd = lsm_openat(procfd, attached_pid, on_exec);
 			if (labelfd < 0)
-				goto cleanup_error;
+				goto on_error;
 
 			/* Send child fd of the LSM security module to write to. */
 			ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
 			if (ret <= 0) {
-				ERROR("Error using IPC to send child LSM fd (4): %s.",
-						strerror(errno));
-				goto cleanup_error;
+				ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(errno));
+				goto on_error;
 			}
 		}
 
-		/* now shut down communication with child, we're done */
+		/* Now shut down communication with child, we're done. */
 		shutdown(ipc_sockets[0], SHUT_RDWR);
 		close(ipc_sockets[0]);
 		lxc_proc_put_context_info(init_ctx);
 
-		/* we're done, the child process should now execute whatever
-		 * it is that the user requested. The parent can now track it
-		 * with waitpid() or similar.
+		/* We're done, the child process should now execute whatever it
+		 * is that the user requested. The parent can now track it with
+		 * waitpid() or similar.
 		 */
 
 		*attached_process = attached_pid;
 		return 0;
 
-	cleanup_error:
-		/* first shut down the socket, then wait for the pid,
-		 * otherwise the pid we're waiting for may never exit
+	on_error:
+		/* First shut down the socket, then wait for the pid, otherwise
+		 * the pid we're waiting for may never exit.
 		 */
 		if (procfd >= 0)
 			close(procfd);
@@ -975,17 +974,17 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 		return -1;
 	}
 
-	/* first subprocess begins here, we close the socket that is for the
-	 * initial thread
+	/* First subprocess begins here, we close the socket that is for the
+	 * initial thread.
 	 */
 	close(ipc_sockets[0]);
 
-	/* Wait for the parent to have setup cgroups */
+	/* Wait for the parent to have setup cgroups. */
 	expected = 0;
 	status = -1;
 	ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status), &expected);
 	if (ret <= 0) {
-		ERROR("error communicating with child process");
+		ERROR("Expected to receive sequence number 0: %s.", strerror(errno));
 		shutdown(ipc_sockets[1], SHUT_RDWR);
 		rexit(-1);
 	}
@@ -993,27 +992,27 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 	if ((options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) && cgns_supported())
 		options->namespaces |= CLONE_NEWCGROUP;
 
-	/* attach now, create another subprocess later, since pid namespaces
-	 * only really affect the children of the current process
+	/* Attach now, create another subprocess later, since pid namespaces
+	 * only really affect the children of the current process.
 	 */
 	ret = lxc_attach_to_ns(init_pid, options->namespaces);
 	if (ret < 0) {
-		ERROR("failed to enter the namespace");
+		ERROR("Failed to enter namespaces.");
 		shutdown(ipc_sockets[1], SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* attach succeeded, try to cwd */
+	/* Attach succeeded, try to cwd. */
 	if (options->initial_cwd)
 		new_cwd = options->initial_cwd;
 	else
 		new_cwd = cwd;
 	ret = chdir(new_cwd);
 	if (ret < 0)
-		WARN("could not change directory to '%s'", new_cwd);
+		WARN("Could not change directory to \"%s\".", new_cwd);
 	free(cwd);
 
-	/* now create the real child process */
+	/* Now create the real child process. */
 	{
 		struct attach_clone_payload payload = {
 			.ipc_socket = ipc_sockets[1],
@@ -1022,35 +1021,36 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 			.exec_function = exec_function,
 			.exec_payload = exec_payload
 		};
-		/* We use clone_parent here to make this subprocess a direct child of
-		 * the initial process. Then this intermediate process can exit and
-		 * the parent can directly track the attached process.
+		/* We use clone_parent here to make this subprocess a direct
+		 * child of the initial process. Then this intermediate process
+		 * can exit and the parent can directly track the attached
+		 * process.
 		 */
 		pid = lxc_clone(attach_child_main, &payload, CLONE_PARENT);
 	}
 
-	/* shouldn't happen, clone() should always return positive pid */
+	/* Shouldn't happen, clone() should always return positive pid. */
 	if (pid <= 0) {
-		SYSERROR("failed to create subprocess");
+		SYSERROR("Failed to create subprocess.");
 		shutdown(ipc_sockets[1], SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* tell grandparent the pid of the pid of the newly created child */
+	/* Tell grandparent the pid of the pid of the newly created child. */
 	ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid));
 	if (ret != sizeof(pid)) {
-		/* if this really happens here, this is very unfortunate, since the
-		 * parent will not know the pid of the attached process and will
-		 * not be able to wait for it (and we won't either due to CLONE_PARENT)
-		 * so the parent won't be able to reap it and the attached process
-		 * will remain a zombie
+		/* If this really happens here, this is very unfortunate, since
+		 * the parent will not know the pid of the attached process and
+		 * will not be able to wait for it (and we won't either due to
+		 * CLONE_PARENT) so the parent won't be able to reap it and the
+		 * attached process will remain a zombie.
 		 */
-		ERROR("error using IPC to notify main process of pid of the attached process");
+		ERROR("Intended to send pid %d: %s.", pid, strerror(errno));
 		shutdown(ipc_sockets[1], SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* the rest is in the hands of the initial and the attached process */
+	/* The rest is in the hands of the initial and the attached process. */
 	rexit(0);
 }
 
@@ -1072,22 +1072,22 @@ static int attach_child_main(void* data)
 	uid_t new_uid;
 	gid_t new_gid;
 
-	/* wait for the initial thread to signal us that it's ready
-	 * for us to start initializing
+	/* Wait for the initial thread to signal us that it's ready for us to
+	 * start initializing.
 	 */
 	expected = 0;
 	status = -1;
 	ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected);
 	if (ret <= 0) {
-		ERROR("Error using IPC to receive notification from initial process (0): %s.", strerror(errno));
+		ERROR("Expected to receive sequence number 0: %s.", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* A description of the purpose of this functionality is
-	 * provided in the lxc-attach(1) manual page. We have to
-	 * remount here and not in the parent process, otherwise
-	 * /proc may not properly reflect the new pid namespace.
+	/* A description of the purpose of this functionality is provided in the
+	 * lxc-attach(1) manual page. We have to remount here and not in the
+	 * parent process, otherwise /proc may not properly reflect the new pid
+	 * namespace.
 	 */
 	if (!(options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_REMOUNT_PROC_SYS)) {
 		ret = lxc_attach_remount_sys_proc();
@@ -1097,7 +1097,7 @@ static int attach_child_main(void* data)
 		}
 	}
 
-	/* now perform additional attachments*/
+	/* Now perform additional attachments. */
 #if HAVE_SYS_PERSONALITY_H
 	if (options->personality < 0)
 		new_personality = init_ctx->personality;
@@ -1107,7 +1107,7 @@ static int attach_child_main(void* data)
 	if (options->attach_flags & LXC_ATTACH_SET_PERSONALITY) {
 		ret = personality(new_personality);
 		if (ret < 0) {
-			SYSERROR("could not ensure correct architecture");
+			SYSERROR("Could not ensure correct architecture.");
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
@@ -1117,25 +1117,27 @@ static int attach_child_main(void* data)
 	if (options->attach_flags & LXC_ATTACH_DROP_CAPABILITIES) {
 		ret = lxc_attach_drop_privs(init_ctx);
 		if (ret < 0) {
-			ERROR("could not drop privileges");
+			ERROR("Could not drop privileges.");
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
 	}
 
-	/* always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL) if you want this to be a no-op) */
+	/* Always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL)
+	 * if you want this to be a no-op).
+	 */
 	ret = lxc_attach_set_environment(options->env_policy, options->extra_env_vars, options->extra_keep_env);
 	if (ret < 0) {
-		ERROR("could not set initial environment for attached process");
+		ERROR("Could not set initial environment for attached process.");
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* set user / group id */
+	/* Set {u,g}id. */
 	new_uid = 0;
 	new_gid = 0;
-	/* ignore errors, we will fall back to root in that case
-	 * (/proc was not mounted etc.)
+	/* Ignore errors, we will fall back to root in that case (/proc was not
+	 * mounted etc.).
 	 */
 	if (options->namespaces & CLONE_NEWUSER)
 		lxc_attach_get_init_uidgid(&new_uid, &new_gid);
@@ -1145,54 +1147,52 @@ static int attach_child_main(void* data)
 	if (options->gid != (gid_t)-1)
 		new_gid = options->gid;
 
-	/* setup the control tty */
+	/* Setup the controlling tty. */
 	if (options->stdin_fd && isatty(options->stdin_fd)) {
 		if (setsid() < 0) {
-			SYSERROR("unable to setsid");
+			SYSERROR("Unable to setsid.");
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
 
 		if (ioctl(options->stdin_fd, TIOCSCTTY, (char *)NULL) < 0) {
-			SYSERROR("unable to TIOCSTTY");
+			SYSERROR("Unable to set TIOCSTTY.");
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
 	}
 
-	/* try to set the uid/gid combination */
+	/* Try to set the {u,g}id combination. */
 	if ((new_gid != 0 || options->namespaces & CLONE_NEWUSER)) {
 		if (setgid(new_gid) || setgroups(0, NULL)) {
-			SYSERROR("switching to container gid");
+			SYSERROR("Switching to container gid.");
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
 	}
 	if ((new_uid != 0 || options->namespaces & CLONE_NEWUSER) && setuid(new_uid)) {
-		SYSERROR("switching to container uid");
+		SYSERROR("Switching to container uid.");
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* tell initial process it may now put us into the cgroups */
+	/* Tell initial process it may now put us into cgroups. */
 	status = 1;
 	ret = lxc_write_nointr(ipc_socket, &status, sizeof(status));
 	if (ret != sizeof(status)) {
-		ERROR("Error using IPC to notify initial process for initialization (1): %s.", strerror(errno));
+		ERROR("Intended to send sequence number 1: %s.", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
 
-	/* wait for the initial thread to signal us that it has done
-	 * everything for us when it comes to cgroups etc.
+	/* Wait for the initial thread to signal us that it has done everything
+	 * for us when it comes to cgroups etc.
 	 */
 	expected = 2;
 	status = -1;
 	ret = lxc_read_nointr_expect(ipc_socket, &status, sizeof(status), &expected);
 	if (ret <= 0) {
-		ERROR("Error using IPC to receive message from initial process "
-		      "that it is done pre-initializing (2): %s",
-		      strerror(errno));
+		ERROR("Expected to receive sequence number 2: %s", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
@@ -1202,7 +1202,7 @@ static int attach_child_main(void* data)
 	status = 3;
 	ret = lxc_write_nointr(ipc_socket, &status, sizeof(status));
 	if (ret <= 0) {
-		ERROR("Error using IPC to tell parent to set up LSM labels (3): %s.", strerror(errno));
+		ERROR("Intended to send sequence number 3: %s.", strerror(errno));
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
@@ -1212,7 +1212,7 @@ static int attach_child_main(void* data)
 		/* Receive fd for LSM security module. */
 		ret = lxc_abstract_unix_recv_fd(ipc_socket, &lsm_labelfd, NULL, 0);
 		if (ret <= 0) {
-			ERROR("Error using IPC for parent to tell us LSM label fd (4): %s.", strerror(errno));
+			ERROR("Expected to receive file descriptor: %s.", strerror(errno));
 			shutdown(ipc_socket, SHUT_RDWR);
 			rexit(-1);
 		}
@@ -1230,7 +1230,7 @@ static int attach_child_main(void* data)
 
 	if (init_ctx->container && init_ctx->container->lxc_conf &&
 			lxc_seccomp_load(init_ctx->container->lxc_conf) != 0) {
-		ERROR("Loading seccomp policy");
+		ERROR("Failed to load seccomp policy.");
 		shutdown(ipc_socket, SHUT_RDWR);
 		rexit(-1);
 	}
@@ -1239,16 +1239,15 @@ static int attach_child_main(void* data)
 	close(ipc_socket);
 	lxc_proc_put_context_info(init_ctx);
 
-	/* The following is done after the communication socket is
-	 * shut down. That way, all errors that might (though
-	 * unlikely) occur up until this point will have their messages
-	 * printed to the original stderr (if logging is so configured)
-	 * and not the fd the user supplied, if any.
+	/* The following is done after the communication socket is shut down.
+	 * That way, all errors that might (though unlikely) occur up until this
+	 * point will have their messages printed to the original stderr (if
+	 * logging is so configured) and not the fd the user supplied, if any.
 	 */
 
-	/* fd handling for stdin, stdout and stderr;
-	 * ignore errors here, user may want to make sure
-	 * the fds are closed, for example */
+	/* Fd handling for stdin, stdout and stderr; ignore errors here, user
+	 * may want to make sure the fds are closed, for example.
+	 */
 	if (options->stdin_fd >= 0 && options->stdin_fd != 0)
 		dup2(options->stdin_fd, 0);
 	if (options->stdout_fd >= 0 && options->stdout_fd != 1)
@@ -1264,18 +1263,19 @@ static int attach_child_main(void* data)
 	if (options->stderr_fd > 2)
 		close(options->stderr_fd);
 
-	/* try to remove CLOEXEC flag from stdin/stdout/stderr,
-	 * but also here, ignore errors */
+	/* Try to remove FD_CLOEXEC flag from stdin/stdout/stderr, but also
+	 * here, ignore errors.
+	 */
 	for (fd = 0; fd <= 2; fd++) {
 		flags = fcntl(fd, F_GETFL);
 		if (flags < 0)
 			continue;
 		if (flags & FD_CLOEXEC)
 			if (fcntl(fd, F_SETFL, flags & ~FD_CLOEXEC) < 0)
-				SYSERROR("Unable to clear CLOEXEC from fd");
+				SYSERROR("Unable to clear FD_CLOEXEC from file descriptor.");
 	}
 
-	/* we're done, so we can now do whatever the user intended us to do */
+	/* We're done, so we can now do whatever the user intended us to do. */
 	rexit(payload->exec_function(payload->exec_payload));
 }
 
@@ -1284,7 +1284,7 @@ int lxc_attach_run_command(void* payload)
 	lxc_attach_command_t* cmd = (lxc_attach_command_t*)payload;
 
 	execvp(cmd->program, cmd->argv);
-	SYSERROR("failed to exec '%s'", cmd->program);
+	SYSERROR("Failed to exec \"%s\".", cmd->program);
 	return -1;
 }
 
@@ -1294,18 +1294,17 @@ int lxc_attach_run_shell(void* payload)
 	struct passwd *passwd;
 	char *user_shell;
 
-	/* ignore payload parameter */
+	/* Ignore payload parameter. */
 	(void)payload;
 
 	uid = getuid();
 	passwd = getpwuid(uid);
 
-	/* this probably happens because of incompatible nss
-	 * implementations in host and container (remember, this
-	 * code is still using the host's glibc but our mount
-	 * namespace is in the container)
-	 * we may try to get the information by spawning a
-	 * [getent passwd uid] process and parsing the result
+	/* This probably happens because of incompatible nss implementations in
+	 * host and container (remember, this code is still using the host's
+	 * glibc but our mount namespace is in the container) we may try to get
+	 * the information by spawning a [getent passwd uid] process and parsing
+	 * the result.
 	 */
 	if (!passwd)
 		user_shell = lxc_attach_getpwshell(uid);
@@ -1315,10 +1314,10 @@ int lxc_attach_run_shell(void* payload)
 	if (user_shell)
 		execlp(user_shell, user_shell, (char *)NULL);
 
-	/* executed if either no passwd entry or execvp fails,
-	 * we will fall back on /bin/sh as a default shell
+	/* Executed if either no passwd entry or execvp fails, we will fall back
+	 * on /bin/sh as a default shell.
 	 */
 	execlp("/bin/sh", "/bin/sh", (char *)NULL);
-	SYSERROR("failed to exec shell");
+	SYSERROR("Failed to exec shell.");
 	return -1;
 }

From 7a432aef44b2a9031b7bd40f8ad374031a2f8166 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 1 Dec 2016 18:34:00 -0500
Subject: [PATCH 306/334] tests; Don't cause test failures on cleanup errors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 src/tests/lxc-test-usernic.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tests/lxc-test-usernic.in b/src/tests/lxc-test-usernic.in
index 42a9a21..0b99baa 100755
--- a/src/tests/lxc-test-usernic.in
+++ b/src/tests/lxc-test-usernic.in
@@ -28,9 +28,9 @@ KNOWN_RELEASES="precise trusty xenial yakkety zesty"
 LXC_USER_NIC="@LIBEXECDIR@/lxc/lxc-user-nic"
 
 cleanup() {
-	(
-		set +e
+	set +e
 
+	(
 		lxc-stop -n usernic-c1 -k
 		lxc-destroy -n usernic-c1
 

From b41fa55341718a9e1945837bcc634ed41c38b8e6 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller at proxmox.com>
Date: Fri, 2 Dec 2016 14:15:40 +0100
Subject: [PATCH 307/334] tools: lxc-start: set configfile after load_config

Same change as in 6118210e0a which was missing in lxc-start
and back then is_defined() wasn't being called.

Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/lxc/tools/lxc_start.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index 984a28f..c85305b 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -259,6 +259,11 @@ int main(int argc, char *argv[])
 			lxc_container_put(c);
 			exit(err);
 		}
+		c->configfile = strdup(my_args.rcfile);
+		if (!c->configfile) {
+			ERROR("Out of memory setting new config filename");
+			goto out;
+		}
 	} else {
 		int rc;
 

From 266922547baff866d13a9cfa5b2ab7ea157b11c6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 2 Dec 2016 19:41:11 +0100
Subject: [PATCH 308/334] conf: clearly report to either use drop or keep

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 4d5a0ff..2a4b176 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3952,7 +3952,7 @@ int lxc_setup(struct lxc_handler *handler)
 
 	if (!lxc_list_empty(&lxc_conf->keepcaps)) {
 		if (!lxc_list_empty(&lxc_conf->caps)) {
-			ERROR("Simultaneously requested dropping and keeping caps");
+			ERROR("Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both.");
 			return -1;
 		}
 		if (dropcaps_except(&lxc_conf->keepcaps)) {

From a2d6fe80fbe08149338c48d078da726c1015bebc Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 8 Dec 2016 23:18:35 +0100
Subject: [PATCH 309/334] attach: close lsm label file descriptor

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/attach.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 2534152..f44be85 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -932,7 +932,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
 		/* Open LSM fd and send it to child. */
 		if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
-			int on_exec, labelfd;
+			int on_exec;
+			int labelfd = -1;
 			on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
 			/* Open fd for the LSM security module. */
 			labelfd = lsm_openat(procfd, attached_pid, on_exec);
@@ -941,12 +942,15 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
 			/* Send child fd of the LSM security module to write to. */
 			ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
+			close(labelfd);
 			if (ret <= 0) {
 				ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(errno));
 				goto on_error;
 			}
 		}
 
+		if (procfd >= 0)
+			close(procfd);
 		/* Now shut down communication with child, we're done. */
 		shutdown(ipc_sockets[0], SHUT_RDWR);
 		close(ipc_sockets[0]);

From 730d7a6a72cbf7fdf761e70cfcd5260ebbd2961c Mon Sep 17 00:00:00 2001
From: FooDeas <foodeas at aeberlein.de>
Date: Thu, 8 Dec 2016 14:03:10 +0100
Subject: [PATCH 310/334] templates: fix getty service startup

Commit bf39edb39ecaea25801d716aebef798885277992 broke the handling of the getty service file with an '@' character in filename. So the startup condition was not fixed.

Because the parameter was quoted with the causal commit, the escaping has to be removed.

Signed-off-by: Andreas Eberlein foodeas at aeberlein.de
---
 templates/lxc-debian.in | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 55afee1..15a85c5 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -211,11 +211,11 @@ configure_debian_systemd()
     num_tty=$4
 
     # this only works if we have getty at .service to manipulate
-    if [ -f "${rootfs}/lib/systemd/system/getty\@.service" ]; then
+    if [ -f "${rootfs}/lib/systemd/system/getty at .service" ]; then
        sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
            -e 's/After=dev-%i.device/After=/' \
-           < "${rootfs}/lib/systemd/system/getty\@.service" \
-           > "${rootfs}/etc/systemd/system/getty\@.service"
+           < "${rootfs}/lib/systemd/system/getty at .service" \
+           > "${rootfs}/etc/systemd/system/getty at .service"
     fi
 
     # just in case systemd is not installed

From 90cf7f89bb28a40dff4d0875bb90a90040391212 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <wry.git at bumiller.com>
Date: Sat, 10 Dec 2016 10:18:27 +0100
Subject: [PATCH 311/334] conf, attach: save errno across call to close

Save errno across some calls to close() since it can be
interrupted.

Signed-off-by: Wolfgang Bumiller <wry.git at bumiller.com>
---
 src/lxc/attach.c | 5 +++--
 src/lxc/conf.c   | 8 +++++---
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index f44be85..119b9c1 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -932,7 +932,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
 		/* Open LSM fd and send it to child. */
 		if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
-			int on_exec;
+			int on_exec, saved_errno;
 			int labelfd = -1;
 			on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
 			/* Open fd for the LSM security module. */
@@ -942,9 +942,10 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 
 			/* Send child fd of the LSM security module to write to. */
 			ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
+			saved_errno = errno;
 			close(labelfd);
 			if (ret <= 0) {
-				ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(errno));
+				ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(saved_errno));
 				goto on_error;
 			}
 		}
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 2a4b176..abff1c5 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2018,9 +2018,10 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount)
 	}
 
 	if (!file) {
+		int saved_errno = errno;
 		if (fd != -1)
 			close(fd);
-		ERROR("Could not create mount entry file: %s.", strerror(errno));
+		ERROR("Could not create mount entry file: %s.", strerror(saved_errno));
 		return NULL;
 	}
 
@@ -2188,7 +2189,7 @@ static int setup_hw_addr(char *hwaddr, const char *ifname)
 {
 	struct sockaddr sockaddr;
 	struct ifreq ifr;
-	int ret, fd;
+	int ret, fd, saved_errno;
 
 	ret = lxc_convert_mac(hwaddr, &sockaddr);
 	if (ret) {
@@ -2208,9 +2209,10 @@ static int setup_hw_addr(char *hwaddr, const char *ifname)
 	}
 
 	ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
+	saved_errno = errno;
 	close(fd);
 	if (ret)
-		ERROR("ioctl failure : %s", strerror(errno));
+		ERROR("ioctl failure : %s", strerror(saved_errno));
 
 	DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifr.ifr_name);
 

From 73fd697741d3fbe8ea9f0ee6ef303391e2c0cbb2 Mon Sep 17 00:00:00 2001
From: "Terzeus S. Dominguez" <zeus at dmgznet.com>
Date: Tue, 13 Dec 2016 00:56:35 +0800
Subject: [PATCH 312/334] Update openSUSE template for Leap 42.2

Aside from adding a 42.2 option, $DISTRO comparisons for Leap have been
changed [ exp ] => [[ exp ]] to accomodate pattern matching for future
releases.

Signed-off-by: Terzeus S. Dominguez <tsdmgz at gmail.com>
---
 templates/lxc-opensuse.in | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index ad75e10..a2b984f 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -145,7 +145,7 @@ download_opensuse()
     mkdir -p "$cache/partial-$arch-packages"
     zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss/ repo-oss || return 1
     # Leap update repos were rearranged
-    if [ $DISTRO == "leap/42.1" ]; then
+    if [[ $DISTRO == "leap/4"* ]]; then
         zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/update/$DISTRO/oss/ update || return 1
     else
         zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1
@@ -182,14 +182,14 @@ EOF
 	echo "Support: python3-base" >> $cache/partial-$arch-packages/opensuse.conf
     fi
 
-    # dhcpcd is not in the default repos with Leap 42.1
-    if [ $DISTRO != "leap/42.1" ]
+    # dhcpcd is not in the default repos since Leap 42.1
+    if [[ $DISTRO != "leap/4"* ]]
     then
     echo "Support: dhcpcd" >> $cache/partial-$arch-packages/opensuse.conf
     fi
 
     # Leap doesn't seem to have iproute2 utils installed
-    if [ $DISTRO == "leap/42.1" ]
+    if [[ $DISTRO == "leap/4"* ]]
     then
     echo "Support: net-tools iproute2" >> $cache/partial-$arch-packages/opensuse.conf
     fi
@@ -210,11 +210,13 @@ EOF
 
     CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem  --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch --repository $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch || return 1
     chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/distribution/$DISTRO/repo/oss repo-oss || return 1
-    if [ $DISTRO == "leap/42.1" ]; then
+
+    if [[ $DISTRO == "leap/4"* ]]; then
         chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/oss update || return 1
     else
         chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar http://download.opensuse.org/update/$DISTRO/ update || return 1
     fi
+
 #   really clean the image
     rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg}
     rm -fr $cache/partial-$arch/dev
@@ -478,6 +480,11 @@ else
 	    DISTRO="leap/42.1"
 	    ;;
 
+        42.2|leap/42.2|422)
+            echo "Selected openSUSE Leap 42.2"
+            DISTRO="leap/42.2"
+            ;; 
+
 	*)
 	    echo "You have chosen an invalid release, quitting..."
 	    exit 1

From eef20f61f0d1851ed0c11a12c9dd1f086cf7b404 Mon Sep 17 00:00:00 2001
From: "Terzeus S. Dominguez" <zeus at dmgznet.com>
Date: Tue, 13 Dec 2016 01:04:31 +0800
Subject: [PATCH 313/334] Change openSUSE default release to Leap 42.2

Signed-off-by: Terzeus S. Dominguez <tsdmgz at gmail.com>
---
 templates/lxc-opensuse.in | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index a2b984f..29702fb 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -407,7 +407,7 @@ usage()
     cat <<EOF
 $1 -h|--help -p|--path=<path> -r|--release nn.n --clean
 Please give the release as 13.1, 13.2 etc.
-If no release is given, openSUSE 13.1 is installed.
+If no release is given, openSUSE Leap 42.2 is installed.
 EOF
     return 0
 }
@@ -462,8 +462,8 @@ fi
 
 if [ -z "$DISTRO" ]; then
     echo ""
-    echo "No release selected, using openSUSE 13.1"
-    DISTRO=13.1
+    echo "No release selected, using openSUSE Leap 42.2"
+    DISTRO=42.2
 else
     echo ""
     case "$DISTRO" in

From da9ca6569a250f42c35292a0b5eb6731c89860e2 Mon Sep 17 00:00:00 2001
From: "Terzeus S. Dominguez" <tsdmgz at gmail.com>
Date: Tue, 13 Dec 2016 03:51:18 +0800
Subject: [PATCH 314/334] Set openSUSE to be unconfined by AppArmor

Uncommented lxc.aa_profile = unconfined. Otherwise, container fails to
start up.

Signed-off-by: Terzeus S. Dominguez <tsdmgz at gmail.com>
---
 templates/lxc-opensuse.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index 29702fb..d1c7853 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -356,7 +356,7 @@ lxc.utsname = $name
 lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
 
 # When using LXC with apparmor, uncomment the next line to run unconfined:
-#lxc.aa_profile = unconfined
+lxc.aa_profile = unconfined
 
 # example simple networking setup, uncomment to enable
 #lxc.network.type = $lxc_network_type

From 790c6b098308519af5c569179049b6c4f03770e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Santiago=20Ruano=20Rinc=C3=B3n?= <santiago at debian.org>
Date: Mon, 12 Dec 2016 11:00:39 +0100
Subject: [PATCH 315/334] templates/lxc-debian.in: Fix typo in calling dpkg
 with --print-foreign-architectures option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Santiago Ruano Rincón <santiago at debian.org>
Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 templates/lxc-debian.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index 15a85c5..b545e33 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -444,7 +444,7 @@ EOF
     # If the container isn't running a native architecture, setup multiarch
     if [ "${arch}" != "${hostarch}" ]; then
         # Test if dpkg supports multiarch
-        if ! chroot "$rootfs" dpkg --print-foreign-architecture 2>&1; then
+        if ! chroot "$rootfs" dpkg --print-foreign-architectures 2>&1; then
             chroot "$rootfs" dpkg --add-architecture "${hostarch}"
         fi
     fi

From ab9cac16ada3b718933472a41ac115bc04ffd578 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Santiago=20Ruano=20Rinc=C3=B3n?= <santiago at debian.org>
Date: Mon, 12 Dec 2016 11:12:26 +0100
Subject: [PATCH 316/334] templates/lxc-debian.in: handle ppc hostarch ->
 powerpc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Santiago Ruano Rincón <santiago at debian.org>
Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 templates/lxc-debian.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/templates/lxc-debian.in b/templates/lxc-debian.in
index b545e33..f752ccd 100644
--- a/templates/lxc-debian.in
+++ b/templates/lxc-debian.in
@@ -549,6 +549,8 @@ elif [ "$arch" = "x86_64" ]; then
     arch="amd64"
 elif [ "$arch" = "armv7l" ]; then
     arch="armhf"
+elif [ "$arch" = "ppc" ]; then
+    arch="powerpc"
 elif [ "$arch" = "ppc64le" ]; then
     arch="ppc64el"
 elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then

From 7638f5fd32d01475eb1a8f4014436b0ba75fc17e Mon Sep 17 00:00:00 2001
From: "Terzeus S. Dominguez" <tsdmgz at gmail.com>
Date: Tue, 13 Dec 2016 05:01:05 +0800
Subject: [PATCH 317/334] Remove libgcc_s1 from openSUSE template

Removed libgcc_s1 because it breaks container building for openSUSE.

Related: openSUSE/obs-build#188

Signed-off-by: Terzeus S. Dominguez <tsdmgz at gmail.com>
---
 templates/lxc-opensuse.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index d1c7853..0774397 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -155,7 +155,7 @@ download_opensuse()
     cat > $cache/partial-$arch-packages/opensuse.conf << EOF
 Preinstall: aaa_base bash coreutils diffutils
 Preinstall: filesystem fillup glibc grep insserv-compat perl-base
-Preinstall: libbz2-1 libgcc_s1 libncurses5 pam
+Preinstall: libbz2-1 libncurses5 pam
 Preinstall: permissions libreadline6 rpm sed tar libz1 libselinux1
 Preinstall: liblzma5 libcap2 libacl1 libattr1
 Preinstall: libpopt0 libelf1 liblua5_1

From e08c121b20ae60ec7ea434f210f3d534f2e2562c Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Thu, 15 Dec 2016 19:59:13 +0100
Subject: [PATCH 318/334] don't try to get stuff from /usr/lib/systemd on the
 host
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

it might not even be there…

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 templates/lxc-opensuse.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index 0774397..59180df 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -101,7 +101,7 @@ EOF
     ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount
     ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service
     ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service
-    sed -e 's/ConditionPathExists=.*//' /usr/lib/systemd/system/getty at .service > $rootfs/etc/systemd/system/getty at .service
+    sed -e 's/ConditionPathExists=.*//' $rootfs/usr/lib/systemd/system/getty at .service > $rootfs/etc/systemd/system/getty at .service
     ln -s getty at .service $rootfs/etc/systemd/system/getty at tty1.service
     ln -s ../getty at .service $rootfs/etc/systemd/system/getty.target.wants/getty at console.service
     ln -s -f ../getty at .service $rootfs/etc/systemd/system/getty.target.wants/getty at tty1.service
@@ -111,7 +111,7 @@ EOF
 
     # copy host poweroff target as sigpwr target to make shutdown work
     # see https://wiki.archlinux.org/index.php/Linux_Containers#Container_cannot_be_shutdown_if_using_systemd
-    cp /usr/lib/systemd/system/poweroff.target $rootfs/usr/lib/systemd/system/sigpwr.target
+    cp $rootfs/usr/lib/systemd/system/poweroff.target $rootfs/usr/lib/systemd/system/sigpwr.target
 
     touch $rootfs/etc/sysconfig/kernel
 

From fe864494de93b87dd3bd8e9e1af8d54d4e0450c6 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Thu, 15 Dec 2016 20:02:10 +0100
Subject: [PATCH 319/334] lxc-opensuse: rm poweroff.target -> sigpwr.target
 copy

Given commit 330ae3d350e060e5702a0e5ef5d0faeeeea8df6e:

    lxccontainer: detect if we should send SIGRTMIN+3

    This is required by systemd to cleanly shutdown. Other init systems should not
    have SIGRTMIN+3 in the blocked signals set.

we should stop poking around with sigpwr.target for systemd.

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 templates/lxc-opensuse.in | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/templates/lxc-opensuse.in b/templates/lxc-opensuse.in
index 59180df..66176c3 100644
--- a/templates/lxc-opensuse.in
+++ b/templates/lxc-opensuse.in
@@ -109,10 +109,6 @@ EOF
     ln -s ../getty at .service $rootfs/etc/systemd/system/getty.target.wants/getty at tty3.service
     ln -s ../getty at .service $rootfs/etc/systemd/system/getty.target.wants/getty at tty4.service
 
-    # copy host poweroff target as sigpwr target to make shutdown work
-    # see https://wiki.archlinux.org/index.php/Linux_Containers#Container_cannot_be_shutdown_if_using_systemd
-    cp $rootfs/usr/lib/systemd/system/poweroff.target $rootfs/usr/lib/systemd/system/sigpwr.target
-
     touch $rootfs/etc/sysconfig/kernel
 
     echo "Please change root-password !"

From f546eb34814525b04370efd20e6382a1e8aca88a Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fabrice.fontaine at orange.com>
Date: Sun, 18 Dec 2016 21:39:24 +0100
Subject: [PATCH 320/334] Add --enable-gnutls option

Previously HAVE_LIBGNUTLS was never set in config.h even if gnutls was
detected as AC_CHECK_LIB default action-if-found was overriden by
enable_gnutls=yes
This patch adds an --enable-gnutls option and will call AC_CHECK_LIB
with the default action to write HAVE_LIBGNUTLS in config.h

Signed-off-by: Fabrice Fontaine <fabrice.fontaine at orange.com>
---
 configure.ac | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2c0d9d4..e876321 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,13 +252,26 @@ if test "$enable_apparmor" = "auto" ; then
 fi
 AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"])
 
-AC_CHECK_LIB([gnutls], [gnutls_hash_fast], [enable_gnutls=yes], [enable_gnutls=no])
-
 AM_COND_IF([ENABLE_APPARMOR],
 	[AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
 	AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
 	AC_SUBST([APPARMOR_LIBS], [-lapparmor])])
 
+# GnuTLS
+AC_ARG_ENABLE([gnutls],
+	[AC_HELP_STRING([--enable-gnutls], [enable GnuTLS support [default=auto]])],
+	[], [enable_gnutls=auto])
+
+if test "$enable_gnutls" = "auto" ; then
+	AC_CHECK_LIB([gnutls], [gnutls_hash_fast], [enable_gnutls=yes], [enable_gnutls=no])
+fi
+AM_CONDITIONAL([ENABLE_GNUTLS], [test "x$enable_gnutls" = "xyes"])
+
+AM_COND_IF([ENABLE_GNUTLS],
+	[AC_CHECK_HEADER([gnutls/gnutls.h],[],[AC_MSG_ERROR([You must install the GnuTLS development package in order to compile lxc])])
+	AC_CHECK_LIB([gnutls], [gnutls_hash_fast],[],[AC_MSG_ERROR([You must install the GnuTLS development package in order to compile lxc])])
+	AC_SUBST([GNUTLS_LIBS], [-lgnutls])])
+
 # SELinux
 AC_ARG_ENABLE([selinux],
 	[AC_HELP_STRING([--enable-selinux], [enable SELinux support [default=auto]])],

From 569c5fe10365bb93d8773a7bd390353bcaafd3c5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 25 Dec 2016 12:26:17 +0100
Subject: [PATCH 321/334] tests: skip unpriv tests on broken overlay module

This mainly affects Trusty. The 3.13 kernel has a broken overlay module which
does not handle symlinks correctly. This is a problem for containers that use
an overlay based rootfs since safe_mount() uses /proc/<pid>/fd/<fd-number> in
its calls to mount().

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/tests/lxc-test-unpriv | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/tests/lxc-test-unpriv b/src/tests/lxc-test-unpriv
index afe86fa..8ba216f 100755
--- a/src/tests/lxc-test-unpriv
+++ b/src/tests/lxc-test-unpriv
@@ -27,6 +27,41 @@ if [ $(id -u) -ne 0 ]; then
 	echo "ERROR: Must run as root."
 	exit 1
 fi
+
+# Test if we're using an overlayfs module that handles symlinks correctly. If
+# not, we skip these tests since overlay clones will not work correctly.
+if modprobe -q overlayfs; then
+        TMPDIR=$(mktemp -d)
+
+        MOUNTDIR="${TMPDIR}/ovl_symlink_test"
+
+        mkdir ${MOUNTDIR}
+
+        mount -t tmpfs none ${MOUNTDIR}
+
+        mkdir "${MOUNTDIR}/lowerdir" "${MOUNTDIR}/upperdir" "${MOUNTDIR}/overlayfs"
+        mount -t overlayfs -o lowerdir="${MOUNTDIR}/lowerdir",upperdir="${MOUNTDIR}/upperdir" none "${MOUNTDIR}/overlayfs"
+
+        CORRECT_LINK_TARGET="${MOUNTDIR}/overlayfs/dummy_file"
+        exec 9> "${CORRECT_LINK_TARGET}"
+
+        DETECTED_LINK_TARGET=$(readlink -q /proc/$$/fd/9)
+
+        # cleanup
+        exec 9>&-
+
+        umount "${MOUNTDIR}/overlayfs"
+        umount ${MOUNTDIR}
+
+        rmdir ${MOUNTDIR}
+
+        # This overlay module does not correctly handle symlinks, so skip the
+        # tests.
+        if [ "${DETECTED_LINK_TARGET}" != "${CORRECT_LINK_TARGET}" ]; then
+                exit 0
+        fi
+fi
+
 which newuidmap >/dev/null 2>&1 || { echo "'newuidmap' command is missing" >&2; exit 1; }
 
 DONE=0

From f53c6ce7afe1833731a4d47e0d796c8dac7ac4c5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 3 Jan 2017 11:08:25 +0100
Subject: [PATCH 322/334] conf: fix suggest_default_idmap()

We need to remove the newline otherwise lxc_safe_uint() will fail as it detects
an invalid (non-numeric) char in the string.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index abff1c5..3e93277 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4513,6 +4513,7 @@ void suggest_default_idmap(void)
 		return;
 	}
 	while (getline(&line, &len, f) != -1) {
+		size_t no_newline = 0;
 		char *p = strchr(line, ':'), *p2;
 		if (*line == '#')
 			continue;
@@ -4529,6 +4530,9 @@ void suggest_default_idmap(void)
 		p2++;
 		if (!*p2)
 			continue;
+		no_newline = strcspn(p2, "\n");
+		p2[no_newline] = '\0';
+
 		if (lxc_safe_uint(p, &uid) < 0)
 			WARN("Could not parse UID.");
 		if (lxc_safe_uint(p2, &urange) < 0)
@@ -4544,6 +4548,7 @@ void suggest_default_idmap(void)
 		return;
 	}
 	while (getline(&line, &len, f) != -1) {
+		size_t no_newline = 0;
 		char *p = strchr(line, ':'), *p2;
 		if (*line == '#')
 			continue;
@@ -4560,6 +4565,9 @@ void suggest_default_idmap(void)
 		p2++;
 		if (!*p2)
 			continue;
+		no_newline = strcspn(p2, "\n");
+		p2[no_newline] = '\0';
+
 		if (lxc_safe_uint(p, &gid) < 0)
 			WARN("Could not parse GID.");
 		if (lxc_safe_uint(p2, &grange) < 0)

From 03bd7f728ed8605210c93fec739c612972484e8c Mon Sep 17 00:00:00 2001
From: Po-Hsu Lin <po-hsu.lin at canonical.com>
Date: Wed, 4 Jan 2017 19:23:04 +0800
Subject: [PATCH 323/334] python3-lxc: fix api_test.py on s390x

The api_test.py script uses Trusty release by default, which does not
have s390x image. Switch to Xenial to solve this.

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 src/python-lxc/examples/api_test.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/python-lxc/examples/api_test.py b/src/python-lxc/examples/api_test.py
index b8b5ee6..cd7ea77 100755
--- a/src/python-lxc/examples/api_test.py
+++ b/src/python-lxc/examples/api_test.py
@@ -66,7 +66,7 @@
 print("Creating rootfs using 'download', arch=%s" % arch)
 container.create("download", 0,
                  {"dist": "ubuntu",
-                  "release": "trusty",
+                  "release": "xenial",
                   "arch": arch})
 
 assert(container.defined)

From bfc42ff8c63894834cd73db245459904ef6b94b5 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 4 Jan 2017 10:28:25 +0100
Subject: [PATCH 324/334] tree-wide: Sic semper assertis!

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/console.c          |  9 ++++++---
 src/lxc/criu.c             |  1 -
 src/lxc/log.c              |  4 ++--
 src/lxc/lxccontainer.c     | 10 +++++++---
 src/lxc/tools/lxc_attach.c |  7 ++++---
 src/lxc/utils.c            | 11 ++++++++---
 6 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/src/lxc/console.c b/src/lxc/console.c
index 052512e..908ead0 100644
--- a/src/lxc/console.c
+++ b/src/lxc/console.c
@@ -21,7 +21,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -577,7 +576,9 @@ int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
 	struct lxc_tty_state *ts = cbdata;
 	char c;
 
-	assert(fd == ts->stdinfd);
+	if (fd != ts->stdinfd)
+		return 1;
+
 	if (lxc_read_nointr(ts->stdinfd, &c, 1) <= 0)
 		return 1;
 
@@ -607,7 +608,9 @@ int lxc_console_cb_tty_master(int fd, uint32_t events, void *cbdata,
 	char buf[1024];
 	int r, w;
 
-	assert(fd == ts->masterfd);
+	if (fd != ts->masterfd)
+		return 1;
+
 	r = lxc_read_nointr(fd, buf, sizeof(buf));
 	if (r <= 0)
 		return 1;
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index f76eb82..8a0702f 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -21,7 +21,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #define _GNU_SOURCE
-#include <assert.h>
 #include <inttypes.h>
 #include <linux/limits.h>
 #include <sched.h>
diff --git a/src/lxc/log.c b/src/lxc/log.c
index 59e659a..678bec7 100644
--- a/src/lxc/log.c
+++ b/src/lxc/log.c
@@ -23,7 +23,6 @@
 
 #define _GNU_SOURCE
 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
-#include <assert.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <errno.h>
@@ -392,7 +391,8 @@ static int __lxc_log_set_file(const char *fname, int create_dirs)
 		lxc_log_close();
 	}
 
-	assert(fname != NULL);
+	if (!fname)
+		return -1;
 
 	if (strlen(fname) == 0) {
 		log_fname = NULL;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index d96d23e..2a376eb 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -19,7 +19,6 @@
  */
 
 #define _GNU_SOURCE
-#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -4319,7 +4318,7 @@ int list_active_containers(const char *lxcpath, char ***nret,
 	char *line = NULL;
 	char **ct_name = NULL;
 	size_t len = 0;
-	struct lxc_container *c;
+	struct lxc_container *c = NULL;
 	bool is_hashed;
 
 	if (!lxcpath)
@@ -4402,7 +4401,12 @@ int list_active_containers(const char *lxcpath, char ***nret,
 		cret_cnt++;
 	}
 
-	assert(!nret || !cret || cret_cnt == ct_name_cnt);
+	if (nret && cret && cret_cnt != ct_name_cnt) {
+		if (c)
+			lxc_container_put(c);
+		goto free_cret_list;
+	}
+
 	ret = ct_name_cnt;
 	if (nret)
 		*nret = ct_name;
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 4dd3883..acc3dcf 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -23,7 +23,6 @@
 
 #include "config.h"
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -83,7 +82,8 @@ static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
 {
 	ssize_t count = 0;
 
-	assert(array);
+	if (!array)
+		return -1;
 
 	if (*array)
 		for (; (*array)[count]; count++);
@@ -99,7 +99,8 @@ static int add_to_simple_array(char ***array, ssize_t *capacity, char *value)
 		*capacity = new_capacity;
 	}
 
-	assert(*array);
+	if (!(*array))
+		return -1;
 
 	(*array)[count] = value;
 	return 0;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 7c2098e..2a0f05a 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -23,7 +23,6 @@
 
 #include "config.h"
 
-#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -639,10 +638,16 @@ char *lxc_string_replace(const char *needle, const char *replacement, const char
 	/* make sure we did the same thing twice,
 	 * once for calculating length, the other
 	 * time for copying data */
-	assert(saved_len == len);
+	if (saved_len != len) {
+		free(result);
+		return NULL;
+	}
 	/* make sure we didn't overwrite any buffer,
 	 * due to calloc the string should be 0-terminated */
-	assert(result[len] == '\0');
+	if (result[len] != '\0') {
+		free(result);
+		return NULL;
+	}
 
 	return result;
 }

From 9d1d5bcad28d88bc25cb8e4dc54d044485ccfd41 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 4 Jan 2017 16:28:50 +0100
Subject: [PATCH 325/334] tools: only check for O_RDONLY

On some Android systems the lxc folders where containers are stored might be
read-only and so checking for O_RDWR, will effectively make the tools useless
on these systems, so let's dumb the check down to O_RDONLY.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/tools/lxc_attach.c   | 2 +-
 src/lxc/tools/lxc_copy.c     | 2 +-
 src/lxc/tools/lxc_create.c   | 2 +-
 src/lxc/tools/lxc_snapshot.c | 2 +-
 src/lxc/tools/lxc_start.c    | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index acc3dcf..ca66201 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -396,7 +396,7 @@ int main(int argc, char *argv[])
 	lxc_log_options_no_override();
 
 	if (geteuid()) {
-		if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+		if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
 			if (!my_args.quiet)
 				fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
 			exit(EXIT_FAILURE);
diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 7427cd4..c7a47d5 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -173,7 +173,7 @@ int main(int argc, char *argv[])
 	lxc_log_options_no_override();
 
 	if (geteuid()) {
-		if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+		if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
 			if (!my_args.quiet)
 				fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
 			exit(ret);
diff --git a/src/lxc/tools/lxc_create.c b/src/lxc/tools/lxc_create.c
index 6e8acf0..b8795c4 100644
--- a/src/lxc/tools/lxc_create.c
+++ b/src/lxc/tools/lxc_create.c
@@ -252,7 +252,7 @@ int main(int argc, char *argv[])
 		if (mkdir_p(my_args.lxcpath[0], 0755)) {
 			exit(EXIT_FAILURE);
 		}
-		if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+		if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
 			fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
 			exit(EXIT_FAILURE);
 		}
diff --git a/src/lxc/tools/lxc_snapshot.c b/src/lxc/tools/lxc_snapshot.c
index 1a79a7a..6948d19 100644
--- a/src/lxc/tools/lxc_snapshot.c
+++ b/src/lxc/tools/lxc_snapshot.c
@@ -95,7 +95,7 @@ int main(int argc, char *argv[])
 	lxc_log_options_no_override();
 
 	if (geteuid()) {
-		if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+		if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
 			fprintf(stderr, "You lack access to %s\n",
 				my_args.lxcpath[0]);
 			exit(EXIT_FAILURE);
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index c85305b..f5aa24b 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -231,7 +231,7 @@ int main(int argc, char *argv[])
 		exit(err);
 	lxc_log_options_no_override();
 
-	if (access(my_args.lxcpath[0], O_RDWR) < 0) {
+	if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
 		if (!my_args.quiet)
 			fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
 		exit(err);

From 274f480f8419a80e6626cf4abe7984e87d639aeb Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 2 Jan 2017 15:12:10 +0100
Subject: [PATCH 326/334] utils: add uid, gid, group convenience wrappers

This commit adds lxc_switch_uid_gid() which allows to switch the uid and gid of
a process via setuid() and setgid() and lxc_setgroups() which allows to set
groups via setgroups(). The main advantage is that they nicely log the switches
they perform.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/utils.c | 30 ++++++++++++++++++++++++++++++
 src/lxc/utils.h |  4 ++++
 2 files changed, 34 insertions(+)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 2a0f05a..0227c32 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -26,6 +26,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <grp.h>
 #include <libgen.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -2053,3 +2054,32 @@ int lxc_safe_long(const char *numstr, long int *converted)
 	*converted = sli;
 	return 0;
 }
+
+int lxc_switch_uid_gid(uid_t uid, gid_t gid)
+{
+	if (setgid(gid) < 0) {
+		SYSERROR("Failed to switch to gid %d.", gid);
+		return -errno;
+	}
+	NOTICE("Switched to gid %d.", gid);
+
+	if (setuid(uid) < 0) {
+		SYSERROR("Failed to switch to uid %d.", uid);
+		return -errno;
+	}
+	NOTICE("Switched to uid %d.", uid);
+
+	return 0;
+}
+
+/* Simple covenience function which enables uniform logging. */
+int lxc_setgroups(int size, gid_t list[])
+{
+	if (setgroups(size, list) < 0) {
+		SYSERROR("Failed to setgroups().");
+		return -errno;
+	}
+	NOTICE("Dropped additional groups.");
+
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index b7dcd5d..2b56905 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -327,4 +327,8 @@ int lxc_safe_uint(const char *numstr, unsigned int *converted);
 int lxc_safe_int(const char *numstr, int *converted);
 int lxc_safe_long(const char *numstr, long int *converted);
 
+/* Switch to a new uid and gid. */
+int lxc_switch_uid_gid(uid_t uid, gid_t gid);
+int lxc_setgroups(int size, gid_t list[]);
+
 #endif /* __LXC_UTILS_H */

From a5828a51503b913c79a501db8b7371326e8dfa56 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 2 Jan 2017 15:14:22 +0100
Subject: [PATCH 327/334] start: fix execute and improve setgroups() calls

lxc_execute() and lxc-execute where broken when a user tried to switch to a
non-root uid/gid. This prevented necessary setup operations like mounting the
rootfs which require root in the user namespace. This commit separates
switching to root in the user namespace from switching to the requested uid/gid
by lxc_execute().
This should be safe: Once we switched to root in the user namespace via
setuid() and then switch to a non-root uid/gid in the user namespace for
lxc_execute() via setuid() we cannot regain root privileges again. So we can
only make us safer (Unless I forget about some very intricate user namespace
nonsense; which is not as unlikely as I try to make it sound.).

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/start.c | 57 +++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 0ca5ba0..53059e1 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -755,32 +755,17 @@ static int do_start(void *data)
 		goto out_warn_father;
 
 	/* If we are in a new user namespace, become root there to have
-	 * privilege over our namespace. When using lxc-execute we default to
-	 * root, but this can be overriden using the lxc.init_uid and
-	 * lxc.init_gid configuration options.
+	 * privilege over our namespace.
 	 */
 	if (!lxc_list_empty(&handler->conf->id_map)) {
-		gid_t new_gid = 0;
-		if (handler->conf->is_execute && handler->conf->init_gid)
-			new_gid = handler->conf->init_gid;
-
-		uid_t new_uid = 0;
-		if (handler->conf->is_execute && handler->conf->init_uid)
-			new_uid = handler->conf->init_uid;
-
-		NOTICE("Switching to uid=%d and gid=%d in new user namespace.", new_uid, new_gid);
-		if (setgid(new_gid)) {
-			SYSERROR("Failed to setgid().");
+		if (lxc_switch_uid_gid(0, 0) < 0)
 			goto out_warn_father;
-		}
-		if (setuid(new_uid)) {
-			SYSERROR("Failed to setuid().");
-			goto out_warn_father;
-		}
-		if (setgroups(0, NULL)) {
-			SYSERROR("Failed to setgroups().");
+
+		/* Drop groups only after we switched to a valid gid in the new
+		 * user namespace.
+		 */
+		if (lxc_setgroups(0, NULL) < 0)
 			goto out_warn_father;
-		}
 	}
 
 	if (access(handler->lxcpath, X_OK)) {
@@ -875,6 +860,34 @@ static int do_start(void *data)
 		goto out_warn_father;
 	}
 
+	/* The container has been setup. We can now switch to an unprivileged
+	 * uid/gid.
+	 */
+	if (handler->conf->is_execute) {
+		uid_t new_uid = 0;
+		gid_t new_gid = 0;
+
+		if (handler->conf->init_uid > 0)
+			new_uid = handler->conf->init_uid;
+
+		if (handler->conf->init_gid > 0)
+			new_gid = handler->conf->init_gid;
+
+		/* If we are in a new user namespace we already dropped all
+		 * groups when we switched to root in the new user namespace
+		 * further above. Only drop groups if we can, so ensure that we
+		 * have necessary privilege.
+		 */
+		bool can_setgroups = ((getuid() == 0) && (getgid() == 0));
+		if (lxc_list_empty(&handler->conf->id_map) && can_setgroups) {
+			if (lxc_setgroups(0, NULL) < 0)
+				goto out_warn_father;
+		}
+
+		if (lxc_switch_uid_gid(new_uid, new_gid) < 0)
+			goto out_warn_father;
+	}
+
 	/* The clearenv() and putenv() calls have been moved here to allow us to
 	 * use environment variables passed to the various hooks, such as the
 	 * start hook above. Not all of the variables like CONFIG_PATH or ROOTFS

From 3bce0fe96d3648f783ddb8b1c962bf5ac7269cfa Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Jan 2017 12:40:37 +0100
Subject: [PATCH 328/334] caps: add lxc_cap_is_set()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/caps.c | 34 +++++++++++++++++++++++++++++-----
 src/lxc/caps.h | 12 ++++++++++++
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/src/lxc/caps.c b/src/lxc/caps.c
index 9712e11..73b5516 100644
--- a/src/lxc/caps.c
+++ b/src/lxc/caps.c
@@ -22,20 +22,21 @@
  */
 
 #define _GNU_SOURCE
-#include <unistd.h>
+#include "config.h"
+
+#include <errno.h>
+#include <limits.h>
 #include <fcntl.h>
 #include <stdlib.h>
-#include <limits.h>
+#include <unistd.h>
 #include <sys/prctl.h>
-#include <errno.h>
 
-#include "config.h"
+#include "caps.h"
 #include "log.h"
 
 lxc_log_define(lxc_caps, lxc);
 
 #if HAVE_SYS_CAPABILITY_H
-#include <sys/capability.h>
 
 #ifndef PR_CAPBSET_READ
 #define PR_CAPBSET_READ 23
@@ -208,4 +209,27 @@ int lxc_caps_last_cap(void)
 	return last_cap;
 }
 
+bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag)
+{
+	int ret;
+	cap_t caps;
+	cap_flag_value_t flagval;
+
+	caps = cap_get_proc();
+	if (!caps) {
+		ERROR("Failed to perform cap_get_proc(): %s.", strerror(errno));
+		return false;
+	}
+
+	ret = cap_get_flag(caps, cap, flag, &flagval);
+	if (ret < 0) {
+		ERROR("Failed to perform cap_get_flag(): %s.", strerror(errno));
+		cap_free(caps);
+		return false;
+	}
+
+	cap_free(caps);
+	return flagval == CAP_SET;
+}
+
 #endif
diff --git a/src/lxc/caps.h b/src/lxc/caps.h
index f39fec6..390dbdd 100644
--- a/src/lxc/caps.h
+++ b/src/lxc/caps.h
@@ -20,17 +20,23 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+
 #include "config.h"
+#include <stdbool.h>
 
 #ifndef __LXC_CAPS_H
 #define __LXC_CAPS_H
 
 #if HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+
 extern int lxc_caps_down(void);
 extern int lxc_caps_up(void);
 extern int lxc_caps_init(void);
 
 extern int lxc_caps_last_cap(void);
+
+extern bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag);
 #else
 static inline int lxc_caps_down(void) {
 	return 0;
@@ -45,6 +51,12 @@ static inline int lxc_caps_init(void) {
 static inline int lxc_caps_last_cap(void) {
 	return 0;
 }
+
+typedef int cap_value_t;
+typedef int cap_flag_t;
+static inline bool lxc_cap_is_set(cap_value_t cap, cap_flag_t flag) {
+	return true;
+}
 #endif
 
 #define lxc_priv(__lxc_function)			\

From 3e14d7594a271140ce2a921b058c1ec3ea3e99d8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Jan 2017 12:41:18 +0100
Subject: [PATCH 329/334] start: check for CAP_SETGID before setgroups()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/start.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 53059e1..c2c14a7 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -864,22 +864,17 @@ static int do_start(void *data)
 	 * uid/gid.
 	 */
 	if (handler->conf->is_execute) {
-		uid_t new_uid = 0;
-		gid_t new_gid = 0;
-
-		if (handler->conf->init_uid > 0)
-			new_uid = handler->conf->init_uid;
-
-		if (handler->conf->init_gid > 0)
-			new_gid = handler->conf->init_gid;
+		bool have_cap_setgid;
+		uid_t new_uid = handler->conf->init_uid;
+		gid_t new_gid = handler->conf->init_gid;
 
 		/* If we are in a new user namespace we already dropped all
 		 * groups when we switched to root in the new user namespace
 		 * further above. Only drop groups if we can, so ensure that we
 		 * have necessary privilege.
 		 */
-		bool can_setgroups = ((getuid() == 0) && (getgid() == 0));
-		if (lxc_list_empty(&handler->conf->id_map) && can_setgroups) {
+		have_cap_setgid = lxc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE);
+		if (lxc_list_empty(&handler->conf->id_map) && have_cap_setgid) {
 			if (lxc_setgroups(0, NULL) < 0)
 				goto out_warn_father;
 		}

From 2bce26ed17d9ca3bcc14e4e0e6c31c1d6525378f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 11 Jan 2017 16:20:20 +0100
Subject: [PATCH 330/334] tools/lxc-start: remove c->is_defined(c) check

We do not check here whether the container is defined, because we support
volatile containers. Which means the container does not need to be created for
it to be started. You can just pass a configuration file as argument and start
the container right away.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/tools/lxc_start.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index f5aa24b..3c17ea0 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -286,10 +286,11 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	if (!c->is_defined(c)) {
-		fprintf(stderr, "Error: container %s is not defined\n", c->name);
-		goto out;
-	}
+	/* We do not check here whether the container is defined, because we
+	 * support volatile containers. Which means the container does not need
+	 * to be created for it to be started. You can just pass a configuration
+	 * file as argument and start the container right away.
+	 */
 
 	if (!c->may_control(c)) {
 		fprintf(stderr, "Insufficent privileges to control %s\n", c->name);

From 1caa57e6b2db972c261d5143f2cd6774a422f660 Mon Sep 17 00:00:00 2001
From: Evgeni Golov <evgeni at debian.org>
Date: Thu, 12 Jan 2017 12:50:15 +0100
Subject: [PATCH 331/334] add cgroupfs-mount to Should-Start/Stop sysvinit LSB
 headers

otherwise init might try to start the containers before cgroupfs was
mounted.

Debian-Bug: https://bugs.debian.org/850212

Signed-off-by: Evgeni Golov <evgeni at debian.org>
---
 config/init/sysvinit/lxc-containers.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/init/sysvinit/lxc-containers.in b/config/init/sysvinit/lxc-containers.in
index a7502a8..f793d20 100644
--- a/config/init/sysvinit/lxc-containers.in
+++ b/config/init/sysvinit/lxc-containers.in
@@ -9,8 +9,8 @@
 # Provides: lxc
 # Required-Start: $syslog $remote_fs
 # Required-Stop: $syslog $remote_fs
-# Should-Start:
-# Should-Stop:
+# Should-Start: cgroupfs-mount
+# Should-Stop: cgroupfs-mount
 # Default-Start: 2 3 4 5
 # Default-Stop: 0 1 6
 # Short-Description: Bring up/down LXC autostart containers

From d2222fae286ae13dcad8dce7a256201a18788110 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <siarheit at google.com>
Date: Sat, 21 Jan 2017 11:57:13 +0000
Subject: [PATCH 332/334] Use AC_HEADER_MAJOR to detect
 major()/minor()/makedev()

Before the change build failed on Gentoo as:

  bdev/lxclvm.c: In function 'lvm_detect':
  bdev/lxclvm.c:140:4: error: implicit declaration of function 'major' [-Werror=implicit-function-declaration]
    major(statbuf.st_rdev), minor(statbuf.st_rdev));
    ^~~~~
  bdev/lxclvm.c:140:28: error: implicit declaration of function 'minor' [-Werror=implicit-function-declaration]
    major(statbuf.st_rdev), minor(statbuf.st_rdev));
                            ^~~~~

glibc plans to remove <sys/sysmacros.h> from glibc's <sys/types.h>:
    https://sourceware.org/ml/libc-alpha/2015-11/msg00253.html

Gentoo already applied glibc patch to experimental glibc-2.24
to start preparingfor the change.

Autoconf has AC_HEADER_MAJOR to find out which header defines
reqiured macros:
    https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Headers.html

This change should also increase portability across other libcs.

Bug: https://bugs.gentoo.org/604360
Signed-off-by: Sergei Trofimovich <siarheit at google.com>
---
 configure.ac           | 3 +++
 src/lxc/bdev/lxclvm.c  | 9 +++++++++
 src/lxc/conf.c         | 8 ++++++++
 src/lxc/lxccontainer.c | 8 ++++++++
 4 files changed, 28 insertions(+)

diff --git a/configure.ac b/configure.ac
index e876321..1df99cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -632,6 +632,9 @@ AC_CHECK_DECLS([PR_CAPBSET_DROP], [], [], [#include <sys/prctl.h>])
 # Check for some headers
 AC_CHECK_HEADERS([sys/signalfd.h pty.h ifaddrs.h sys/capability.h sys/memfd.h sys/personality.h utmpx.h sys/timerfd.h])
 
+# lookup major()/minor()/makedev()
+AC_HEADER_MAJOR
+
 # Check for some syscalls functions
 AC_CHECK_FUNCS([setns pivot_root sethostname unshare rand_r confstr faccessat gettid memfd_create])
 
diff --git a/src/lxc/bdev/lxclvm.c b/src/lxc/bdev/lxclvm.c
index db0e21c..75de17f 100644
--- a/src/lxc/bdev/lxclvm.c
+++ b/src/lxc/bdev/lxclvm.c
@@ -32,10 +32,19 @@
 #include <sys/wait.h>
 
 #include "bdev.h"
+#include "config.h"
 #include "log.h"
 #include "lxclvm.h"
 #include "utils.h"
 
+/* major()/minor() */
+#ifdef MAJOR_IN_MKDEV
+#    include <sys/mkdev.h>
+#endif
+#ifdef MAJOR_IN_SYSMACROS
+#    include <sys/sysmacros.h>
+#endif
+
 lxc_log_define(lxclvm, lxc);
 
 extern char *dir_new_path(char *src, const char *oldname, const char *name,
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 3e93277..a93124b 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -52,6 +52,14 @@
 #include <sys/utsname.h>
 #include <sys/wait.h>
 
+/* makedev() */
+#ifdef MAJOR_IN_MKDEV
+#    include <sys/mkdev.h>
+#endif
+#ifdef MAJOR_IN_SYSMACROS
+#    include <sys/sysmacros.h>
+#endif
+
 #ifdef HAVE_STATVFS
 #include <sys/statvfs.h>
 #endif
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 2a376eb..0dbbf2c 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -60,6 +60,14 @@
 #include "utils.h"
 #include "version.h"
 
+/* major()/minor() */
+#ifdef MAJOR_IN_MKDEV
+#    include <sys/mkdev.h>
+#endif
+#ifdef MAJOR_IN_SYSMACROS
+#    include <sys/sysmacros.h>
+#endif
+
 #if HAVE_IFADDRS_H
 #include <ifaddrs.h>
 #else

From 4e17526486d0c5b50e3713b782e1f79ac52e139e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 23 Jan 2017 12:44:55 -0500
Subject: [PATCH 333/334] change version to 2.0.7 in configure.ac
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 1df99cc..42ece7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 m4_define([lxc_devel], 0)
 m4_define([lxc_version_major], 2)
 m4_define([lxc_version_minor], 0)
-m4_define([lxc_version_micro], 6)
+m4_define([lxc_version_micro], 7)
 m4_define([lxc_version_beta], [])
 
 m4_define([lxc_abi_major], 1)

From 38503997f3e7b67df9c7733da2bec107275b3784 Mon Sep 17 00:00:00 2001
From: Nevenchanniy Aleksandr <a.nevenchanniy at rambler-co.ru>
Date: Sat, 6 May 2017 19:08:04 +0300
Subject: [PATCH 334/334] [lxc-top] Add memsw monitoing

Linux kernel have unlimited default to memory.memsw.limit_in_bytes
So we need show swap usage in lxc-top.
---
 src/lxc/tools/lxc_top.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c
index d8e7247..cb6ff65 100644
--- a/src/lxc/tools/lxc_top.c
+++ b/src/lxc/tools/lxc_top.c
@@ -50,6 +50,8 @@ lxc_log_define(lxc_top_ui, lxc);
 struct stats {
 	uint64_t mem_used;
 	uint64_t mem_limit;
+	uint64_t memsw_used;
+	uint64_t memsw_limit;
 	uint64_t kmem_used;
 	uint64_t kmem_limit;
 	uint64_t cpu_use_nanos;
@@ -104,12 +106,13 @@ lxc-top monitors the state of the active containers\n\
 \n\
 Options :\n\
   -d, --delay     delay in seconds between refreshes (default: 3.0)\n\
-  -s, --sort      sort by [n,c,b,m] (default: n) where\n\
+  -s, --sort      sort by [n,c,b,m,w] (default: n) where\n\
                   n = Name\n\
                   c = CPU use\n\
                   b = Block I/O use\n\
                   m = Memory use\n\
                   k = Kernel memory use\n\
+                  w = Memory+Swap use\n\
   -r, --reverse   sort in reverse (descending) order\n",
 	.name     = ".*",
 	.options  = my_longopts,
@@ -267,6 +270,8 @@ static void stats_get(struct lxc_container *c, struct ct *ct, struct stats *tota
 	ct->c = c;
 	ct->stats->mem_used      = stat_get_int(c, "memory.usage_in_bytes");
 	ct->stats->mem_limit     = stat_get_int(c, "memory.limit_in_bytes");
+	ct->stats->memsw_used    = stat_get_int(c, "memory.memsw.usage_in_bytes");
+	ct->stats->memsw_limit   = stat_get_int(c, "memory.memsw.limit_in_bytes");
 	ct->stats->kmem_used     = stat_get_int(c, "memory.kmem.usage_in_bytes");
 	ct->stats->kmem_limit    = stat_get_int(c, "memory.kmem.limit_in_bytes");
 	ct->stats->cpu_use_nanos = stat_get_int(c, "cpuacct.usage");
@@ -277,6 +282,8 @@ static void stats_get(struct lxc_container *c, struct ct *ct, struct stats *tota
 	if (total) {
 		total->mem_used      = total->mem_used      + ct->stats->mem_used;
 		total->mem_limit     = total->mem_limit     + ct->stats->mem_limit;
+		total->memsw_used    = total->memsw_used    + ct->stats->memsw_used;
+		total->memsw_limit   = total->memsw_limit   + ct->stats->memsw_limit;
 		total->kmem_used     = total->kmem_used     + ct->stats->kmem_used;
 		total->kmem_limit    = total->kmem_limit    + ct->stats->kmem_limit;
 		total->cpu_use_nanos = total->cpu_use_nanos + ct->stats->cpu_use_nanos;
@@ -290,11 +297,15 @@ static void stats_print_header(struct stats *stats)
 {
 	printf(TERMRVRS TERMBOLD);
 	printf("%-18s %12s %12s %12s %14s %10s", "Container", "CPU",  "CPU",  "CPU",  "BlkIO", "Mem");
+	if (stats->memsw_used > 0)
+		printf(" %10s", "MemSW");
 	if (stats->kmem_used > 0)
 		printf(" %10s", "KMem");
 	printf("\n");
 
 	printf("%-18s %12s %12s %12s %14s %10s", "Name",      "Used", "Sys",  "User", "Total", "Used");
+	if (stats->memsw_used > 0)
+		printf(" %10s", "Used");
 	if (stats->kmem_used > 0)
 		printf(" %10s", "Used");
 	printf("\n");
@@ -307,6 +318,7 @@ static void stats_print(const char *name, const struct stats *stats,
 	char blkio_str[20];
 	char mem_used_str[20];
 	char kmem_used_str[20];
+	char memsw_used_str[20];
 
 	size_humanize(stats->blkio, blkio_str, sizeof(blkio_str));
 	size_humanize(stats->mem_used, mem_used_str, sizeof(mem_used_str));
@@ -318,6 +330,10 @@ static void stats_print(const char *name, const struct stats *stats,
 	       (float)stats->cpu_use_user / USER_HZ,
 	       blkio_str,
 	       mem_used_str);
+	if (total->memsw_used > 0) {
+		size_humanize(stats->memsw_used, memsw_used_str, sizeof(memsw_used_str));
+		printf(" %10s", memsw_used_str);
+	}
 	if (total->kmem_used > 0) {
 		size_humanize(stats->kmem_used, kmem_used_str, sizeof(kmem_used_str));
 		printf(" %10s", kmem_used_str);
@@ -374,6 +390,16 @@ static int cmp_kmemory(const void *sct1, const void *sct2)
 	return ct1->stats->kmem_used < ct2->stats->kmem_used;
 }
 
+static int cmp_memorysw(const void *sct1, const void *sct2)
+{
+	const struct ct *ct1 = sct1;
+	const struct ct *ct2 = sct2;
+
+	if (sort_reverse)
+		return ct2->stats->memsw_used < ct1->stats->memsw_used;
+	return ct1->stats->memsw_used < ct2->stats->memsw_used;
+}
+
 static void ct_sort(int active)
 {
 	int (*cmp_func)(const void *, const void *);
@@ -385,6 +411,7 @@ static void ct_sort(int active)
 	case 'b': cmp_func = cmp_blkio; break;
 	case 'm': cmp_func = cmp_memory; break;
 	case 'k': cmp_func = cmp_kmemory; break;
+	case 'w': cmp_func = cmp_memorysw; break;
 	}
 	qsort(ct, active, sizeof(*ct), (int (*)(const void *,const void *))cmp_func);
 }
@@ -501,6 +528,7 @@ int main(int argc, char *argv[])
 		case 'b':
 		case 'm':
 		case 'k':
+		case 'w':
 			if (sort_by == in_char)
 				sort_reverse ^= 1;
 			else


More information about the lxc-devel mailing list