[lxc-devel] [lxc/master] cleanup macros and rexec fixes

brauner on Github lxc-bot at linuxcontainers.org
Mon Feb 18 12:33:48 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190218/0a154816/attachment-0001.bin>
-------------- next part --------------
From d85617bc6760745047745b6ea6f268bedde123ef Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 11:32:45 +0100
Subject: [PATCH 01/19] start: move variable into tighter scope

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/start.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 89262c7368..928702559b 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -452,7 +452,6 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
 	size_t retlen;
 	ssize_t ret;
 	struct lxc_list *cur, *next;
-	struct lxc_state_client *client;
 	struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
 
 	if (state == THAWED)
@@ -472,7 +471,7 @@ int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
 		return -E2BIG;
 
 	lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
-		client = cur->elem;
+		struct lxc_state_client *client = cur->elem;
 
 		if (client->states[state] == 0) {
 			TRACE("State %s not registered for state client %d",

From 83c11f1d041027d66fd72498f282f8989dc0e4d2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 11:36:18 +0100
Subject: [PATCH 02/19] af_unix: use __do_free

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

diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c
index 02f32c4542..3b00d64fb5 100644
--- a/src/lxc/af_unix.c
+++ b/src/lxc/af_unix.c
@@ -37,6 +37,7 @@
 
 #include "config.h"
 #include "log.h"
+#include "memory_utils.h"
 #include "raw_syscalls.h"
 #include "utils.h"
 
@@ -155,12 +156,11 @@ int lxc_abstract_unix_connect(const char *path)
 int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
 			       void *data, size_t size)
 {
-	int ret;
+	__do_free char *cmsgbuf;
 	struct msghdr msg;
 	struct iovec iov;
 	struct cmsghdr *cmsg = NULL;
 	char buf[1] = {0};
-	char *cmsgbuf;
 	size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int));
 
 	memset(&msg, 0, sizeof(msg));
@@ -189,20 +189,18 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
 
-	ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
-	free(cmsgbuf);
-	return ret;
+	return sendmsg(fd, &msg, MSG_NOSIGNAL);
 }
 
 int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
 			       void *data, size_t size)
 {
+	__do_free char *cmsgbuf;
 	int ret;
 	struct msghdr msg;
 	struct iovec iov;
 	struct cmsghdr *cmsg = NULL;
 	char buf[1] = {0};
-	char *cmsgbuf;
 	size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int));
 
 	memset(&msg, 0, sizeof(msg));
@@ -234,7 +232,6 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
 		memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
 
 out:
-	free(cmsgbuf);
 	return ret;
 }
 

From cd8f5663ab6b5c8712305b4f8321bec8e0ac7565 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 11:46:15 +0100
Subject: [PATCH 03/19] attach: use __do_free

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/attach.c | 67 ++++++++++++++++--------------------------------
 1 file changed, 22 insertions(+), 45 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index eb5ae74600..756ccfbcfe 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -59,6 +59,7 @@
 #include "lxcseccomp.h"
 #include "macro.h"
 #include "mainloop.h"
+#include "memory_utils.h"
 #include "namespace.h"
 #include "raw_syscalls.h"
 #include "syscall_wrappers.h"
@@ -76,31 +77,28 @@ static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_D
 
 static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 {
+	__do_free char *line = NULL;
+	__do_fclose FILE *proc_file = NULL;
 	int ret;
 	bool found;
-	FILE *proc_file;
 	char proc_fn[LXC_PROC_STATUS_LEN];
+	struct lxc_proc_context_info *info;
 	size_t line_bufsz = 0;
-	char *line = NULL;
-	struct lxc_proc_context_info *info = NULL;
 
 	/* Read capabilities. */
 	ret = snprintf(proc_fn, LXC_PROC_STATUS_LEN, "/proc/%d/status", pid);
 	if (ret < 0 || ret >= LXC_PROC_STATUS_LEN)
-		goto on_error;
+		return NULL;
 
 	proc_file = fopen(proc_fn, "r");
 	if (!proc_file) {
-		SYSERROR("Could not open %s", proc_fn);
-		goto on_error;
+		SYSERROR("Failed to open %s", proc_fn);
+		return NULL;
 	}
 
 	info = calloc(1, sizeof(*info));
-	if (!info) {
-		SYSERROR("Could not allocate memory");
-		fclose(proc_file);
+	if (!info)
 		return NULL;
-	}
 
 	found = false;
 
@@ -112,13 +110,10 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 		}
 	}
 
-	free(line);
-	fclose(proc_file);
-
 	if (!found) {
-		ERROR("Could not read capability bounding set from %s",
-		      proc_fn);
-		goto on_error;
+		ERROR("Could not read capability bounding set from %s", proc_fn);
+		free(info);
+		return NULL;
 	}
 
 	info->lsm_label = lsm_process_label_get(pid);
@@ -126,10 +121,6 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 	memset(info->ns_fd, -1, sizeof(int) * LXC_NS_MAX);
 
 	return info;
-
-on_error:
-	free(info);
-	return NULL;
 }
 
 static inline void lxc_proc_close_ns_fd(struct lxc_proc_context_info *ctx)
@@ -440,13 +431,14 @@ static int lxc_attach_set_environment(struct lxc_proc_context_info *init_ctx,
 
 static char *lxc_attach_getpwshell(uid_t uid)
 {
+	__do_free char *line = NULL;
+	__do_fclose FILE *pipe_f = NULL;
 	int fd, ret;
 	pid_t pid;
 	int pipes[2];
-	FILE *pipe_f;
 	bool found = false;
 	size_t line_bufsz = 0;
-	char *line = NULL, *result = NULL;
+	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.
@@ -567,9 +559,6 @@ static char *lxc_attach_getpwshell(uid_t uid)
 		found = true;
 	}
 
-	free(line);
-	fclose(pipe_f);
-
 	ret = wait_for_pid(pid);
 	if (ret < 0) {
 		free(result);
@@ -586,10 +575,10 @@ 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;
+	__do_free char *line = NULL;
+	__do_fclose FILE *proc_file = NULL;
 	char proc_fn[LXC_PROC_STATUS_LEN];
 	int ret;
-	char *line = NULL;
 	size_t line_bufsz = 0;
 	long value = -1;
 	uid_t uid = (uid_t)-1;
@@ -620,9 +609,6 @@ static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
 			break;
 	}
 
-	fclose(proc_file);
-	free(line);
-
 	/* Only override arguments if we found something. */
 	if (uid != (uid_t)-1)
 		*init_uid = uid;
@@ -637,9 +623,9 @@ static void lxc_attach_get_init_uidgid(uid_t *init_uid, gid_t *init_gid)
 
 static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options)
 {
+	__do_free char *path = NULL;
 	int ret;
 	bool bret;
-	char *path;
 
 	if (!(options->namespaces & CLONE_NEWNS) ||
 	    !(options->attach_flags & LXC_ATTACH_LSM)) {
@@ -667,7 +653,6 @@ static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options
 
 	/* Copy the value into the new lxc_conf. */
 	bret = c->set_config_item(c, "lxc.seccomp.profile", path);
-	free(path);
 	if (!bret)
 		return false;
 
@@ -684,8 +669,7 @@ static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options
 
 static bool no_new_privs(struct lxc_container *c, lxc_attach_options_t *options)
 {
-	bool bret;
-	char *val;
+	__do_free char *val = NULL;
 
 	/* Remove current setting. */
 	if (!c->set_config_item(c, "lxc.no_new_privs", "")) {
@@ -701,24 +685,18 @@ static bool no_new_privs(struct lxc_container *c, lxc_attach_options_t *options)
 	}
 
 	/* Set currently active setting. */
-	bret = c->set_config_item(c, "lxc.no_new_privs", val);
-	free(val);
-	return bret;
+	return c->set_config_item(c, "lxc.no_new_privs", val);
 }
 
 static signed long get_personality(const char *name, const char *lxcpath)
 {
-	char *p;
-	signed long ret;
+	__do_free char *p;
 
 	p = lxc_cmd_get_config_item(name, "lxc.arch", lxcpath);
 	if (!p)
 		return -1;
 
-	ret = lxc_config_parse_arch(p);
-	free(p);
-
-	return ret;
+	return lxc_config_parse_arch(p);
 }
 
 struct attach_clone_payload {
@@ -1547,11 +1525,11 @@ int lxc_attach_run_command(void *payload)
 
 int lxc_attach_run_shell(void* payload)
 {
+	__do_free char *buf = NULL;
 	uid_t uid;
 	struct passwd pwent;
 	struct passwd *pwentp = NULL;
 	char *user_shell;
-	char *buf;
 	size_t bufsize;
 	int ret;
 
@@ -1598,6 +1576,5 @@ int lxc_attach_run_shell(void* payload)
 	if (!pwentp)
 		free(user_shell);
 
-	free(buf);
 	return -1;
 }

From 57e7625005f17ab39836b3ef9908d8e0de306550 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 11:51:04 +0100
Subject: [PATCH 04/19] cgroup_utils: use __do_free

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgroup_utils.c | 34 +++++++++-------------------------
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/src/lxc/cgroups/cgroup_utils.c b/src/lxc/cgroups/cgroup_utils.c
index 5a44f36db9..1b780b2bc2 100644
--- a/src/lxc/cgroups/cgroup_utils.c
+++ b/src/lxc/cgroups/cgroup_utils.c
@@ -33,6 +33,7 @@
 #include "cgroup_utils.h"
 #include "config.h"
 #include "macro.h"
+#include "memory_utils.h"
 #include "utils.h"
 
 int get_cgroup_version(char *line)
@@ -65,12 +66,8 @@ bool is_cgroupfs_v2(char *line)
 
 bool test_writeable_v1(char *mountpoint, char *path)
 {
-	char *fullpath = must_make_path(mountpoint, path, NULL);
-	int ret;
-
-	ret = access(fullpath, W_OK);
-	free(fullpath);
-	return ret == 0;
+	__do_free char *fullpath = must_make_path(mountpoint, path, NULL);
+	return (access(fullpath, W_OK) == 0);
 }
 
 bool test_writeable_v2(char *mountpoint, char *path)
@@ -81,39 +78,26 @@ bool test_writeable_v2(char *mountpoint, char *path)
 	 * file.
 	 */
 	int ret;
-	char *cgroup_path, *cgroup_procs_file, *cgroup_threads_file;
+	__do_free char *cgroup_path = NULL, *cgroup_procs_file = NULL,
+		       *cgroup_threads_file = NULL;
 
 	cgroup_path = must_make_path(mountpoint, path, NULL);
 	cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
 
 	ret = access(cgroup_path, W_OK);
-	if (ret < 0) {
-		free(cgroup_path);
-		free(cgroup_procs_file);
+	if (ret < 0)
 		return false;
-	}
 
 	ret = access(cgroup_procs_file, W_OK);
-	free(cgroup_procs_file);
-	if (ret < 0) {
-		free(cgroup_path);
+	if (ret < 0)
 		return false;
-	}
 
 	/* Newer versions of cgroup2 now also require write access to the
 	 * "cgroup.threads" file.
 	 */
 	cgroup_threads_file = must_make_path(cgroup_path, "cgroup.threads", NULL);
-	free(cgroup_path);
-	if (!file_exists(cgroup_threads_file)) {
-		free(cgroup_threads_file);
+	if (!file_exists(cgroup_threads_file))
 		return true;
-	}
-
-	ret = access(cgroup_threads_file, W_OK);
-	free(cgroup_threads_file);
-	if (ret < 0)
-		return false;
 
-	return ret == 0;
+	return (access(cgroup_threads_file, W_OK) == 0);
 }

From 3cf7d8c2b80b6264e1830d41cc9fe84336641688 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 11:57:07 +0100
Subject: [PATCH 05/19] lxc-init: use cleanup macros

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/Makefile.am    |  2 ++
 src/lxc/cmd/lxc_init.c | 22 ++++++++--------------
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index ef19df9e08..35b805393f 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -363,6 +363,7 @@ init_lxc_SOURCES = cmd/lxc_init.c \
 		   compiler.h \
 		   error.h \
 		   initutils.c initutils.h \
+		   memory_utils.h \
 		   parse.c parse.h \
 		   raw_syscalls.c raw_syscalls.h \
 		   string_utils.c string_utils.h
@@ -411,6 +412,7 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \
 			  file_utils.c file_utils.h \
 			  log.c log.h \
 			  macro.h \
+			  memory_utils.h \
 			  namespace.c namespace.h \
 			  string_utils.c string_utils.h
 
diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c
index d9ba40b8d8..aca14d64b8 100644
--- a/src/lxc/cmd/lxc_init.c
+++ b/src/lxc/cmd/lxc_init.c
@@ -47,6 +47,7 @@
 #include "config.h"
 #include "error.h"
 #include "initutils.h"
+#include "memory_utils.h"
 #include "parse.h"
 #include "raw_syscalls.h"
 #include "string_utils.h"
@@ -100,10 +101,10 @@ static struct arguments my_args = {
 
 static void prevent_forking(void)
 {
-	FILE *f;
-	size_t len = 0;
-	char *line = NULL;
+	__do_free char *line = NULL;
+	__do_fclose FILE *f = NULL;
 	char path[PATH_MAX];
+	size_t len = 0;
 
 	f = fopen("/proc/self/cgroup", "r");
 	if (!f)
@@ -138,14 +139,14 @@ static void prevent_forking(void)
 		if (ret < 0 || (size_t)ret >= sizeof(path)) {
 			if (my_args.quiet)
 				fprintf(stderr, "Failed to create string\n");
-			goto on_error;
+			return;
 		}
 
 		fd = open(path, O_WRONLY);
 		if (fd < 0) {
 			if (my_args.quiet)
 				fprintf(stderr, "Failed to open \"%s\"\n", path);
-			goto on_error;
+			return;
 		}
 
 		ret = write(fd, "1", 1);
@@ -153,17 +154,13 @@ static void prevent_forking(void)
 			fprintf(stderr, "Failed to write to \"%s\"\n", path);
 
 		close(fd);
-		break;
+		return;
 	}
-
-on_error:
-	free(line);
-	fclose(f);
 }
 
 static void kill_children(pid_t pid)
 {
-	FILE *f;
+	__do_fclose FILE *f = NULL;
 	char path[PATH_MAX];
 	int ret;
 
@@ -187,15 +184,12 @@ static void kill_children(pid_t pid)
 		if (fscanf(f, "%d ", &find_pid) != 1) {
 			if (my_args.quiet)
 				fprintf(stderr, "Failed to retrieve pid\n");
-			fclose(f);
 			return;
 		}
 
 		(void)kill_children(find_pid);
 		(void)kill(find_pid, SIGKILL);
 	}
-
-	fclose(f);
 }
 
 static void remove_self(void)

From 5c8d235259fa89cd6e4391c4c545ba36964861ec Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 12:02:22 +0100
Subject: [PATCH 06/19] lxc-user-nic: use cleanup macros

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cmd/lxc_user_nic.c | 51 ++++++++------------------------------
 1 file changed, 11 insertions(+), 40 deletions(-)

diff --git a/src/lxc/cmd/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c
index be6b395be9..b9683c2964 100644
--- a/src/lxc/cmd/lxc_user_nic.c
+++ b/src/lxc/cmd/lxc_user_nic.c
@@ -111,10 +111,9 @@ static int open_and_lock(char *path)
 
 static char *get_username(void)
 {
+	__do_free char *buf = NULL;
 	struct passwd pwent;
 	struct passwd *pwentp = NULL;
-	char *buf;
-	char *username;
 	size_t bufsize;
 	int ret;
 
@@ -132,14 +131,10 @@ static char *get_username(void)
 			usernic_error("%s", "Could not find matched password record\n");
 
 		CMD_SYSERROR("Failed to get username: %u\n", getuid());
-		free(buf);
 		return NULL;
 	}
 
-	username = strdup(pwent.pw_name);
-	free(buf);
-
-	return username;
+	return strdup(pwent.pw_name);
 }
 
 static void free_groupnames(char **groupnames)
@@ -157,13 +152,13 @@ static void free_groupnames(char **groupnames)
 
 static char **get_groupnames(void)
 {
+	__do_free char *buf = NULL;
+	__do_free gid_t *group_ids = NULL;
 	int ngroups;
-	gid_t *group_ids;
 	int ret, i;
 	char **groupnames;
 	struct group grent;
 	struct group *grentp = NULL;
-	char *buf;
 	size_t bufsize;
 
 	ngroups = getgroups(0, NULL);
@@ -182,14 +177,12 @@ static char **get_groupnames(void)
 
 	ret = getgroups(ngroups, group_ids);
 	if (ret < 0) {
-		free(group_ids);
 		CMD_SYSERROR("Failed to get process groups\n");
 		return NULL;
 	}
 
 	groupnames = malloc(sizeof(char *) * (ngroups + 1));
 	if (!groupnames) {
-		free(group_ids);
 		CMD_SYSERROR("Failed to allocate memory while getting group names\n");
 		return NULL;
 	}
@@ -202,7 +195,6 @@ static char **get_groupnames(void)
 
 	buf = malloc(bufsize);
 	if (!buf) {
-		free(group_ids);
 		free_groupnames(groupnames);
 		CMD_SYSERROR("Failed to allocate memory while getting group names\n");
 		return NULL;
@@ -215,8 +207,6 @@ static char **get_groupnames(void)
 				usernic_error("%s", "Could not find matched group record\n");
 
 			CMD_SYSERROR("Failed to get group name: %u\n", group_ids[i]);
-			free(buf);
-			free(group_ids);
 			free_groupnames(groupnames);
 			return NULL;
 		}
@@ -224,16 +214,11 @@ static char **get_groupnames(void)
 		groupnames[i] = strdup(grent.gr_name);
 		if (!groupnames[i]) {
 			usernic_error("Failed to copy group name \"%s\"", grent.gr_name);
-			free(buf);
-			free(group_ids);
 			free_groupnames(groupnames);
 			return NULL;
 		}
 	}
 
-	free(buf);
-	free(group_ids);
-
 	return groupnames;
 }
 
@@ -321,13 +306,13 @@ static void free_alloted(struct alloted_s **head)
 static int get_alloted(char *me, char *intype, char *link,
 		       struct alloted_s **alloted)
 {
+	__do_free char *line = NULL;
+	__do_fclose FILE *fin = NULL;
 	int n, ret;
 	char name[100], type[100], br[100];
 	char **groups;
-	FILE *fin;
 	int count = 0;
 	size_t len = 0;
-	char *line = NULL;
 
 	fin = fopen(LXC_USERNIC_CONF, "r");
 	if (!fin) {
@@ -378,8 +363,6 @@ static int get_alloted(char *me, char *intype, char *link,
 	}
 
 	free_groupnames(groups);
-	fclose(fin);
-	free(line);
 
 	/* Now return the total number of nics that this user can create. */
 	return count;
@@ -610,12 +593,12 @@ struct entry_line {
 static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
 			 char *net_dev, bool *found_nicname)
 {
+	__do_free struct entry_line *entry_lines = NULL;
 	int i, ret;
 	char *buf, *buf_end, *buf_start;
 	struct stat sb;
 	int n = 0;
 	bool found, keep;
-	struct entry_line *entry_lines = NULL;
 
 	ret = fstat(fd, &sb);
 	if (ret < 0) {
@@ -641,7 +624,6 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
 
 		newe = realloc(entry_lines, sizeof(*entry_lines) * (n + 1));
 		if (!newe) {
-			free(entry_lines);
 			lxc_strmunmap(buf, sb.st_size);
 			return false;
 		}
@@ -672,8 +654,6 @@ static bool cull_entries(int fd, char *name, char *net_type, char *net_link,
 		buf_start++;
 	}
 
-	free(entry_lines);
-
 	ret = ftruncate(fd, buf_start - buf);
 	lxc_strmunmap(buf, sb.st_size);
 	if (ret < 0)
@@ -706,9 +686,10 @@ static int count_entries(char *buf, off_t len, char *name, char *net_type, char
 static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
 			      char *intype, char *br, int allowed, char **cnic)
 {
+	__do_free char *newline = NULL;
 	int ret;
 	size_t slen;
-	char *newline, *owner;
+	char *owner;
 	char nicname[IFNAMSIZ];
 	struct stat sb;
 	struct alloted_s *n;
@@ -795,7 +776,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
 	slen = strlen(owner) + strlen(intype) + strlen(br) + strlen(nicname) + 4;
 	newline = malloc(slen + 1);
 	if (!newline) {
-		free(newline);
 		CMD_SYSERROR("Failed allocate memory\n");
 		return NULL;
 	}
@@ -805,7 +785,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
 		if (lxc_netdev_delete_by_name(nicname) != 0)
 			usernic_error("Error unlinking %s\n", nicname);
 
-		free(newline);
 		return NULL;
 	}
 
@@ -824,7 +803,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
 		if (lxc_netdev_delete_by_name(nicname) != 0)
 			usernic_error("Error unlinking %s\n", nicname);
 
-		free(newline);
 		return NULL;
 	}
 
@@ -832,7 +810,6 @@ static char *get_nic_if_avail(int fd, struct alloted_s *names, int pid,
 	 * \0 byte! Files are not \0-terminated!
 	 */
 	memmove(buf + sb.st_size, newline, slen);
-	free(newline);
 	lxc_strmunmap(buf, sb.st_size + slen);
 
 	return strdup(nicname);
@@ -1115,11 +1092,11 @@ static bool is_privileged_over_netns(int netns_fd)
 
 int main(int argc, char *argv[])
 {
+	__do_free char *me = NULL, *newname = NULL, *nicname = NULL;
 	int fd, n, pid, request, ret;
-	char *me, *newname;
 	struct user_nic_args args;
 	int container_veth_ifidx = -1, host_veth_ifidx = -1, netns_fd = -1;
-	char *cnic = NULL, *nicname = NULL;
+	char *cnic = NULL;
 	struct alloted_s *alloted = NULL;
 
 	if (argc < 7 || argc > 8) {
@@ -1248,7 +1225,6 @@ int main(int argc, char *argv[])
 	}
 
 	n = get_alloted(me, args.type, args.link, &alloted);
-	free(me);
 
 	if (request == LXC_USERNIC_DELETE) {
 		struct alloted_s *it;
@@ -1313,14 +1289,11 @@ int main(int argc, char *argv[])
 		if (ret < 0)
 			usernic_error("Failed to delete \"%s\"\n", cnic);
 
-		free(nicname);
 		_exit(EXIT_FAILURE);
 	}
 
 	host_veth_ifidx = if_nametoindex(nicname);
 	if (!host_veth_ifidx) {
-		free(newname);
-		free(nicname);
 		CMD_SYSERROR("Failed to get netdev index\n");
 		_exit(EXIT_FAILURE);
 	}
@@ -1330,8 +1303,6 @@ int main(int argc, char *argv[])
 	 */
 	fprintf(stdout, "%s:%d:%s:%d\n", newname, container_veth_ifidx, nicname,
 		host_veth_ifidx);
-	free(newname);
-	free(nicname);
 
 	fflush(stdout);
 	_exit(EXIT_SUCCESS);

From e8cc83897a0f35436f95637181cfa61902eed91f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 9 Feb 2019 12:05:46 +0100
Subject: [PATCH 07/19] lxc-usernsexec: use cleanup macros

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/Makefile.am          |  3 ++-
 src/lxc/cmd/lxc_usernsexec.c | 24 ++++++++----------------
 2 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 35b805393f..538201b517 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -385,10 +385,11 @@ lxc_user_nic_SOURCES = cmd/lxc_user_nic.c \
 		       syscall_wrappers.h
 lxc_usernsexec_SOURCES = cmd/lxc_usernsexec.c \
 			 conf.c conf.h \
+			 file_utils.c file_utils.h \
 			 list.h \
 			 log.c log.h \
 			 macro.h \
-			 file_utils.c file_utils.h \
+			 memory_utils.h \
 			 string_utils.c string_utils.h \
 			 syscall_wrappers.h \
 			 utils.c utils.h
diff --git a/src/lxc/cmd/lxc_usernsexec.c b/src/lxc/cmd/lxc_usernsexec.c
index ab0dffcffc..3641d94dfb 100644
--- a/src/lxc/cmd/lxc_usernsexec.c
+++ b/src/lxc/cmd/lxc_usernsexec.c
@@ -47,6 +47,7 @@
 #include "list.h"
 #include "log.h"
 #include "macro.h"
+#include "memory_utils.h"
 #include "file_utils.h"
 #include "string_utils.h"
 #include "syscall_wrappers.h"
@@ -198,13 +199,13 @@ static int parse_map(char *map)
  */
 static int read_default_map(char *fnam, int which, char *user)
 {
+	__do_free char *line = NULL;
+	__do_fclose FILE *fin = NULL;
 	size_t len;
 	char *p1, *p2;
 	unsigned long ul1, ul2;
-	FILE *fin;
 	int ret = -1;
 	size_t sz = 0;
-	char *line = NULL;
 	struct lxc_list *tmp = NULL;
 	struct id_map *newmap = NULL;
 
@@ -259,16 +260,13 @@ static int read_default_map(char *fnam, int which, char *user)
 		break;
 	}
 
-	fclose(fin);
-	free(line);
-
 	return ret;
 }
 
 static int find_default_map(void)
 {
+	__do_free char *buf = NULL;
 	size_t bufsize;
-	char *buf;
 	struct passwd pwent;
 	int ret = -1;
 	struct passwd *pwentp = NULL;
@@ -287,24 +285,18 @@ static int find_default_map(void)
 			CMD_SYSERROR("Failed to find matched password record");
 
 		CMD_SYSERROR("Failed to get password record for uid %d", getuid());
-		ret = -1;
-		goto out;
+		return -1;
 	}
 
 	ret = read_default_map(subuidfile, ID_TYPE_UID, pwent.pw_name);
 	if (ret < 0)
-		goto out;
+		return -1;
 
 	ret = read_default_map(subgidfile, ID_TYPE_GID, pwent.pw_name);
 	if (ret < 0)
-		goto out;
-
-	ret = 0;
-
-out:
-	free(buf);
+		return -1;
 
-	return ret;
+	return 0;
 }
 
 int main(int argc, char *argv[])

From 2ebc7bde97503c30671f1f8892171094a7fe6101 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:21:09 +0100
Subject: [PATCH 08/19] commands: move declaration into tighter scope

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

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index b80e39eb41..2d99e15805 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -1074,7 +1074,6 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
 			       struct lxc_epoll_descr *descr,
 			       const lxc_cmd_t cmd)
 {
-	struct lxc_state_client *client;
 	struct lxc_list *cur, *next;
 
 	lxc_terminal_free(handler->conf, fd);
@@ -1085,7 +1084,8 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
 	}
 
 	lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
-		client = cur->elem;
+		struct lxc_state_client *client = cur->elem;
+
 		if (client->clientfd != fd)
 			continue;
 

From 028bd699e06a199d4b011af238bfbea32eeeba18 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:24:30 +0100
Subject: [PATCH 09/19] commands: cleanup macros in lxc_cmd_console()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 2d99e15805..7cc4b25179 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -698,8 +698,8 @@ static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
  */
 int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
 {
+	__do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
 	int ret, stopped;
-	struct lxc_cmd_console_rsp_data *rspdata;
 	struct lxc_cmd_rr cmd = {
 		.req = { .cmd = LXC_CMD_CONSOLE, .data = INT_TO_PTR(*ttynum) },
 	};
@@ -711,20 +711,18 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
 	if (cmd.rsp.ret < 0) {
 		errno = -cmd.rsp.ret;
 		SYSERROR("Denied access to tty");
-		ret = -1;
-		goto out;
+		return -1;
 	}
 
 	if (ret == 0) {
 		ERROR("tty number %d invalid, busy or all ttys busy", *ttynum);
-		ret = -1;
-		goto out;
+		return -1;
 	}
 
 	rspdata = cmd.rsp.data;
 	if (rspdata->masterfd < 0) {
 		ERROR("Unable to allocate fd for tty %d", rspdata->ttynum);
-		goto out;
+		return -1;
 	}
 
 	ret = cmd.rsp.ret; /* socket fd */
@@ -732,8 +730,6 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
 	*ttynum = rspdata->ttynum;
 	INFO("Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
 
-out:
-	free(cmd.rsp.data);
 	return ret;
 }
 

From f9fb3a3b17e89a273e14e1db56cc7862bfa4f4ee Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:31:40 +0100
Subject: [PATCH 10/19] macro: introduce steal_fd()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/macro.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/lxc/macro.h b/src/lxc/macro.h
index bd632dc1fd..61e626f2ef 100644
--- a/src/lxc/macro.h
+++ b/src/lxc/macro.h
@@ -400,4 +400,11 @@ enum {
 		_ptr_;                     \
 	})
 
+#define steal_fd(fd)             \
+	({                       \
+		int _fd_ = (fd); \
+		(fd) = -EBADF;   \
+		_fd_;            \
+	})
+
 #endif /* __LXC_MACRO_H */

From 7b3a0a4b96121d2bd9da0f4556d627859f5b1fd6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:31:52 +0100
Subject: [PATCH 11/19] memory_utils: introduce __do_close_prot_errno

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/memory_utils.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/src/lxc/memory_utils.h b/src/lxc/memory_utils.h
index d42babfd8f..fdcfb55301 100644
--- a/src/lxc/memory_utils.h
+++ b/src/lxc/memory_utils.h
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 static inline void __auto_free__(void *p)
 {
@@ -44,6 +45,16 @@ static inline void __auto_closedir__(DIR **d)
 		closedir(*d);
 }
 
+static inline void __auto_close__(int *fd)
+{
+	if (*fd >= 0) {
+		int e = errno;
+		close(*fd);
+		errno = e;
+	}
+}
+
+#define __do_close_prot_errno __attribute__((__cleanup__(__auto_close__)))
 #define __do_free __attribute__((__cleanup__(__auto_free__)))
 #define __do_fclose __attribute__((__cleanup__(__auto_fclose__)))
 #define __do_closedir __attribute__((__cleanup__(__auto_closedir__)))

From 124cf7ca56e4d5d689fc40cf052c9ace65b99b3c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:32:14 +0100
Subject: [PATCH 12/19] commands: use __do_close_prot_errno

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

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 7cc4b25179..cc3292330c 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -232,7 +232,7 @@ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
 static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
 			const char *lxcpath, const char *hashed_sock_name)
 {
-	int client_fd, saved_errno;
+	__do_close_prot_errno int client_fd = -EBADF;
 	ssize_t ret = -1;
 
 	client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
@@ -242,25 +242,18 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
 	ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
 						sizeof(cmd->req));
 	if (ret < 0 || (size_t)ret != sizeof(cmd->req))
-		goto on_error;
+		return -1;
 
 	if (cmd->req.datalen <= 0)
-		return client_fd;
+		return steal_fd(client_fd);
 
 	errno = EMSGSIZE;
 	ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
 			      cmd->req.datalen, MSG_NOSIGNAL);
 	if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
-		goto on_error;
-
-	return client_fd;
-
-on_error:
-	saved_errno = errno;
-	close(client_fd);
-	errno = saved_errno;
+		return -1;
 
-	return -1;
+	return steal_fd(client_fd);
 }
 
 /*

From 63fc04e191241d7d5b63161b29dee5b9382dae52 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:36:52 +0100
Subject: [PATCH 13/19] commands: cleanup macros lxc_cmd()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index cc3292330c..92d9765887 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -278,7 +278,7 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
 static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
 		   const char *lxcpath, const char *hashed_sock_name)
 {
-	int client_fd, saved_errno;
+	__do_close_prot_errno int client_fd = -EBADF;
 	int ret = -1;
 	bool stay_connected = false;
 
@@ -303,15 +303,8 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
 	if (ret < 0 && errno == ECONNRESET)
 		*stopped = 1;
 
-	if (!stay_connected || ret <= 0) {
-		saved_errno = errno;
-		close(client_fd);
-		errno = saved_errno;
-		return ret;
-	}
-
-	if (stay_connected)
-		cmd->rsp.ret = client_fd;
+	if (stay_connected && ret > 0)
+		cmd->rsp.ret = steal_fd(client_fd);
 
 	return ret;
 }

From 02f97343eb9eb3cd3c28d2a7467bf795acc4320b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:39:55 +0100
Subject: [PATCH 14/19] commands: cleanup macros lxc_cmd_add_state_client

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 92d9765887..f1206a9737 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -828,6 +828,7 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
 			     lxc_state_t states[MAX_STATE],
 			     int *state_client_fd)
 {
+	__do_close_prot_errno int clientfd = -EBADF;
 	int state, stopped;
 	ssize_t ret;
 	struct lxc_cmd_rr cmd = {
@@ -852,8 +853,9 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
 	/* We should now be guaranteed to get an answer from the state sending
 	 * function.
 	 */
-	if (cmd.rsp.ret < 0) {
-		errno = -cmd.rsp.ret;
+	clientfd = cmd.rsp.ret;
+	if (clientfd < 0) {
+		errno = -clientfd;
 		SYSERROR("Failed to receive socket fd");
 		return -1;
 	}
@@ -861,12 +863,11 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
 	state = PTR_TO_INT(cmd.rsp.data);
 	if (state < MAX_STATE) {
 		TRACE("Container is already in requested state %s", lxc_state2str(state));
-		close(cmd.rsp.ret);
 		return state;
 	}
 
-	*state_client_fd = cmd.rsp.ret;
-	TRACE("Added state client %d to state client list", cmd.rsp.ret);
+	*state_client_fd = steal_fd(clientfd);
+	TRACE("Added state client %d to state client list", *state_client_fd);
 	return MAX_STATE;
 }
 

From 2a77b6ea1f6239aefeeeea4b91fd56841bcd0680 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:42:51 +0100
Subject: [PATCH 15/19] commands: cleanup macros lxc_cmd_accept()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index f1206a9737..3b4cca8ef4 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -1157,7 +1157,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
 static int lxc_cmd_accept(int fd, uint32_t events, void *data,
 			  struct lxc_epoll_descr *descr)
 {
-	int connection;
+	__do_close_prot_errno int connection = -EBADF;
 	int opt = 1, ret = -1;
 
 	connection = accept(fd, NULL, 0);
@@ -1169,27 +1169,23 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
 	ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
 	if (ret < 0) {
 		SYSERROR("Failed to set close-on-exec on incoming command connection");
-		goto out_close;
+		return ret;
 	}
 
 	ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
 	if (ret < 0) {
 		SYSERROR("Failed to enable necessary credentials on command socket");
-		goto out_close;
+		return ret;
 	}
 
 	ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
 	if (ret) {
 		ERROR("Failed to add command handler");
-		goto out_close;
+		return ret;
 	}
 
-out:
+	steal_fd(connection);
 	return ret;
-
-out_close:
-	close(connection);
-	goto out;
 }
 
 int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)

From 45843fb98e1919848ac6c146d3d0e0434bfe246f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:44:20 +0100
Subject: [PATCH 16/19] commands: cleanup macros lxc_cmd_init

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

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 3b4cca8ef4..a7087b2922 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -1190,13 +1190,13 @@ static int lxc_cmd_accept(int fd, uint32_t events, void *data,
 
 int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
 {
-	int fd, ret;
+	__do_close_prot_errno int fd = -EBADF;
+	int ret;
 	char path[LXC_AUDS_ADDR_LEN] = {0};
 
 	ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
 	if (ret < 0)
 		return -1;
-	TRACE("Creating abstract unix socket \"%s\"", &path[1]);
 
 	fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
 	if (fd < 0) {
@@ -1210,11 +1210,11 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
 	ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
 	if (ret < 0) {
 		SYSERROR("Failed to set FD_CLOEXEC on command socket file descriptor");
-		close(fd);
 		return -1;
 	}
 
-	return fd;
+	TRACE("Created abstract unix socket \"%s\"", &path[1]);
+	return steal_fd(fd);
 }
 
 int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,

From 28c1c3980fd4e1430f3453b81a238b8cbffc7d9a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 14:46:25 +0100
Subject: [PATCH 17/19] commands: cleanup macros lxc_cmd_init()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/commands.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index a7087b2922..55c6b198a1 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -1220,14 +1220,15 @@ int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
 int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
 			 struct lxc_handler *handler)
 {
+	__do_close_prot_errno int fd = handler->conf->maincmd_fd;
 	int ret;
-	int fd = handler->conf->maincmd_fd;
 
 	ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
 	if (ret < 0) {
 		ERROR("Failed to add handler for command socket");
-		close(fd);
+		return ret;
 	}
 
+	steal_fd(fd);
 	return ret;
 }

From 60b78bd4708b2bd25b36684ce2c229d41c787d51 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 17 Feb 2019 15:12:19 +0100
Subject: [PATCH 18/19] rexec: use __do_close_prot_errno

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/rexec.c | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/src/lxc/rexec.c b/src/lxc/rexec.c
index fe362f284d..0589b4a781 100644
--- a/src/lxc/rexec.c
+++ b/src/lxc/rexec.c
@@ -83,16 +83,14 @@ static int parse_argv(char ***argv)
 
 static int is_memfd(void)
 {
-	int fd, saved_errno, seals;
+	__do_close_prot_errno int fd = -EBADF;
+	int saved_errno, seals;
 
 	fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		return -ENOTRECOVERABLE;
 
 	seals = fcntl(fd, F_GET_SEALS);
-	saved_errno = errno;
-	close(fd);
-	errno = saved_errno;
 	if (seals < 0)
 		return -EINVAL;
 
@@ -101,9 +99,9 @@ static int is_memfd(void)
 
 static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
 {
+	__do_close_prot_errno int fd = -EBADF, memfd = -EBADF;
 	int saved_errno;
 	ssize_t bytes_sent;
-	int fd = -1, memfd = -1;
 
 	memfd = memfd_create(memfd_name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
 	if (memfd < 0)
@@ -111,25 +109,17 @@ static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
 
 	fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
-		goto on_error;
+		return;
 
 	/* sendfile() handles up to 2GB. */
 	bytes_sent = lxc_sendfile_nointr(memfd, fd, NULL, LXC_SENDFILE_MAX);
-	saved_errno = errno;
-	close(fd);
-	errno = saved_errno;
 	if (bytes_sent < 0)
-		goto on_error;
+		return;
 
 	if (fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS))
-		goto on_error;
+		return;
 
 	fexecve(memfd, argv, envp);
-
-on_error:
-	saved_errno = errno;
-	close(memfd);
-	errno = saved_errno;
 }
 
 /*

From 3793bc3dbaada6317c9c025d8a49190c06c29824 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 18 Feb 2019 13:32:26 +0100
Subject: [PATCH 19/19] rexec: handle legacy kernels

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/file_utils.c   | 32 +++++++++++++++++-
 src/lxc/file_utils.h   |  1 +
 src/lxc/memory_utils.h | 16 ++++++---
 src/lxc/rexec.c        | 77 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c
index 930fd738a9..c057cb5d25 100644
--- a/src/lxc/file_utils.c
+++ b/src/lxc/file_utils.c
@@ -222,7 +222,7 @@ int lxc_make_tmpfile(char *template, bool rm)
 	mode_t msk;
 
 	msk = umask(0022);
-	fd = mkstemp(template);
+	fd = mkostemp(template, O_CLOEXEC);
 	umask(msk);
 	if (fd < 0)
 		return -1;
@@ -366,3 +366,33 @@ char *file_to_buf(char *path, size_t *length)
 
 	return NULL;
 }
+
+int fd_to_fd(int from, int to)
+{
+	for (;;) {
+		uint8_t buf[PATH_MAX];
+		uint8_t *p = buf;
+		ssize_t bytes_to_write;
+		ssize_t bytes_read;
+
+		bytes_read = lxc_read_nointr(from, buf, sizeof buf);
+		if (bytes_read < 0)
+			return -1;
+		if (bytes_read == 0)
+			break;
+
+		bytes_to_write = (size_t)bytes_read;
+		do {
+			ssize_t bytes_written;
+
+			bytes_written = lxc_write_nointr(to, p, bytes_to_write);
+			if (bytes_written < 0)
+				return -1;
+
+			bytes_to_write -= bytes_written;
+			p += bytes_written;
+		} while (bytes_to_write > 0);
+	}
+
+	return 0;
+}
diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h
index fc2b7d8c10..cc8f69e183 100644
--- a/src/lxc/file_utils.h
+++ b/src/lxc/file_utils.h
@@ -57,5 +57,6 @@ extern FILE *fopen_cloexec(const char *path, const char *mode);
 extern ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset,
 				   size_t count);
 extern char *file_to_buf(char *path, size_t *length);
+extern int fd_to_fd(int from, int to);
 
 #endif /* __LXC_FILE_UTILS_H */
diff --git a/src/lxc/memory_utils.h b/src/lxc/memory_utils.h
index fdcfb55301..c1dafb441a 100644
--- a/src/lxc/memory_utils.h
+++ b/src/lxc/memory_utils.h
@@ -28,6 +28,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "macro.h"
+
 static inline void __auto_free__(void *p)
 {
 	free(*(void **)p);
@@ -45,13 +47,17 @@ static inline void __auto_closedir__(DIR **d)
 		closedir(*d);
 }
 
+#define close_prot_errno_disarm(fd) \
+	if (fd >= 0) {              \
+		int _e_ = errno;    \
+		close(fd);          \
+		errno = _e_;        \
+		fd = -EBADF;        \
+	}
+
 static inline void __auto_close__(int *fd)
 {
-	if (*fd >= 0) {
-		int e = errno;
-		close(*fd);
-		errno = e;
-	}
+	close_prot_errno_disarm(*fd);
 }
 
 #define __do_close_prot_errno __attribute__((__cleanup__(__auto_close__)))
diff --git a/src/lxc/rexec.c b/src/lxc/rexec.c
index 0589b4a781..26b9bb787a 100644
--- a/src/lxc/rexec.c
+++ b/src/lxc/rexec.c
@@ -84,42 +84,97 @@ static int parse_argv(char ***argv)
 static int is_memfd(void)
 {
 	__do_close_prot_errno int fd = -EBADF;
-	int saved_errno, seals;
+	int seals;
 
 	fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		return -ENOTRECOVERABLE;
 
 	seals = fcntl(fd, F_GET_SEALS);
-	if (seals < 0)
+	if (seals < 0) {
+		struct stat s = {0};
+
+		if (fstat(fd, &s) == 0) {
+			fprintf(stderr, "AAAAA: %ld\n", (long)s.st_nlink);
+			return (s.st_nlink == 0);
+		}
+
 		return -EINVAL;
+	}
 
 	return seals == LXC_MEMFD_REXEC_SEALS;
 }
 
 static void lxc_rexec_as_memfd(char **argv, char **envp, const char *memfd_name)
 {
-	__do_close_prot_errno int fd = -EBADF, memfd = -EBADF;
-	int saved_errno;
-	ssize_t bytes_sent;
+	__do_close_prot_errno int fd = -EBADF, memfd = -EBADF, tmpfd = -EBADF;
+	int ret;
 
 	memfd = memfd_create(memfd_name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
-	if (memfd < 0)
-		return;
+	if (memfd < 0) {
+		char template[PATH_MAX];
+
+		ret = snprintf(template, sizeof(template),
+			       P_tmpdir "/.%s_XXXXXX", memfd_name);
+		if (ret < 0 || (size_t)ret >= sizeof(template))
+			return;
+
+		tmpfd = lxc_make_tmpfile(template, true);
+		if (tmpfd < 0)
+			return;
+
+		ret = fchmod(tmpfd, 0700);
+		if (ret)
+			return;
+	}
 
 	fd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
 		return;
 
 	/* sendfile() handles up to 2GB. */
-	bytes_sent = lxc_sendfile_nointr(memfd, fd, NULL, LXC_SENDFILE_MAX);
-	if (bytes_sent < 0)
+	if (memfd >= 0) {
+		ssize_t bytes_sent = 0;
+		struct stat st = {0};
+
+		ret = fstat(fd, &st);
+		if (ret)
+			return;
+
+		while (bytes_sent < st.st_size) {
+			size_t sent;
+			sent = lxc_sendfile_nointr(memfd, fd, NULL,
+						   st.st_size - bytes_sent);
+			if (sent < 0)
+				return;
+			bytes_sent += sent;
+		}
+	} else if (fd_to_fd(fd, tmpfd)) {
 		return;
+	}
 
-	if (fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS))
+	close_prot_errno_disarm(fd);
+
+	if (memfd >= 0 && fcntl(memfd, F_ADD_SEALS, LXC_MEMFD_REXEC_SEALS))
 		return;
 
-	fexecve(memfd, argv, envp);
+	if (memfd >= 0) {
+		fexecve(memfd, argv, envp);
+	} else {
+		__do_close_prot_errno int execfd = -EBADF;
+		char procfd[LXC_PROC_PID_FD_LEN];
+
+		ret = snprintf(procfd, sizeof(procfd), "/proc/self/fd/%d", tmpfd);
+		if (ret < 0 || (size_t)ret >= sizeof(procfd))
+			return;
+
+		execfd = open(procfd, O_PATH | O_CLOEXEC);
+		close_prot_errno_disarm(tmpfd);
+		if (execfd < 0)
+			return;
+
+		fexecve(execfd, argv, envp);
+	}
 }
 
 /*


More information about the lxc-devel mailing list