[lxc-devel] [lxc/master] cgroups, logging: fixes and improvements

brauner on Github lxc-bot at linuxcontainers.org
Sun Dec 8 00:19:28 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/20191207/fc1e279c/attachment-0001.bin>
-------------- next part --------------
From 2b0c584613bcc75c25f0491c4622fa9169196959 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:21:18 +0100
Subject: [PATCH 01/44] log: rearrange

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

diff --git a/src/lxc/log.h b/src/lxc/log.h
index 951eaba318..553bc2a120 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -491,12 +491,6 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 		-1;                              \
 	})
 
-#define log_trace(__ret__, format, ...)	      \
-	({                                    \
-		TRACE(format, ##__VA_ARGS__); \
-		__ret__;                      \
-	})
-
 #define log_error_errno(__ret__, __errno__, format, ...) \
 	({						 \
 		errno = __errno__;			 \
@@ -510,6 +504,19 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 		__ret__;		      \
 	})
 
+#define log_trace_errno(__ret__, __errno__, format, ...) \
+	({                                               \
+		errno = __errno__;			 \
+		SYSTRACE(format, ##__VA_ARGS__);         \
+		__ret__;                                 \
+	})
+
+#define log_trace(__ret__, format, ...)	      \
+	({                                    \
+		TRACE(format, ##__VA_ARGS__); \
+		__ret__;                      \
+	})
+
 #define log_warn_errno(__ret__, __errno__, format, ...) \
 	({						\
 		errno = __errno__;			\
@@ -517,18 +524,19 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 		__ret__;				\
 	})
 
-#define log_debug(__ret__, format, ...)	      \
-	({				      \
-		DEBUG(format, ##__VA_ARGS__); \
-		__ret__;		      \
-	})
-
 #define log_debug_errno(__ret__, __errno__, format, ...) \
 	({						 \
+		errno = __errno__;			\
 		SYSDEBUG(format, ##__VA_ARGS__);	 \
 		__ret__;				 \
 	})
 
+#define log_debug(__ret__, format, ...)	      \
+	({				      \
+		DEBUG(format, ##__VA_ARGS__); \
+		__ret__;		      \
+	})
+
 extern int lxc_log_fd;
 
 extern int lxc_log_syslog(int facility);

From 9958e6fe7f69871a8452cebf48e9e8da019fa6a0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:21:53 +0100
Subject: [PATCH 02/44] macro: add ret_errno()

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

diff --git a/src/lxc/macro.h b/src/lxc/macro.h
index e011596d21..b4c9f4e7c6 100644
--- a/src/lxc/macro.h
+++ b/src/lxc/macro.h
@@ -454,6 +454,12 @@ enum {
 		__ret__;                  \
 	})
 
+#define ret_errno(__errno__)       \
+	({                         \
+		errno = __errno__; \
+		-__errno__;        \
+	})
+
 #define free_replace_move_ptr(a, b) \
 	({                          \
 		free(a);            \

From db1b8b0f5ef3d24760587a1a56b7ea0fa5c0c712 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:22:14 +0100
Subject: [PATCH 03/44] af_unix: s/minus_one_set_errno(/ret_set_errno(-1, /g

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

diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c
index 061d1c3176..7f8c88b1a2 100644
--- a/src/lxc/af_unix.c
+++ b/src/lxc/af_unix.c
@@ -335,14 +335,14 @@ int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path)
 
 	len = strlen(path);
 	if (len == 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	if (path[0] != '/' && path[0] != '@')
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	if (path[1] == '\0')
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (len + 1 > sizeof(ret->sun_path))
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	*ret = (struct sockaddr_un){
 	    .sun_family = AF_UNIX,

From 540a2f7092605c586ad1f1c8e4231c3a53655099 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:22:53 +0100
Subject: [PATCH 04/44] attach: s/minus_one_set_errno(/ret_set_errno(-1, /g

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

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 7976d464ce..3dd56ccb3a 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -1009,10 +1009,10 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
 	}
 
 	if (!container)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (!lxc_container_get(container))
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	name = container->name;
 	lxcpath = container->config_path;

From 3d0327ed245ff14e8a33659ec82ef13b6b54fc55 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:23:24 +0100
Subject: [PATCH 05/44] commands: replace logging helpers

s/error_log_errno(/log_error_errno(-1, /g
s/minus_one_set_errno(/ret_set_errno(-1, /g

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

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 9bbc206096..c46a4106d5 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -913,16 +913,16 @@ int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
 	int ret;
 
 	if (strlen(device->access) > STRLITERALLEN("rwm"))
-		return error_log_errno(EINVAL, "Invalid access mode specified %s",
+		return log_error_errno(-1, EINVAL, "Invalid access mode specified %s",
 				       device->access);
 
 	ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
 	if (ret < 0 || cmd.rsp.ret < 0)
-		return error_log_errno(errno, "Failed to add new bpf device cgroup rule");
+		return log_error_errno(-1, errno, "Failed to add new bpf device cgroup rule");
 
 	return 0;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -1006,7 +1006,7 @@ static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *re
 	 */
 	return 1;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -1155,7 +1155,7 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
 
 	return cmd.rsp.ret;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -1211,7 +1211,7 @@ int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout)
 
 	ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
 	if (ret <= 0 || cmd.rsp.ret < 0)
-		return error_log_errno(errno, "Failed to freeze container");
+		return log_error_errno(-1, errno, "Failed to freeze container");
 
 	return cmd.rsp.ret;
 }
@@ -1244,7 +1244,7 @@ int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout)
 
 	ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
 	if (ret <= 0 || cmd.rsp.ret < 0)
-		return error_log_errno(errno, "Failed to unfreeze container");
+		return log_error_errno(-1, errno, "Failed to unfreeze container");
 
 	return cmd.rsp.ret;
 }

From 596a002c6846cc977c45e0fff595ed58278169b0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:24:29 +0100
Subject: [PATCH 06/44] network: replace logging helpers

s/error_log_errno(/log_error_errno(-1, /g
s/minus_one_set_errno(/ret_set_errno(-1, /g

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

diff --git a/src/lxc/network.c b/src/lxc/network.c
index 9faa2e6a93..65eca60e83 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -131,7 +131,7 @@ static int lxc_setup_ipv4_routes(struct lxc_list *ip, int ifindex)
 		if (err) {
 			SYSERROR("Failed to setup ipv4 route for network device "
 			         "with ifindex %d", ifindex);
-			return minus_one_set_errno(-err);
+			return ret_set_errno(-1, -err);
 		}
 	}
 
@@ -150,7 +150,7 @@ static int lxc_setup_ipv6_routes(struct lxc_list *ip, int ifindex)
 		if (err) {
 			SYSERROR("Failed to setup ipv6 route for network device "
 			         "with ifindex %d", ifindex);
-			return minus_one_set_errno(-err);
+			return ret_set_errno(-1, -err);
 		}
 	}
 
@@ -168,7 +168,7 @@ static int setup_ipv4_addr_routes(struct lxc_list *ip, int ifindex)
 		err = lxc_ipv4_dest_add(ifindex, &inetdev->addr, 32);
 
 		if (err)
-			return error_log_errno(err,
+			return log_error_errno(-1, err,
 				"Failed to setup ipv4 address route for network device with eifindex %d",
 				ifindex);
 	}
@@ -186,7 +186,7 @@ static int setup_ipv6_addr_routes(struct lxc_list *ip, int ifindex)
 
 		err = lxc_ipv6_dest_add(ifindex, &inet6dev->addr, 128);
 		if (err)
-			return error_log_errno(err,
+			return log_error_errno(-1, err,
 				"Failed to setup ipv6 address route for network device with eifindex %d",
 				ifindex);
 	}
@@ -258,13 +258,13 @@ static int lxc_is_ip_forwarding_enabled(const char *ifname, int family)
 	char buf[1] = "";
 
 	if (family != AF_INET && family != AF_INET6)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
 		       family == AF_INET ? "ipv4" : "ipv6", ifname,
 		       "forwarding");
 	if (ret < 0 || (size_t)ret >= PATH_MAX)
-		return minus_one_set_errno(E2BIG);
+		return ret_set_errno(-1, E2BIG);
 
 	return lxc_read_file_expect(path, buf, 1, "1");
 }
@@ -401,19 +401,19 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 		if (netdev->ipv4_gateway) {
 			char bufinet4[INET_ADDRSTRLEN];
 			if (!inet_ntop(AF_INET, netdev->ipv4_gateway, bufinet4, sizeof(bufinet4))) {
-				error_log_errno(-errno, "Failed to convert gateway ipv4 address on \"%s\"", veth1);
+				log_error_errno(-1, -errno, "Failed to convert gateway ipv4 address on \"%s\"", veth1);
 				goto out_delete;
 			}
 
 			err = lxc_ip_forwarding_on(veth1, AF_INET);
 			if (err) {
-				error_log_errno(err, "Failed to activate ipv4 forwarding on \"%s\"", veth1);
+				log_error_errno(-1, err, "Failed to activate ipv4 forwarding on \"%s\"", veth1);
 				goto out_delete;
 			}
 
 			err = lxc_add_ip_neigh_proxy(bufinet4, veth1);
 			if (err) {
-				error_log_errno(err, "Failed to add gateway ipv4 proxy on \"%s\"", veth1);
+				log_error_errno(-1, err, "Failed to add gateway ipv4 proxy on \"%s\"", veth1);
 				goto out_delete;
 			}
 		}
@@ -422,7 +422,7 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 			char bufinet6[INET6_ADDRSTRLEN];
 
 			if (!inet_ntop(AF_INET6, netdev->ipv6_gateway, bufinet6, sizeof(bufinet6))) {
-				error_log_errno(-errno, "Failed to convert gateway ipv6 address on \"%s\"", veth1);
+				log_error_errno(-1, -errno, "Failed to convert gateway ipv6 address on \"%s\"", veth1);
 				goto out_delete;
 			}
 
@@ -431,25 +431,25 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 			*/
 			err = lxc_is_ip_forwarding_enabled("all", AF_INET6);
 			if (err) {
-				error_log_errno(err, "Requires sysctl net.ipv6.conf.all.forwarding=1");
+				log_error_errno(-1, err, "Requires sysctl net.ipv6.conf.all.forwarding=1");
 				goto out_delete;
 			}
 
 			err = lxc_ip_forwarding_on(veth1, AF_INET6);
 			if (err) {
-				error_log_errno(err, "Failed to activate ipv6 forwarding on \"%s\"", veth1);
+				log_error_errno(-1, err, "Failed to activate ipv6 forwarding on \"%s\"", veth1);
 				goto out_delete;
 			}
 
 			err = lxc_neigh_proxy_on(veth1, AF_INET6);
 			if (err) {
-				error_log_errno(err, "Failed to activate proxy ndp on \"%s\"", veth1);
+				log_error_errno(-1, err, "Failed to activate proxy ndp on \"%s\"", veth1);
 				goto out_delete;
 			}
 
 			err = lxc_add_ip_neigh_proxy(bufinet6, veth1);
 			if (err) {
-				error_log_errno(err, "Failed to add gateway ipv6 proxy on \"%s\"", veth1);
+				log_error_errno(-1, err, "Failed to add gateway ipv6 proxy on \"%s\"", veth1);
 				goto out_delete;
 			}
 		}
@@ -457,14 +457,14 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 		/* setup ipv4 address routes on the host interface */
 		err = setup_ipv4_addr_routes(&netdev->ipv4, netdev->priv.veth_attr.ifindex);
 		if (err) {
-			error_log_errno(err, "Failed to setup ip address routes for network device \"%s\"", veth1);
+			log_error_errno(-1, err, "Failed to setup ip address routes for network device \"%s\"", veth1);
 			goto out_delete;
 		}
 
 		/* setup ipv6 address routes on the host interface */
 		err = setup_ipv6_addr_routes(&netdev->ipv6, netdev->priv.veth_attr.ifindex);
 		if (err) {
-			error_log_errno(err, "Failed to setup ip address routes for network device \"%s\"", veth1);
+			log_error_errno(-1, err, "Failed to setup ip address routes for network device \"%s\"", veth1);
 			goto out_delete;
 		}
 	}
@@ -580,19 +580,19 @@ static int lxc_ipvlan_create(const char *master, const char *name, int mode, int
 
 	len = strlen(master);
 	if (len == 1 || len >= IFNAMSIZ)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	len = strlen(name);
 	if (len == 1 || len >= IFNAMSIZ)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	index = if_nametoindex(master);
 	if (!index)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	err = netlink_open(&nlh, NETLINK_ROUTE);
 	if (err)
-		return minus_one_set_errno(-err);
+		return ret_set_errno(-1, -err);
 
 	err = -ENOMEM;
 	nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
@@ -653,7 +653,7 @@ static int lxc_ipvlan_create(const char *master, const char *name, int mode, int
 	nlmsg_free(answer);
 	nlmsg_free(nlmsg);
 	if (err < 0)
-		return minus_one_set_errno(-err);
+		return ret_set_errno(-1, -err);
 	return 0;
 }
 
@@ -846,7 +846,7 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
 	mtu_orig = netdev_get_mtu(netdev->ifindex);
 	if (mtu_orig < 0) {
 		SYSERROR("Failed to get original mtu for interface \"%s\"", netdev->link);
-		return minus_one_set_errno(-mtu_orig);
+		return ret_set_errno(-1, -mtu_orig);
 	}
 
 	netdev->priv.phys_attr.mtu = mtu_orig;
@@ -2007,13 +2007,13 @@ static int lxc_is_ip_neigh_proxy_enabled(const char *ifname, int family)
 	char buf[1] = "";
 
 	if (family != AF_INET && family != AF_INET6)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	ret = snprintf(path, PATH_MAX, "/proc/sys/net/%s/conf/%s/%s",
 		       family == AF_INET ? "ipv4" : "ipv6", ifname,
 		       family == AF_INET ? "proxy_arp" : "proxy_ndp");
 	if (ret < 0 || (size_t)ret >= PATH_MAX)
-		return minus_one_set_errno(E2BIG);
+		return ret_set_errno(-1, E2BIG);
 
 	return lxc_read_file_expect(path, buf, 1, "1");
 }
@@ -3047,7 +3047,7 @@ static int lxc_setup_l2proxy(struct lxc_netdev *netdev) {
 		/* Check for net.ipv4.conf.[link].forwarding=1 */
 		if (lxc_is_ip_forwarding_enabled(netdev->link, AF_INET) < 0) {
 			ERROR("Requires sysctl net.ipv4.conf.%s.forwarding=1", netdev->link);
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 		}
 	}
 
@@ -3056,13 +3056,13 @@ static int lxc_setup_l2proxy(struct lxc_netdev *netdev) {
 		/* Check for net.ipv6.conf.[link].proxy_ndp=1 */
 		if (lxc_is_ip_neigh_proxy_enabled(netdev->link, AF_INET6) < 0) {
 			ERROR("Requires sysctl net.ipv6.conf.%s.proxy_ndp=1", netdev->link);
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 		}
 
 		/* Check for net.ipv6.conf.[link].forwarding=1 */
 		if (lxc_is_ip_forwarding_enabled(netdev->link, AF_INET6) < 0) {
 			ERROR("Requires sysctl net.ipv6.conf.%s.forwarding=1", netdev->link);
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 		}
 	}
 
@@ -3071,31 +3071,31 @@ static int lxc_setup_l2proxy(struct lxc_netdev *netdev) {
 		/* Check mode is l3s as other modes do not work with l2proxy. */
 		if (netdev->priv.ipvlan_attr.mode != IPVLAN_MODE_L3S) {
 			ERROR("Requires ipvlan mode on dev \"%s\" be l3s when used with l2proxy", netdev->link);
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 		}
 
 		/* Retrieve local-loopback interface index for use with IPVLAN static routes. */
 		lo_ifindex = if_nametoindex(loop_device);
 		if (lo_ifindex == 0) {
 			ERROR("Failed to retrieve ifindex for \"%s\" routing cleanup", loop_device);
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 		}
 	}
 
 	lxc_list_for_each_safe(cur, &netdev->ipv4, next) {
 		inet4dev = cur->elem;
 		if (!inet_ntop(AF_INET, &inet4dev->addr, bufinet4, sizeof(bufinet4)))
-			return minus_one_set_errno(-errno);
+			return ret_set_errno(-1, -errno);
 
 		if (lxc_add_ip_neigh_proxy(bufinet4, netdev->link) < 0)
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 
 		/* IPVLAN requires a route to local-loopback to trigger l2proxy. */
 		if (netdev->type == LXC_NET_IPVLAN) {
 			err = lxc_ipv4_dest_add(lo_ifindex, &inet4dev->addr, 32);
 			if (err < 0) {
 				ERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"", bufinet4, loop_device);
-				return minus_one_set_errno(-err);
+				return ret_set_errno(-1, -err);
 			}
 		}
 	}
@@ -3103,17 +3103,17 @@ static int lxc_setup_l2proxy(struct lxc_netdev *netdev) {
 	lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
 		inet6dev = cur->elem;
 		if (!inet_ntop(AF_INET6, &inet6dev->addr, bufinet6, sizeof(bufinet6)))
-			return minus_one_set_errno(-errno);
+			return ret_set_errno(-1, -errno);
 
 		if (lxc_add_ip_neigh_proxy(bufinet6, netdev->link) < 0)
-			return minus_one_set_errno(EINVAL);
+			return ret_set_errno(-1, EINVAL);
 
 		/* IPVLAN requires a route to local-loopback to trigger l2proxy. */
 		if (netdev->type == LXC_NET_IPVLAN) {
 			err = lxc_ipv6_dest_add(lo_ifindex, &inet6dev->addr, 128);
 			if (err < 0) {
 				ERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"", bufinet6, loop_device);
-				return minus_one_set_errno(-err);
+				return ret_set_errno(-1, -err);
 			}
 		}
 	}
@@ -3127,7 +3127,7 @@ static int lxc_delete_ipv4_l2proxy(struct in_addr *ip, char *link, unsigned int
 
 	if (!inet_ntop(AF_INET, ip, bufinet4, sizeof(bufinet4))) {
 		SYSERROR("Failed to convert IP for l2proxy ipv4 removal on dev \"%s\"", link);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	/* If a local-loopback ifindex supplied remove the static route to the lo device. */
@@ -3145,7 +3145,7 @@ static int lxc_delete_ipv4_l2proxy(struct in_addr *ip, char *link, unsigned int
 	}
 
 	if (errCount > 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	return 0;
 }
@@ -3156,7 +3156,7 @@ static int lxc_delete_ipv6_l2proxy(struct in6_addr *ip, char *link, unsigned int
 
 	if (!inet_ntop(AF_INET6, ip, bufinet6, sizeof(bufinet6))) {
 		SYSERROR("Failed to convert IP for l2proxy ipv6 removal on dev \"%s\"", link);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	/* If a local-loopback ifindex supplied remove the static route to the lo device. */
@@ -3174,7 +3174,7 @@ static int lxc_delete_ipv6_l2proxy(struct in6_addr *ip, char *link, unsigned int
 	}
 
 	if (errCount > 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	return 0;
 }
@@ -3209,7 +3209,7 @@ static int lxc_delete_l2proxy(struct lxc_netdev *netdev) {
 	}
 
 	if (errCount > 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	return 0;
 }
@@ -3766,12 +3766,12 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
 			if (err < 0) {
 				SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
 				         current_ifname);
-				return minus_one_set_errno(-err);
+				return ret_set_errno(-1, -err);
 			}
 		} else {
 			/* Check the gateway address is valid */
 			if (!inet_ntop(AF_INET, netdev->ipv4_gateway, bufinet4, sizeof(bufinet4)))
-				return minus_one_set_errno(errno);
+				return ret_set_errno(-1, errno);
 
 			/* Try adding a default route to the gateway address */
 			err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
@@ -3820,12 +3820,12 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
 			if (err < 0) {
 				SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
 				         current_ifname);
-				return minus_one_set_errno(-err);
+				return ret_set_errno(-1, -err);
 			}
 		} else {
 			/* Check the gateway address is valid */
 			if (!inet_ntop(AF_INET6, netdev->ipv6_gateway, bufinet6, sizeof(bufinet6)))
-				return minus_one_set_errno(errno);
+				return ret_set_errno(-1, errno);
 
 			/* Try adding a default route to the gateway address */
 			err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);

From 21fce08cb69ab6c912c68fb8aefcdfa1a6fbe166 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:25:28 +0100
Subject: [PATCH 07/44] confile: replace logging helpers

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

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 79fef103ab..c27d432d81 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -401,11 +401,11 @@ static int set_config_net_l2proxy(const char *key, const char *value,
 		return clr_config_net_l2proxy(key, lxc_conf, data);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	ret = lxc_safe_uint(value, &val);
 	if (ret < 0)
-		return minus_one_set_errno(-ret);
+		return ret_set_errno(-1, -ret);
 
 	switch (val) {
 	case 0:
@@ -416,7 +416,7 @@ static int set_config_net_l2proxy(const char *key, const char *value,
 		return 0;
 	}
 
-	return minus_one_set_errno(EINVAL);
+	return ret_set_errno(-1, EINVAL);
 }
 
 static int set_config_net_name(const char *key, const char *value,
@@ -485,11 +485,11 @@ static int set_config_net_ipvlan_mode(const char *key, const char *value,
 		return clr_config_net_ipvlan_mode(key, lxc_conf, data);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN) {
 		SYSERROR("Invalid ipvlan mode \"%s\", can only be used with ipvlan network", value);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	return lxc_ipvlan_mode_to_flag(&netdev->priv.ipvlan_attr.mode, value);
@@ -504,11 +504,11 @@ static int set_config_net_ipvlan_isolation(const char *key, const char *value,
 		return clr_config_net_ipvlan_isolation(key, lxc_conf, data);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN) {
 		SYSERROR("Invalid ipvlan isolation \"%s\", can only be used with ipvlan network", value);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	return lxc_ipvlan_isolation_to_flag(&netdev->priv.ipvlan_attr.isolation, value);
@@ -729,11 +729,11 @@ static int set_config_net_veth_ipv4_route(const char *key, const char *value,
 		return clr_config_net_veth_ipv4_route(key, lxc_conf, data);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH) {
 		SYSERROR("Invalid ipv4 route \"%s\", can only be used with veth network", value);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	inetdev = malloc(sizeof(*inetdev));
@@ -754,22 +754,22 @@ static int set_config_net_veth_ipv4_route(const char *key, const char *value,
 
 	slash = strchr(valdup, '/');
 	if (!slash)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	*slash = '\0';
 	slash++;
 	if (*slash == '\0')
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	netmask = slash;
 
 	ret = lxc_safe_uint(netmask, &inetdev->prefix);
 	if (ret < 0 || inetdev->prefix > 32)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	ret = inet_pton(AF_INET, valdup, &inetdev->addr);
 	if (!ret || ret < 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	lxc_list_add_tail(&netdev->priv.veth_attr.ipv4_routes, list);
 	move_ptr(inetdev);
@@ -900,11 +900,11 @@ static int set_config_net_veth_ipv6_route(const char *key, const char *value,
 		return clr_config_net_veth_ipv6_route(key, lxc_conf, data);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH) {
 		SYSERROR("Invalid ipv6 route \"%s\", can only be used with veth network", value);
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 	}
 
 	inet6dev = malloc(sizeof(*inet6dev));
@@ -925,22 +925,22 @@ static int set_config_net_veth_ipv6_route(const char *key, const char *value,
 
 	slash = strchr(valdup, '/');
 	if (!slash)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	*slash = '\0';
 	slash++;
 	if (*slash == '\0')
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	netmask = slash;
 
 	ret = lxc_safe_uint(netmask, &inet6dev->prefix);
 	if (ret < 0 || inet6dev->prefix > 128)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	ret = inet_pton(AF_INET6, valdup, &inet6dev->addr);
 	if (!ret || ret < 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	lxc_list_add_tail(&netdev->priv.veth_attr.ipv6_routes, list);
 	move_ptr(inet6dev);
@@ -1004,7 +1004,7 @@ static int set_config_seccomp_allow_nesting(const char *key, const char *value,
 		return -1;
 
 	if (lxc_conf->seccomp.allow_nesting > 1)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	return 0;
 #else
@@ -1019,7 +1019,7 @@ static int set_config_seccomp_notify_cookie(const char *key, const char *value,
 #ifdef HAVE_SECCOMP_NOTIFY
 	return set_config_string_item(&lxc_conf->seccomp.notifier.cookie, value);
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -1033,7 +1033,7 @@ static int set_config_seccomp_notify_proxy(const char *key, const char *value,
 		return clr_config_seccomp_notify_proxy(key, lxc_conf, NULL);
 
 	if (strncmp(value, "unix:", 5) != 0)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	offset = value + 5;
 	if (lxc_unix_sockaddr(&lxc_conf->seccomp.notifier.proxy_addr, offset) < 0)
@@ -1041,7 +1041,7 @@ static int set_config_seccomp_notify_proxy(const char *key, const char *value,
 
 	return 0;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -3985,7 +3985,7 @@ static int get_config_seccomp_notify_cookie(const char *key, char *retv, int inl
 #ifdef HAVE_SECCOMP_NOTIFY
 	return lxc_get_conf_str(retv, inlen, c->seccomp.notifier.cookie);
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -3998,7 +3998,7 @@ static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inle
 				    ? &c->seccomp.notifier.proxy_addr.sun_path[0]
 				    : &c->seccomp.notifier.proxy_addr.sun_path[1]);
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -4611,7 +4611,7 @@ static inline int clr_config_seccomp_notify_cookie(const char *key,
 	c->seccomp.notifier.cookie = NULL;
 	return 0;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -4623,7 +4623,7 @@ static inline int clr_config_seccomp_notify_proxy(const char *key,
 	       sizeof(c->seccomp.notifier.proxy_addr));
 	return 0;
 #else
-	return minus_one_set_errno(ENOSYS);
+	return ret_set_errno(-1, ENOSYS);
 #endif
 }
 
@@ -5064,7 +5064,7 @@ static int clr_config_net_l2proxy(const char *key, struct lxc_conf *lxc_conf,
 	struct lxc_netdev *netdev = data;
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	netdev->l2proxy = false;
 
@@ -5093,7 +5093,7 @@ static int clr_config_net_ipvlan_mode(const char *key,
 	struct lxc_netdev *netdev = data;
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN)
 		return 0;
@@ -5109,7 +5109,7 @@ static int clr_config_net_ipvlan_isolation(const char *key,
 	struct lxc_netdev *netdev = data;
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN)
 		return 0;
@@ -5125,7 +5125,7 @@ static int clr_config_net_veth_mode(const char *key,
 	struct lxc_netdev *netdev = data;
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH)
 		return 0;
@@ -5493,7 +5493,7 @@ static int get_config_net_ipvlan_mode(const char *key, char *retv, int inlen,
 		memset(retv, 0, inlen);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN)
 		return 0;
@@ -5532,7 +5532,7 @@ static int get_config_net_ipvlan_isolation(const char *key, char *retv, int inle
 		memset(retv, 0, inlen);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_IPVLAN)
 		return 0;
@@ -5571,7 +5571,7 @@ static int get_config_net_veth_mode(const char *key, char *retv, int inlen,
 		memset(retv, 0, inlen);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH)
 		return 0;
@@ -5800,7 +5800,7 @@ static int get_config_net_veth_ipv4_route(const char *key, char *retv, int inlen
 		memset(retv, 0, inlen);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH)
 		return 0;
@@ -5891,7 +5891,7 @@ static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen
 		memset(retv, 0, inlen);
 
 	if (!netdev)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (netdev->type != LXC_NET_VETH)
 		return 0;

From d220323012d3bc176461018cc1743ac05e789cb7 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:28:06 +0100
Subject: [PATCH 08/44] cgroups/cgfsng: replace logging functions

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index d5ddc8388d..e88e158d0a 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1941,7 +1941,7 @@ static bool cg_legacy_freeze(struct cgroup_ops *ops)
 
 	h = get_hierarchy(ops, "freezer");
 	if (!h)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	path = must_make_path(h->container_full_path, "freezer.state", NULL);
 	return lxc_write_to_file(path, "FROZEN", STRLITERALLEN("FROZEN"), false, 0666);
@@ -1992,10 +1992,10 @@ static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 
 	h = ops->unified;
 	if (!h)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	if (!h->container_full_path)
-		return minus_one_set_errno(EEXIST);
+		return ret_set_errno(-1, EEXIST);
 
 	if (timeout != 0) {
 		__do_free char *events_file = NULL;
@@ -2003,27 +2003,27 @@ static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 		events_file = must_make_path(h->container_full_path, "cgroup.events", NULL);
 		fd = open(events_file, O_RDONLY | O_CLOEXEC);
 		if (fd < 0)
-			return error_log_errno(errno, "Failed to open cgroup.events file");
+			return log_error_errno(-1, errno, "Failed to open cgroup.events file");
 
 		ret = lxc_mainloop_open(&descr);
 		if (ret)
-			return error_log_errno(errno, "Failed to create epoll instance to wait for container freeze");
+			return log_error_errno(-1, errno, "Failed to create epoll instance to wait for container freeze");
 
 		/* automatically cleaned up now */
 		descr_ptr = &descr;
 
 		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR((int){1}));
 		if (ret < 0)
-			return error_log_errno(errno, "Failed to add cgroup.events fd handler to mainloop");
+			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}
 
 	path = must_make_path(h->container_full_path, "cgroup.freeze", NULL);
 	ret = lxc_write_to_file(path, "1", 1, false, 0666);
 	if (ret < 0)
-		return error_log_errno(errno, "Failed to open cgroup.freeze file");
+		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
 
 	if (timeout != 0 && lxc_mainloop(&descr, timeout))
-		return error_log_errno(errno, "Failed to wait for container to be frozen");
+		return log_error_errno(-1, errno, "Failed to wait for container to be frozen");
 
 	return 0;
 }
@@ -2031,7 +2031,7 @@ static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 __cgfsng_ops static int cgfsng_freeze(struct cgroup_ops *ops, int timeout)
 {
 	if (!ops->hierarchies)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	if (ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED)
 		return cg_legacy_freeze(ops);
@@ -2046,7 +2046,7 @@ static int cg_legacy_unfreeze(struct cgroup_ops *ops)
 
 	h = get_hierarchy(ops, "freezer");
 	if (!h)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	path = must_make_path(h->container_full_path, "freezer.state", NULL);
 	return lxc_write_to_file(path, "THAWED", STRLITERALLEN("THAWED"), false, 0666);
@@ -2063,10 +2063,10 @@ static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 
 	h = ops->unified;
 	if (!h)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	if (!h->container_full_path)
-		return minus_one_set_errno(EEXIST);
+		return ret_set_errno(-1, EEXIST);
 
 	if (timeout != 0) {
 		__do_free char *events_file = NULL;
@@ -2074,27 +2074,27 @@ static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 		events_file = must_make_path(h->container_full_path, "cgroup.events", NULL);
 		fd = open(events_file, O_RDONLY | O_CLOEXEC);
 		if (fd < 0)
-			return error_log_errno(errno, "Failed to open cgroup.events file");
+			return log_error_errno(-1, errno, "Failed to open cgroup.events file");
 
 		ret = lxc_mainloop_open(&descr);
 		if (ret)
-			return error_log_errno(errno, "Failed to create epoll instance to wait for container unfreeze");
+			return log_error_errno(-1, errno, "Failed to create epoll instance to wait for container unfreeze");
 
 		/* automatically cleaned up now */
 		descr_ptr = &descr;
 
 		ret = lxc_mainloop_add_handler(&descr, fd, freezer_cgroup_events_cb, INT_TO_PTR((int){0}));
 		if (ret < 0)
-			return error_log_errno(errno, "Failed to add cgroup.events fd handler to mainloop");
+			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}
 
 	path = must_make_path(h->container_full_path, "cgroup.freeze", NULL);
 	ret = lxc_write_to_file(path, "0", 1, false, 0666);
 	if (ret < 0)
-		return error_log_errno(errno, "Failed to open cgroup.freeze file");
+		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
 
 	if (timeout != 0 && lxc_mainloop(&descr, timeout))
-		return error_log_errno(errno, "Failed to wait for container to be unfrozen");
+		return log_error_errno(-1, errno, "Failed to wait for container to be unfrozen");
 
 	return 0;
 }
@@ -2102,7 +2102,7 @@ static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 __cgfsng_ops static int cgfsng_unfreeze(struct cgroup_ops *ops, int timeout)
 {
 	if (!ops->hierarchies)
-		return minus_one_set_errno(ENOENT);
+		return ret_set_errno(-1, ENOENT);
 
 	if (ops->cgroup_layout != CGROUP_LAYOUT_UNIFIED)
 		return cg_legacy_unfreeze(ops);
@@ -2148,7 +2148,7 @@ static int cgroup_attach_leaf(int unified_fd, int64_t pid)
 		return 0;
 	/* this is a non-leaf node */
 	if (errno != EBUSY)
-		return error_log_errno(errno, "Failed to attach to unified cgroup");
+		return log_error_errno(-1, errno, "Failed to attach to unified cgroup");
 
 	do {
 		char *slash;
@@ -2167,7 +2167,7 @@ static int cgroup_attach_leaf(int unified_fd, int64_t pid)
 		*slash = '\0';
 		ret = mkdirat(unified_fd, attach_cgroup, 0755);
 		if (ret < 0 && errno != EEXIST)
-			return error_log_errno(errno, "Failed to create cgroup %s", attach_cgroup);
+			return log_error_errno(-1, errno, "Failed to create cgroup %s", attach_cgroup);
 
 		*slash = '/';
 		ret = lxc_writeat(unified_fd, attach_cgroup, pidstr, pidstr_len);
@@ -2176,7 +2176,7 @@ static int cgroup_attach_leaf(int unified_fd, int64_t pid)
 
 		/* this is a non-leaf node */
 		if (errno != EBUSY)
-			return error_log_errno(errno, "Failed to attach to unified cgroup");
+			return log_error_errno(-1, errno, "Failed to attach to unified cgroup");
 
 		idx++;
 	} while (idx < 1000);
@@ -2435,7 +2435,7 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
 
 		ret = device_cgroup_rule_parse(&device, key, value);
 		if (ret < 0)
-			return error_log_errno(EINVAL, "Failed to parse device string %s=%s",
+			return log_error_errno(-1, EINVAL, "Failed to parse device string %s=%s",
 					       key, value);
 
 		ret = lxc_cmd_add_bpf_device_cgroup(name, lxcpath, &device);
@@ -2644,7 +2644,7 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops,
 
 	ret = device_cgroup_rule_parse(&device_item, key, val);
 	if (ret < 0)
-		return error_log_errno(EINVAL,
+		return log_error_errno(-1, EINVAL,
 				       "Failed to parse device string %s=%s",
 				       key, val);
 
@@ -3072,14 +3072,14 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative,
 
 	ret = unified_cgroup_hierarchy();
 	if (ret == -ENOMEDIUM)
-		return -ENOMEDIUM;
+		return ret_errno(ENOMEDIUM);
 
 	if (ret != CGROUP2_SUPER_MAGIC)
 		return 0;
 
 	base_cgroup = cg_unified_get_current_cgroup(relative);
 	if (!base_cgroup)
-		return -EINVAL;
+		return ret_errno(EINVAL);
 	if (!relative)
 		prune_init_scope(base_cgroup);
 

From 102dca262246efa419058f14f56717b44b85dec2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:29:12 +0100
Subject: [PATCH 09/44] cgroups/cgroup: replace logging functions

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

diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index 8804d59ac3..84171c18d9 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -24,19 +24,16 @@ struct cgroup_ops *cgroup_init(struct lxc_conf *conf)
 {
 	struct cgroup_ops *cgroup_ops;
 
-	if (!conf) {
-		ERROR("No valid conf given");
-		return NULL;
-	}
+	if (!conf)
+		return log_error_errno(NULL, EINVAL, "No valid conf given");
 
 	cgroup_ops = cgfsng_ops_init(conf);
-	if (!cgroup_ops) {
-		ERROR("Failed to initialize cgroup driver");
-		return NULL;
-	}
+	if (!cgroup_ops)
+		return log_error_errno(NULL, errno, "Failed to initialize cgroup driver");
 
-	if (!cgroup_ops->data_init(cgroup_ops))
-		return NULL;
+	if (cgroup_ops->data_init(cgroup_ops))
+		return log_error_errno(NULL, errno,
+				       "Failed to initialize cgroup data");
 
 	TRACE("Initialized cgroup driver %s", cgroup_ops->driver);
 

From 55cc1116857df23d76eec0b6a2241c7aa3e0f5f3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:30:07 +0100
Subject: [PATCH 10/44] cgroups/cgroup2_devices: replace logging functions

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

diff --git a/src/lxc/cgroups/cgroup2_devices.c b/src/lxc/cgroups/cgroup2_devices.c
index cb6f76abc1..7df8112422 100644
--- a/src/lxc/cgroups/cgroup2_devices.c
+++ b/src/lxc/cgroups/cgroup2_devices.c
@@ -35,11 +35,11 @@ static int bpf_program_add_instructions(struct bpf_program *prog,
 	struct bpf_insn *new_insn;
 
 	if (prog->kernel_fd >= 0)
-		return error_log_errno(EBUSY, "Refusing to update bpf cgroup program that's already loaded");
+		return log_error_errno(-1, EBUSY, "Refusing to update bpf cgroup program that's already loaded");
 
 	new_insn = realloc(prog->instructions, sizeof(struct bpf_insn) * (count + prog->n_instructions));
 	if (!new_insn)
-		return error_log_errno(ENOMEM, "Failed to reallocate bpf cgroup program");
+		return log_error_errno(-1, ENOMEM, "Failed to reallocate bpf cgroup program");
 
 	prog->instructions = new_insn;
 	memcpy(prog->instructions + prog->n_instructions, instructions,
@@ -184,7 +184,7 @@ struct bpf_program *bpf_program_new(uint32_t prog_type)
 int bpf_program_init(struct bpf_program *prog)
 {
 	if (!prog)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	const struct bpf_insn pre_insn[] = {
 	    /* load device type to r2 */
@@ -217,7 +217,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 	int device_type;
 
 	if (!prog || !device)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	/* This is a global rule so no need to append anything. */
 	if (device->global_rule > LXC_BPF_DEVICE_CGROUP_LOCAL_RULE) {
@@ -227,7 +227,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 
 	device_type = bpf_device_type(device->type);
 	if (device_type < 0)
-		return error_log_errno(EINVAL, "Invalid bpf cgroup device type %c", device->type);
+		return log_error_errno(-1, EINVAL, "Invalid bpf cgroup device type %c", device->type);
 
 	if (device_type > 0)
 		jump_nr++;
@@ -249,7 +249,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 
 		ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
 		if (ret)
-			return error_log_errno(errno, "Failed to add instructions to bpf cgroup program");
+			return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
 	}
 
 	if (!bpf_device_all_access(access_mask)) {
@@ -262,7 +262,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 		jump_nr -= 3;
 		ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
 		if (ret)
-			return error_log_errno(errno, "Failed to add instructions to bpf cgroup program");
+			return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
 	}
 
 	if (device->major >= 0) {
@@ -272,7 +272,7 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 
 		ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
 		if (ret)
-			return error_log_errno(errno, "Failed to add instructions to bpf cgroup program");
+			return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
 	}
 
 	if (device->minor >= 0) {
@@ -282,13 +282,13 @@ int bpf_program_append_device(struct bpf_program *prog, struct device_item *devi
 
 		ret = bpf_program_add_instructions(prog, ins, ARRAY_SIZE(ins));
 		if (ret)
-			return error_log_errno(errno, "Failed to add instructions to bpf cgroup program");
+			return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
 	}
 
 	ret = bpf_program_add_instructions(prog, bpf_access_decision,
 					    ARRAY_SIZE(bpf_access_decision));
 	if (ret)
-		return error_log_errno(errno, "Failed to add instructions to bpf cgroup program");
+		return log_error_errno(-1, errno, "Failed to add instructions to bpf cgroup program");
 
 	return 0;
 }
@@ -301,7 +301,7 @@ int bpf_program_finalize(struct bpf_program *prog)
 	};
 
 	if (!prog)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	TRACE("Implementing %s bpf device cgroup program",
 	      prog->device_list_type == LXC_BPF_DEVICE_CGROUP_BLACKLIST
@@ -332,7 +332,7 @@ static int bpf_program_load_kernel(struct bpf_program *prog, char *log_buf,
 
 	prog->kernel_fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 	if (prog->kernel_fd < 0)
-		return error_log_errno(errno, "Failed to load bpf program");
+		return log_error_errno(-1, errno, "Failed to load bpf program");
 
 	return 0;
 }
@@ -346,17 +346,17 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type,
 	int ret;
 
 	if (!prog)
-		return minus_one_set_errno(EINVAL);
+		return ret_set_errno(-1, EINVAL);
 
 	if (flags & ~(BPF_F_ALLOW_OVERRIDE, BPF_F_ALLOW_MULTI))
-		return error_log_errno(EINVAL, "Invalid flags for bpf program");
+		return log_error_errno(-1, EINVAL, "Invalid flags for bpf program");
 
 	if (prog->attached_path) {
 		if (prog->attached_type != type)
-			return error_log_errno(EBUSY, "Wrong type for bpf program");
+			return log_error_errno(-1, EBUSY, "Wrong type for bpf program");
 
 		if (prog->attached_flags != flags)
-			return error_log_errno(EBUSY, "Wrong flags for bpf program");
+			return log_error_errno(-1, EBUSY, "Wrong flags for bpf program");
 
 		if (flags != BPF_F_ALLOW_OVERRIDE)
 			return true;
@@ -364,15 +364,15 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type,
 
 	ret = bpf_program_load_kernel(prog, NULL, 0);
 	if (ret < 0)
-		return error_log_errno(ret, "Failed to load bpf program");
+		return log_error_errno(-1, ret, "Failed to load bpf program");
 
 	copy = strdup(path);
 	if (!copy)
-		return error_log_errno(ENOMEM, "Failed to duplicate cgroup path %s", path);
+		return log_error_errno(-1, ENOMEM, "Failed to duplicate cgroup path %s", path);
 
 	fd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 	if (fd < 0)
-		return error_log_errno(errno, "Failed to open cgroup path %s", path);
+		return log_error_errno(-1, errno, "Failed to open cgroup path %s", path);
 
 	attr = (union bpf_attr){
 	    .attach_type	= type,
@@ -383,7 +383,7 @@ int bpf_program_cgroup_attach(struct bpf_program *prog, int type,
 
 	ret = bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
 	if (ret < 0)
-		return error_log_errno(errno, "Failed to attach bpf program");
+		return log_error_errno(-1, errno, "Failed to attach bpf program");
 
 	free_replace_move_ptr(prog->attached_path, copy);
 	prog->attached_type = type;
@@ -407,7 +407,7 @@ int bpf_program_cgroup_detach(struct bpf_program *prog)
 	fd = open(prog->attached_path, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 	if (fd < 0) {
 		if (errno != ENOENT)
-			return error_log_errno(errno, "Failed to open attach cgroup %s",
+			return log_error_errno(-1, errno, "Failed to open attach cgroup %s",
 					       prog->attached_path);
 	} else {
 		union bpf_attr attr;
@@ -420,7 +420,7 @@ int bpf_program_cgroup_detach(struct bpf_program *prog)
 
 		ret = bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
 		if (ret < 0)
-			return error_log_errno(errno, "Failed to detach bpf program from cgroup %s",
+			return log_error_errno(-1, errno, "Failed to detach bpf program from cgroup %s",
 					       prog->attached_path);
 	}
 
@@ -488,11 +488,11 @@ int bpf_list_add_device(struct lxc_conf *conf, struct device_item *device)
 
 	list_elem = malloc(sizeof(*list_elem));
 	if (!list_elem)
-		return error_log_errno(ENOMEM, "Failed to allocate new device list");
+		return log_error_errno(-1, ENOMEM, "Failed to allocate new device list");
 
 	new_device = memdup(device, sizeof(struct device_item));
 	if (!new_device)
-		return error_log_errno(ENOMEM, "Failed to allocate new device item");
+		return log_error_errno(-1, ENOMEM, "Failed to allocate new device item");
 
 	lxc_list_add_elem(list_elem, move_ptr(new_device));
 	lxc_list_add_tail(&conf->devices, move_ptr(list_elem));

From 341e6516f255753cf4e1d35f75647e4896bf919c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:30:57 +0100
Subject: [PATCH 11/44] cgroups: rework return values of some functions

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 58 ++++++++++++++++++----------------------
 src/lxc/cgroups/cgroup.h |  2 +-
 2 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index e88e158d0a..d981708114 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2887,8 +2887,7 @@ static void cg_unified_delegate(char ***delegate)
 /* At startup, parse_hierarchies finds all the info we need about cgroup
  * mountpoints and current cgroups, and stores it in @d.
  */
-static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
-			   bool unprivileged)
+static int cg_hybrid_init(struct cgroup_ops *ops, bool relative, bool unprivileged)
 {
 	__do_free char *basecginfo = NULL;
 	__do_free char *line = NULL;
@@ -2905,19 +2904,15 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
 	else
 		basecginfo = read_file("/proc/self/cgroup");
 	if (!basecginfo)
-		return false;
+		return ret_set_errno(-1, ENOMEM);
 
 	ret = get_existing_subsystems(&klist, &nlist);
-	if (ret < 0) {
-		ERROR("Failed to retrieve available legacy cgroup controllers");
-		return false;
-	}
+	if (ret < 0)
+		return log_error_errno(-1, errno, "Failed to retrieve available legacy cgroup controllers");
 
 	f = fopen("/proc/self/mountinfo", "r");
-	if (!f) {
-		ERROR("Failed to open \"/proc/self/mountinfo\"");
-		return false;
-	}
+	if (!f)
+		return log_error_errno(-1, errno, "Failed to open \"/proc/self/mountinfo\"");
 
 	lxc_cgfsng_print_basecg_debuginfo(basecginfo, klist, nlist);
 
@@ -2954,22 +2949,18 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
 
 		if (type == CGROUP_SUPER_MAGIC)
 			if (controller_list_is_dup(ops->hierarchies, controller_list))
-				goto next;
+				log_trace_errno(goto next, EEXIST, "Skipping duplicating controller");
 
 		mountpoint = cg_hybrid_get_mountpoint(line);
-		if (!mountpoint) {
-			ERROR("Failed parsing mountpoint from \"%s\"", line);
-			goto next;
-		}
+		if (!mountpoint)
+			log_error_errno(goto next, EINVAL, "Failed parsing mountpoint from \"%s\"", line);
 
 		if (type == CGROUP_SUPER_MAGIC)
 			base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, controller_list[0], CGROUP_SUPER_MAGIC);
 		else
 			base_cgroup = cg_hybrid_get_current_cgroup(basecginfo, NULL, CGROUP2_SUPER_MAGIC);
-		if (!base_cgroup) {
-			ERROR("Failed to find current cgroup");
-			goto next;
-		}
+		if (!base_cgroup)
+			log_error_errno(goto next, EINVAL, "Failed to find current cgroup");
 
 		trim(base_cgroup);
 		prune_init_scope(base_cgroup);
@@ -2978,7 +2969,7 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
 		else
 			writeable = test_writeable_v1(mountpoint, base_cgroup);
 		if (!writeable)
-			goto next;
+			log_trace_errno(goto next, EROFS, "The %s group is not writeable", base_cgroup);
 
 		if (type == CGROUP2_SUPER_MAGIC) {
 			char *cgv2_ctrl_path;
@@ -2998,7 +2989,7 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
 
 		/* Exclude all controllers that cgroup use does not want. */
 		if (!cgroup_use_wants_controllers(ops, controller_list))
-			goto next;
+			log_trace_errno(goto next, EINVAL, "Skipping controller");
 
 		new = add_hierarchy(&ops->hierarchies, controller_list, mountpoint, base_cgroup, type);
 		if (type == CGROUP2_SUPER_MAGIC && !ops->unified) {
@@ -3025,9 +3016,9 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
 	 * controllers are accounted for
 	 */
 	if (!all_controllers_found(ops))
-		return false;
+		return log_error_errno(-1, ENOENT, "Failed to find all required controllers");
 
-	return true;
+	return 0;
 }
 
 /* Get current cgroup from /proc/self/cgroup for the cgroupfs v2 hierarchy. */
@@ -3114,7 +3105,7 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative,
 	return CGROUP2_SUPER_MAGIC;
 }
 
-static bool cg_init(struct cgroup_ops *ops, struct lxc_conf *conf)
+static int cg_init(struct cgroup_ops *ops, struct lxc_conf *conf)
 {
 	int ret;
 	const char *tmp;
@@ -3134,29 +3125,32 @@ static bool cg_init(struct cgroup_ops *ops, struct lxc_conf *conf)
 
 	ret = cg_unified_init(ops, relative, !lxc_list_empty(&conf->id_map));
 	if (ret < 0)
-		return false;
+		return -1;
 
 	if (ret == CGROUP2_SUPER_MAGIC)
-		return true;
+		return 0;
 
 	return cg_hybrid_init(ops, relative, !lxc_list_empty(&conf->id_map));
 }
 
-__cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops)
+__cgfsng_ops static int cgfsng_data_init(struct cgroup_ops *ops)
 {
 	const char *cgroup_pattern;
 
+	if (!ops)
+		return ret_set_errno(-1, ENOENT);
+
 	/* copy system-wide cgroup information */
 	cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
 	if (!cgroup_pattern) {
 		/* lxc.cgroup.pattern is only NULL on error. */
 		ERROR("Failed to retrieve cgroup pattern");
-		return false;
+		return ret_set_errno(-1, ENOMEM);
 	}
 	ops->cgroup_pattern = must_copy_string(cgroup_pattern);
 	ops->monitor_pattern = MONITOR_CGROUP;
 
-	return true;
+	return 0;
 }
 
 struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
@@ -3165,12 +3159,12 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
 
 	cgfsng_ops = malloc(sizeof(struct cgroup_ops));
 	if (!cgfsng_ops)
-		return NULL;
+		return ret_set_errno(NULL, ENOMEM);
 
 	memset(cgfsng_ops, 0, sizeof(struct cgroup_ops));
 	cgfsng_ops->cgroup_layout = CGROUP_LAYOUT_UNKNOWN;
 
-	if (!cg_init(cgfsng_ops, conf))
+	if (cg_init(cgfsng_ops, conf))
 		return NULL;
 
 	cgfsng_ops->unified_fd = -EBADF;
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index 80d2c315a3..dce506aa20 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -132,7 +132,7 @@ struct cgroup_ops {
 	 */
 	cgroup_layout_t cgroup_layout;
 
-	bool (*data_init)(struct cgroup_ops *ops);
+	int (*data_init)(struct cgroup_ops *ops);
 	void (*payload_destroy)(struct cgroup_ops *ops, struct lxc_handler *handler);
 	void (*monitor_destroy)(struct cgroup_ops *ops, struct lxc_handler *handler);
 	bool (*monitor_create)(struct cgroup_ops *ops, struct lxc_handler *handler);

From bf39128d818fcdf8248a029e711ae00e2e803329 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:31:21 +0100
Subject: [PATCH 12/44] confile_utils: replace logging functions

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

diff --git a/src/lxc/confile_utils.c b/src/lxc/confile_utils.c
index fe62d74d51..b5a9f1c1ee 100644
--- a/src/lxc/confile_utils.c
+++ b/src/lxc/confile_utils.c
@@ -503,7 +503,7 @@ int lxc_veth_mode_to_flag(int *mode, const char *value)
 		return 0;
 	}
 
-	return minus_one_set_errno(EINVAL);
+	return ret_set_errno(-1, EINVAL);
 }
 
 static struct lxc_macvlan_mode {

From b18f6aac91dab359e43821b22ae46eb259ca5050 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:31:36 +0100
Subject: [PATCH 13/44] lxccontainer: replace logging functions

Signed-off-by: Christian Brauner <christian.brauner 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 b97b58ec6a..dc977f57b0 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -5262,7 +5262,7 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
 static int do_lxcapi_seccomp_notify_fd(struct lxc_container *c)
 {
 	if (!c || !c->lxc_conf)
-		return minus_one_set_errno(-EINVAL);
+		return ret_set_errno(-1, -EINVAL);
 
 	return lxc_seccomp_get_notify_fd(&c->lxc_conf->seccomp);
 }

From 08e8091de8218dfa0ba67be25a639587913259d7 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:31:50 +0100
Subject: [PATCH 14/44] {log, macro}: remove unused logging functions

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/log.h   | 7 -------
 src/lxc/macro.h | 6 ------
 2 files changed, 13 deletions(-)

diff --git a/src/lxc/log.h b/src/lxc/log.h
index 553bc2a120..d5bfd42e97 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -484,13 +484,6 @@ ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 	} while (0)
 #endif
 
-#define error_log_errno(__errno__, format, ...)  \
-	({                                       \
-		errno = __errno__;               \
-		SYSERROR(format, ##__VA_ARGS__); \
-		-1;                              \
-	})
-
 #define log_error_errno(__ret__, __errno__, format, ...) \
 	({						 \
 		errno = __errno__;			 \
diff --git a/src/lxc/macro.h b/src/lxc/macro.h
index b4c9f4e7c6..68bd6ca844 100644
--- a/src/lxc/macro.h
+++ b/src/lxc/macro.h
@@ -442,12 +442,6 @@ enum {
 		__internal_fd__;            \
 	})
 
-#define minus_one_set_errno(__errno__) \
-	({                             \
-		errno = __errno__;     \
-		-1;                    \
-	})
-
 #define ret_set_errno(__ret__, __errno__) \
 	({                                \
 		errno = __errno__;        \

From 1a080cd740c4fc4a6a9dd6136b2acc2dfa1c4802 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:38:42 +0100
Subject: [PATCH 15/44] compiler: add __unused attribute

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

diff --git a/src/lxc/compiler.h b/src/lxc/compiler.h
index e8adf37c47..2774c6334d 100644
--- a/src/lxc/compiler.h
+++ b/src/lxc/compiler.h
@@ -45,6 +45,13 @@
 #define __returns_twice __attribute__((returns_twice))
 #endif
 
+/* This attribute is required to silence clang warnings */
+#if defined(__GNUC__)
+#define __unused __attribute__ ((unused))
+#else
+#define __unused
+#endif
+
 #define __cgfsng_ops
 
 #endif /* __LXC_COMPILER_H */

From 81102768102dc5f539bf21287433614da608808b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:39:03 +0100
Subject: [PATCH 16/44] attach: replace closing helpers

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

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 3dd56ccb3a..5c50e1a109 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -104,9 +104,8 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 
 static inline void lxc_proc_close_ns_fd(struct lxc_proc_context_info *ctx)
 {
-	for (int i = 0; i < LXC_NS_MAX; i++) {
-		__do_close_prot_errno int fd ATTR_UNUSED = move_fd(ctx->ns_fd[i]);
-	}
+	for (int i = 0; i < LXC_NS_MAX; i++)
+		close_prot_errno_disarm(ctx->ns_fd[i]);
 }
 
 static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
@@ -668,9 +667,8 @@ struct attach_clone_payload {
 
 static void lxc_put_attach_clone_payload(struct attach_clone_payload *p)
 {
-	__do_close_prot_errno int ipc_socket ATTR_UNUSED = p->ipc_socket;
-	__do_close_prot_errno int terminal_slave_fd ATTR_UNUSED = p->terminal_slave_fd;
-
+	close_prot_errno_disarm(p->ipc_socket);
+	close_prot_errno_disarm(p->terminal_slave_fd);
 	if (p->init_ctx) {
 		lxc_proc_put_context_info(p->init_ctx);
 		p->init_ctx = NULL;

From 47d8afa2a6c49e3053a8c249a6c497d0f13cc03b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:39:49 +0100
Subject: [PATCH 17/44] log: replace compiler attributes

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

diff --git a/src/lxc/log.h b/src/lxc/log.h
index d5bfd42e97..99cc4680b6 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -245,10 +245,10 @@ static inline void __lxc_log(const struct lxc_log_category *category,
  */
 #define lxc_log_priority_define(acategory, LEVEL)				\
 										\
-ATTR_UNUSED __attribute__ ((format (printf, 2, 3)))				\
+__unused __attribute__ ((format (printf, 2, 3)))				\
 static inline void LXC_##LEVEL(struct lxc_log_locinfo *, const char *, ...);	\
 										\
-ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
+__unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 					   const char* format, ...)		\
 {										\
 	if (lxc_log_priority_is_enabled(acategory, LXC_LOG_LEVEL_##LEVEL)) {	\

From 9ff57a59182521e50126c333f84a1d9d6e4615e6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:40:05 +0100
Subject: [PATCH 18/44] start: replace compiler attributes

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

diff --git a/src/lxc/start.c b/src/lxc/start.c
index db57600b00..3dd96bc354 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1119,8 +1119,8 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
 static int do_start(void *data)
 {
 	struct lxc_handler *handler = data;
-	ATTR_UNUSED __do_close_prot_errno int data_sock0 = handler->data_sock[0],
-					      data_sock1 = handler->data_sock[1];
+	__unused __do_close_prot_errno int data_sock0 = handler->data_sock[0],
+					   data_sock1 = handler->data_sock[1];
 	__do_close_prot_errno int status_fd = -EBADF;
 	int ret;
 	uid_t new_uid;
@@ -1132,7 +1132,7 @@ static int do_start(void *data)
 
 	lxc_sync_fini_parent(handler);
 
-	if (lxc_abstract_unix_recv_fds(handler->data_sock[1], &status_fd, 1, NULL, 0) < 0) {
+	if (lxc_abstract_unix_recv_fds(data_sock1, &status_fd, 1, NULL, 0) < 0) {
 		ERROR("Failed to receive status file descriptor to child process");
 		goto out_warn_father;
 	}

From 41ad3c906826f1e7b123a6fc5b3cb7e17694d2bd Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 17:40:32 +0100
Subject: [PATCH 19/44] log: remove unused compiler attribute

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

diff --git a/src/lxc/log.h b/src/lxc/log.h
index 99cc4680b6..1d5d444b4e 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -26,13 +26,6 @@
 #define LXC_LOG_PREFIX_SIZE	32
 #define LXC_LOG_BUFFER_SIZE	4096
 
-/* This attribute is required to silence clang warnings */
-#if defined(__GNUC__)
-#define ATTR_UNUSED __attribute__ ((unused))
-#else
-#define ATTR_UNUSED
-#endif
-
 /* predefined lxc log priorities. */
 enum lxc_loglevel {
 	LXC_LOG_LEVEL_TRACE,

From fc1c3af911da0bf5ce88bb7f7ca1c167ecaeba3b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 18:04:17 +0100
Subject: [PATCH 20/44] cgroups/cgfsng: rework cgfsng_payload_destroy()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index d981708114..8a6d6cba5b 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1086,9 +1086,18 @@ __cgfsng_ops static void cgfsng_payload_destroy(struct cgroup_ops *ops,
 	int ret;
 	struct generic_userns_exec_data wrap;
 
+	if (!ops)
+		log_error_errno(return, ENOENT, "Called with uninitialized cgroup operations");
+
 	if (!ops->hierarchies)
 		return;
 
+	if (!handler)
+		log_error_errno(return, EINVAL, "Called with uninitialized handler");
+
+	if (!handler->conf)
+		log_error_errno(return, EINVAL, "Called with uninitialized conf");
+
 	wrap.origuid = 0;
 	wrap.container_cgroup = ops->container_cgroup;
 	wrap.hierarchies = ops->hierarchies;

From b376d3d03a0d2039acda1c57b5c1708ca9622538 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 18:08:25 +0100
Subject: [PATCH 21/44] cgroups/cgfsng: rework cgfsng_monitor_destroy()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 8a6d6cba5b..2549ca628e 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1124,12 +1124,23 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
 						struct lxc_handler *handler)
 {
 	int len;
-	struct lxc_conf *conf = handler->conf;
 	char pidstr[INTTYPE_TO_STRLEN(pid_t)];
+	struct lxc_conf *conf;
+
+	if (!ops)
+		log_error_errno(return, ENOENT, "Called with uninitialized cgroup operations");
 
 	if (!ops->hierarchies)
 		return;
 
+	if (!handler)
+		log_error_errno(return, EINVAL, "Called with uninitialized handler");
+
+	if (!handler->conf)
+		log_error_errno(return, EINVAL, "Called with uninitialized conf");
+
+	conf = handler->conf;
+
 	len = snprintf(pidstr, sizeof(pidstr), "%d", handler->monitor_pid);
 	if (len < 0 || (size_t)len >= sizeof(pidstr))
 		return;
@@ -1164,16 +1175,15 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
 		 * Make sure not to pass in the ro string literal PIVOT_CGROUP
 		 * here.
 		 */
-		if (!cg_legacy_handle_cpuset_hierarchy(h, pivot_cgroup)) {
-			WARN("Failed to handle legacy cpuset controller");
-			continue;
-		}
+		if (!cg_legacy_handle_cpuset_hierarchy(h, pivot_cgroup))
+			log_warn_errno(continue,
+				       errno, "Failed to handle legacy cpuset controller");
 
 		ret = mkdir_p(pivot_path, 0755);
-		if (ret < 0 && errno != EEXIST) {
-			SYSWARN("Failed to create cgroup \"%s\"\n", pivot_path);
-			continue;
-		}
+		if (ret < 0 && errno != EEXIST)
+			log_warn_errno(continue, errno,
+				       "Failed to create cgroup \"%s\"\n",
+				       pivot_path);
 
 		if (chop)
 			*chop = '/';
@@ -1182,10 +1192,10 @@ __cgfsng_ops static void cgfsng_monitor_destroy(struct cgroup_ops *ops,
 		 * cgroup.
 		 */
 		ret = lxc_write_to_file(pivot_path, pidstr, len, false, 0666);
-		if (ret != 0) {
-			SYSWARN("Failed to move monitor %s to \"%s\"\n", pidstr, pivot_path);
-			continue;
-		}
+		if (ret != 0)
+			log_warn_errno(continue, errno,
+				       "Failed to move monitor %s to \"%s\"\n",
+				       pidstr, pivot_path);
 
 		ret = recursive_destroy(h->monitor_full_path);
 		if (ret < 0)

From 0d66e29ae61eb183a10343f6e74dbdda6a770dba Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 18:12:30 +0100
Subject: [PATCH 22/44] cgroups/cgfsng: rework cgfsng_monitor_create()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 28 ++++++++++++++++------------
 src/lxc/log.h            |  8 +++++++-
 2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 2549ca628e..aa90842ffa 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1303,14 +1303,22 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
 	char *offset, *tmp;
 	int i, idx = 0;
 	size_t len;
-	struct lxc_conf *conf = handler->conf;
+	struct lxc_conf *conf;
 
-	if (!conf)
-		return false;
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
 
 	if (!ops->hierarchies)
 		return true;
 
+	if (ops->monitor_cgroup)
+		return ret_set_errno(false, EEXIST);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+
+	conf = handler->conf;
+
 	if (conf->cgroup_meta.dir)
 		tmp = lxc_string_join("/",
 				      (const char *[]){conf->cgroup_meta.dir,
@@ -1320,7 +1328,7 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
 	else
 		tmp = must_make_path(ops->monitor_pattern, handler->name, NULL);
 	if (!tmp)
-		return false;
+		return ret_set_errno(false, ENOMEM);
 
 	len = strlen(tmp) + 5; /* leave room for -NNN\0 */
 	monitor_cgroup = must_realloc(tmp, len);
@@ -1328,11 +1336,8 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
 	*offset = 0;
 
 	do {
-		if (idx) {
-			int ret = snprintf(offset, 5, "-%d", idx);
-			if (ret < 0 || (size_t)ret >= 5)
-				return false;
-		}
+		if (idx)
+			sprintf(offset, "-%d", idx);
 
 		for (i = 0; ops->hierarchies[i]; i++) {
 			if (!monitor_create_path_for_hierarchy(ops->hierarchies[i],
@@ -1351,11 +1356,10 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
 	} while (ops->hierarchies[i] && idx > 0 && idx < 1000);
 
 	if (idx == 1000)
-		return false;
+		return ret_set_errno(false, ERANGE);
 
-	INFO("The monitor process uses \"%s\" as cgroup", monitor_cgroup);
 	ops->monitor_cgroup = move_ptr(monitor_cgroup);
-	return true;
+	return log_info(true, "The monitor process uses \"%s\" as cgroup", monitor_cgroup);
 }
 
 /* Try to create the same cgroup in all hierarchies. Start with cgroup_pattern;
diff --git a/src/lxc/log.h b/src/lxc/log.h
index 1d5d444b4e..5305d55b62 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -512,7 +512,7 @@ __unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 
 #define log_debug_errno(__ret__, __errno__, format, ...) \
 	({						 \
-		errno = __errno__;			\
+		errno = __errno__;		         \
 		SYSDEBUG(format, ##__VA_ARGS__);	 \
 		__ret__;				 \
 	})
@@ -523,6 +523,12 @@ __unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 		__ret__;		      \
 	})
 
+#define log_info(__ret__, format, ...)       \
+	({                                   \
+		INFO(format, ##__VA_ARGS__); \
+		__ret__;                     \
+	})
+
 extern int lxc_log_fd;
 
 extern int lxc_log_syslog(int facility);

From 797fa65e6ddb6b015deb59c8f40232d241ecc9f8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 18:13:54 +0100
Subject: [PATCH 23/44] cgroups/cgfsng: rework cgfsng_monitor_enter()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index aa90842ffa..abd085a6d3 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1445,9 +1445,18 @@ __cgfsng_ops static bool cgfsng_monitor_enter(struct cgroup_ops *ops,
 	char monitor[INTTYPE_TO_STRLEN(pid_t)],
 	    transient[INTTYPE_TO_STRLEN(pid_t)];
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	if (!ops->hierarchies)
 		return true;
 
+	if (!ops->monitor_cgroup)
+		return ret_set_errno(false, ENOENT);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+
 	monitor_len = snprintf(monitor, sizeof(monitor), "%d", handler->monitor_pid);
 	if (handler->transient_pid > 0)
 		transient_len = snprintf(transient, sizeof(transient), "%d",

From 61fbc369f9ff0bf186971693cf420c6b0829ac49 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 18:17:48 +0100
Subject: [PATCH 24/44] cgroups/cgfsng: rework
 cgfsng_{monitor,payload}_delegate_controllers()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index abd085a6d3..2011eb8a28 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2838,10 +2838,10 @@ bool __cgfsng_delegate_controllers(struct cgroup_ops *ops, const char *cgroup)
 			base_path = must_append_path(base_path, parts[i], NULL);
 		target = must_make_path(base_path, "cgroup.subtree_control", NULL);
 		ret = lxc_writeat(-1, target, add_controllers, full_len);
-		if (ret < 0) {
-			SYSERROR("Could not enable \"%s\" controllers in the unified cgroup \"%s\"", add_controllers, target);
-			goto on_error;
-		}
+		if (ret < 0)
+			log_error_errno(goto on_error,
+					errno, "Could not enable \"%s\" controllers in the unified cgroup \"%s\"",
+					add_controllers, target);
 		TRACE("Enable \"%s\" controllers in the unified cgroup \"%s\"", add_controllers, target);
 	}
 
@@ -2854,11 +2854,17 @@ bool __cgfsng_delegate_controllers(struct cgroup_ops *ops, const char *cgroup)
 
 __cgfsng_ops bool cgfsng_monitor_delegate_controllers(struct cgroup_ops *ops)
 {
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	return __cgfsng_delegate_controllers(ops, ops->monitor_cgroup);
 }
 
 __cgfsng_ops bool cgfsng_payload_delegate_controllers(struct cgroup_ops *ops)
 {
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	return __cgfsng_delegate_controllers(ops, ops->container_cgroup);
 }
 

From d606c4e9d2c311f701ec904ca42f92be45633162 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 21:51:58 +0100
Subject: [PATCH 25/44] cgroups/cgfsng: rework cgroup2 unprivileged delegation

We accidently checked files to delegate for privileged container and not for
unprivileged containers in the pure unified case. Fix that and clean up the
delegation file parsing.

Closes #3206.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 42 +++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 2011eb8a28..f42bedd270 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2896,29 +2896,30 @@ static bool cgroup_use_wants_controllers(const struct cgroup_ops *ops,
 
 static void cg_unified_delegate(char ***delegate)
 {
-	__do_free char *tmp = NULL;
-	int idx;
+	__do_free char *buf = NULL;
 	char *standard[] = {"cgroup.subtree_control", "cgroup.threads", NULL};
+	char *token;
+	int idx;
 
-	tmp = read_file("/sys/kernel/cgroup/delegate");
-	if (!tmp) {
+	buf = read_file("/sys/kernel/cgroup/delegate");
+	if (!buf) {
 		for (char **p = standard; p && *p; p++) {
 			idx = append_null_to_list((void ***)delegate);
 			(*delegate)[idx] = must_copy_string(*p);
 		}
-	} else {
-		char *token;
-		lxc_iterate_parts (token, tmp, " \t\n") {
-			/*
-			 * We always need to chown this for both cgroup and
-			 * cgroup2.
-			 */
-			if (strcmp(token, "cgroup.procs") == 0)
-				continue;
+		log_warn_errno(return, errno, "Failed to read /sys/kernel/cgroup/delegate");
+	}
 
-			idx = append_null_to_list((void ***)delegate);
-			(*delegate)[idx] = must_copy_string(token);
-		}
+	lxc_iterate_parts (token, buf, " \t\n") {
+		/*
+		 * We always need to chown this for both cgroup and
+		 * cgroup2.
+		 */
+		if (strcmp(token, "cgroup.procs") == 0)
+			continue;
+
+		idx = append_null_to_list((void ***)delegate);
+		(*delegate)[idx] = must_copy_string(token);
 	}
 }
 
@@ -3112,9 +3113,10 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative,
 	if (!relative)
 		prune_init_scope(base_cgroup);
 
-	/* We assume that we have already been given controllers to delegate
-	 * further down the hierarchy. If not it is up to the user to delegate
-	 * them to us.
+	/*
+	 * We assume that the cgroup we're currently in has been delegated to
+	 * us and we are free to further delege all of the controllers listed
+	 * in cgroup.controllers further down the hierarchy.
 	 */
 	mountpoint = must_copy_string(DEFAULT_CGROUP_MOUNTPOINT);
 	subtree_path = must_make_path(mountpoint, base_cgroup, "cgroup.controllers", NULL);
@@ -3132,7 +3134,7 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative,
 	 */
 
 	new = add_hierarchy(&ops->hierarchies, delegatable, mountpoint, base_cgroup, CGROUP2_SUPER_MAGIC);
-	if (!unprivileged)
+	if (unprivileged)
 		cg_unified_delegate(&new->cgroup2_chown);
 
 	if (bpf_devices_cgroup_supported())

From 803e41235fd20039999734d4ca0f368197d4100c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 22:04:04 +0100
Subject: [PATCH 26/44] cgroups/cgfsng: log chown_cgroup_wrapper()

It's becoming more important on cgroup2 to properly delegate cgroups.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 43 +++++++++++++++++++++++-----------------
 src/lxc/log.h            |  7 +++++++
 2 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index f42bedd270..2eb0d0aee6 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1545,24 +1545,20 @@ static int chown_cgroup_wrapper(void *data)
 	gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid;
 
 	ret = setresgid(nsgid, nsgid, nsgid);
-	if (ret < 0) {
-		SYSERROR("Failed to setresgid(%d, %d, %d)",
-			 (int)nsgid, (int)nsgid, (int)nsgid);
-		return -1;
-	}
+	if (ret < 0)
+		return log_error_errno(-1, errno,
+				       "Failed to setresgid(%d, %d, %d)",
+				       (int)nsgid, (int)nsgid, (int)nsgid);
 
 	ret = setresuid(nsuid, nsuid, nsuid);
-	if (ret < 0) {
-		SYSERROR("Failed to setresuid(%d, %d, %d)",
-			 (int)nsuid, (int)nsuid, (int)nsuid);
-		return -1;
-	}
+	if (ret < 0)
+		return log_error_errno(-1, errno,
+				       "Failed to setresuid(%d, %d, %d)",
+				       (int)nsuid, (int)nsuid, (int)nsuid);
 
 	ret = setgroups(0, NULL);
-	if (ret < 0 && errno != EPERM) {
-		SYSERROR("Failed to setgroups(0, NULL)");
-		return -1;
-	}
+	if (ret < 0 && errno != EPERM)
+		return log_error_errno(-1, errno, "Failed to setgroups(0, NULL)");
 
 	destuid = get_ns_uid(arg->origuid);
 	if (destuid == LXC_INVALID_UID)
@@ -1574,7 +1570,9 @@ static int chown_cgroup_wrapper(void *data)
 
 		ret = chowmod(path, destuid, nsgid, 0775);
 		if (ret < 0)
-			return -1;
+			log_info_errno(continue,
+				       errno, "Failed to change %s to uid %d and gid %d and mode 0755",
+				       path, destuid, nsgid);
 
 		/* Failures to chown() these are inconvenient but not
 		 * detrimental We leave these owned by the container launcher,
@@ -1585,18 +1583,27 @@ static int chown_cgroup_wrapper(void *data)
 
 		if (arg->hierarchies[i]->version == CGROUP_SUPER_MAGIC) {
 			fullpath = must_make_path(path, "tasks", NULL);
-			(void)chowmod(fullpath, destuid, nsgid, 0664);
+			ret = chowmod(fullpath, destuid, nsgid, 0664);
+			if (ret < 0)
+				SYSINFO("Failed to change %s to uid %d and gid %d and mode 0664",
+					fullpath, destuid, nsgid);
 		}
 
 		fullpath = must_make_path(path, "cgroup.procs", NULL);
-		(void)chowmod(fullpath, destuid, nsgid, 0664);
+		ret = chowmod(fullpath, destuid, nsgid, 0664);
+		if (ret < 0)
+			SYSINFO("Failed to change %s to uid %d and gid %d and mode 0664",
+				fullpath, destuid, nsgid);
 
 		if (arg->hierarchies[i]->version != CGROUP2_SUPER_MAGIC)
 			continue;
 
 		for (char **p = arg->hierarchies[i]->cgroup2_chown; p && *p; p++) {
 			fullpath = must_make_path(path, *p, NULL);
-			(void)chowmod(fullpath, destuid, nsgid, 0664);
+			ret = chowmod(fullpath, destuid, nsgid, 0664);
+			if (ret < 0)
+				SYSINFO("Failed to change %s to uid %d and gid %d and mode 0664",
+					fullpath, destuid, nsgid);
 		}
 	}
 
diff --git a/src/lxc/log.h b/src/lxc/log.h
index 5305d55b62..b5df492fec 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -523,6 +523,13 @@ __unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 		__ret__;		      \
 	})
 
+#define log_info_errno(__ret__, __errno__, format, ...) \
+	({                                              \
+		errno = __errno__;                      \
+		SYSINFO(format, ##__VA_ARGS__);         \
+		__ret__;                                \
+	})
+
 #define log_info(__ret__, format, ...)       \
 	({                                   \
 		INFO(format, ##__VA_ARGS__); \

From 6e8703a41195c6b7e45b16efdfb36b3f266b8fe7 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 22:12:00 +0100
Subject: [PATCH 27/44] cgroups/cgfsng: don't dereference NULL-pointer

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 2eb0d0aee6..97dd0b3741 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1359,7 +1359,7 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
 		return ret_set_errno(false, ERANGE);
 
 	ops->monitor_cgroup = move_ptr(monitor_cgroup);
-	return log_info(true, "The monitor process uses \"%s\" as cgroup", monitor_cgroup);
+	return log_info(true, "The monitor process uses \"%s\" as cgroup", ops->monitor_cgroup);
 }
 
 /* Try to create the same cgroup in all hierarchies. Start with cgroup_pattern;

From ad275c16050c27c3c0a90543eada75edc9933b9c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 22:19:20 +0100
Subject: [PATCH 28/44] cgroups/cgfsng: rework cgroup attach

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 97dd0b3741..cdb1e7eb2d 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2176,39 +2176,41 @@ static inline char *build_full_cgpath_from_monitorpath(struct hierarchy *h,
 
 static int cgroup_attach_leaf(int unified_fd, int64_t pid)
 {
-	int idx = 0;
+	int idx = 1;
 	int ret;
 	char pidstr[INTTYPE_TO_STRLEN(int64_t) + 1];
+	char attach_cgroup[STRLITERALLEN("lxc-1000/cgroup.procs") + 1];
 	size_t pidstr_len;
 
+	/* Create leaf cgroup. */
+	ret = mkdirat(unified_fd, "lxc", 0755);
+	if (ret < 0 && errno != EEXIST)
+		return log_error_errno(-1, errno, "Failed to create leaf cgroup \"lxc\"");
+
 	pidstr_len = sprintf(pidstr, INT64_FMT, pid);
-	ret = lxc_writeat(unified_fd, "cgroup.procs", pidstr, pidstr_len);
+	ret = lxc_writeat(unified_fd, "lxc/cgroup.procs", pidstr, pidstr_len);
+	if (ret < 0)
+		ret = lxc_writeat(unified_fd, "cgroup.procs", pidstr, pidstr_len);
 	if (ret == 0)
 		return 0;
+
 	/* this is a non-leaf node */
 	if (errno != EBUSY)
 		return log_error_errno(-1, errno, "Failed to attach to unified cgroup");
 
 	do {
 		char *slash;
-		char attach_cgroup[STRLITERALLEN("lxc-1000/cgroup.procs") + 1];
-
-		if (idx)
-			ret = snprintf(attach_cgroup, sizeof(attach_cgroup),
-				       "lxc-%d/cgroup.procs", idx);
-		else
-			ret = snprintf(attach_cgroup, sizeof(attach_cgroup),
-				       "lxc/cgroup.procs");
-		if (ret < 0 || (size_t)ret >= sizeof(attach_cgroup))
-			return -1;
 
+		sprintf(attach_cgroup, "lxc-%d/cgroup.procs", idx);
 		slash = &attach_cgroup[ret] - STRLITERALLEN("/cgroup.procs");
 		*slash = '\0';
+
 		ret = mkdirat(unified_fd, attach_cgroup, 0755);
 		if (ret < 0 && errno != EEXIST)
 			return log_error_errno(-1, errno, "Failed to create cgroup %s", attach_cgroup);
 
 		*slash = '/';
+
 		ret = lxc_writeat(unified_fd, attach_cgroup, pidstr, pidstr_len);
 		if (ret == 0)
 			return 0;
@@ -2220,7 +2222,7 @@ static int cgroup_attach_leaf(int unified_fd, int64_t pid)
 		idx++;
 	} while (idx < 1000);
 
-	return -1;
+	return log_error_errno(-1, errno, "Failed to attach to unified cgroup");
 }
 
 int cgroup_attach(const char *name, const char *lxcpath, int64_t pid)

From 53675a8d1fcd34ae0316e7e75f5ec72449c7bfd8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 7 Dec 2019 23:47:16 +0100
Subject: [PATCH 29/44] tree-wide: s/__unused/__lxc_unused/g

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/compiler.h | 4 ++--
 src/lxc/log.h      | 4 ++--
 src/lxc/start.c    | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/lxc/compiler.h b/src/lxc/compiler.h
index 2774c6334d..ad9ac9033a 100644
--- a/src/lxc/compiler.h
+++ b/src/lxc/compiler.h
@@ -47,9 +47,9 @@
 
 /* This attribute is required to silence clang warnings */
 #if defined(__GNUC__)
-#define __unused __attribute__ ((unused))
+#define __lxc_unused __attribute__ ((unused))
 #else
-#define __unused
+#define __lxc_unused
 #endif
 
 #define __cgfsng_ops
diff --git a/src/lxc/log.h b/src/lxc/log.h
index b5df492fec..db4129493d 100644
--- a/src/lxc/log.h
+++ b/src/lxc/log.h
@@ -238,10 +238,10 @@ static inline void __lxc_log(const struct lxc_log_category *category,
  */
 #define lxc_log_priority_define(acategory, LEVEL)				\
 										\
-__unused __attribute__ ((format (printf, 2, 3)))				\
+__lxc_unused __attribute__ ((format (printf, 2, 3)))				\
 static inline void LXC_##LEVEL(struct lxc_log_locinfo *, const char *, ...);	\
 										\
-__unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
+__lxc_unused static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,	\
 					   const char* format, ...)		\
 {										\
 	if (lxc_log_priority_is_enabled(acategory, LXC_LOG_LEVEL_##LEVEL)) {	\
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 3dd96bc354..851518b116 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1119,7 +1119,7 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
 static int do_start(void *data)
 {
 	struct lxc_handler *handler = data;
-	__unused __do_close_prot_errno int data_sock0 = handler->data_sock[0],
+	__lxc_unused __do_close_prot_errno int data_sock0 = handler->data_sock[0],
 					   data_sock1 = handler->data_sock[1];
 	__do_close_prot_errno int status_fd = -EBADF;
 	int ret;

From f3839f1225fa99ce26acfced6d808ed2abf7fc70 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:06:59 +0100
Subject: [PATCH 30/44] cgroups/cgfsng: rework cgfsng_payload_create()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index cdb1e7eb2d..d1a18174cf 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1366,32 +1366,36 @@ __cgfsng_ops static inline bool cgfsng_monitor_create(struct cgroup_ops *ops,
  * next cgroup_pattern-1, -2, ..., -999.
  */
 __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
-							struct lxc_handler *handler)
+						      struct lxc_handler *handler)
 {
 	__do_free char *container_cgroup = NULL, *tmp = NULL;
+	int idx = 0;
 	int i, ret;
 	size_t len;
 	char *offset;
-	int idx = 0;
-	struct lxc_conf *conf = handler->conf;
-
-	if (ops->container_cgroup)
-		return false;
+	struct lxc_conf *conf;
 
-	if (!conf)
-		return false;
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
 
 	if (!ops->hierarchies)
 		return true;
 
+	if (ops->container_cgroup)
+		return ret_set_errno(false, EEXIST);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+
+	conf = handler->conf;
+
 	if (conf->cgroup_meta.dir)
 		tmp = lxc_string_join("/", (const char *[]){conf->cgroup_meta.dir, handler->name, NULL}, false);
 	else
 		tmp = lxc_string_replace("%n", handler->name, ops->cgroup_pattern);
-	if (!tmp) {
-		ERROR("Failed expanding cgroup name pattern");
-		return false;
-	}
+	if (!tmp)
+		return log_error_errno(false, ENOMEM,
+				       "Failed expanding cgroup name pattern");
 
 	len = strlen(tmp) + 5; /* leave room for -NNN\0 */
 	container_cgroup = must_realloc(NULL, len);
@@ -1399,11 +1403,8 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
 	offset = container_cgroup + len - 5;
 
 	do {
-		if (idx) {
-			ret = snprintf(offset, 5, "-%d", idx);
-			if (ret < 0 || (size_t)ret >= 5)
-				return false;
-		}
+		if (idx)
+			sprintf(offset, "-%d", idx);
 
 		for (i = 0; ops->hierarchies[i]; i++) {
 			if (!container_create_path_for_hierarchy(ops->hierarchies[i],
@@ -1421,7 +1422,7 @@ __cgfsng_ops static inline bool cgfsng_payload_create(struct cgroup_ops *ops,
 	} while (ops->hierarchies[i] && idx > 0 && idx < 1000);
 
 	if (idx == 1000)
-		return false;
+		return ret_set_errno(false, ERANGE);
 
 	INFO("The container process uses \"%s\" as cgroup", container_cgroup);
 	ops->container_cgroup = move_ptr(container_cgroup);

From 4490328e59901bf16290279445d8eea1f8fce454 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:13:14 +0100
Subject: [PATCH 31/44] cgroups/cgfsng: rework cgfsng_payload_enter()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index d1a18174cf..1638f5d528 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1491,9 +1491,18 @@ __cgfsng_ops static bool cgfsng_payload_enter(struct cgroup_ops *ops,
 	int len;
 	char pidstr[INTTYPE_TO_STRLEN(pid_t)];
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	if (!ops->hierarchies)
 		return true;
 
+	if (!ops->container_cgroup)
+		return ret_set_errno(false, ENOENT);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+
 	len = snprintf(pidstr, sizeof(pidstr), "%d", handler->pid);
 
 	for (int i = 0; ops->hierarchies[i]; i++) {

From 52d08ab033460d704466bf34b7b84ced3a1d7905 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:16:59 +0100
Subject: [PATCH 32/44] cgroups/cgfsng: rework cgfsng_escape()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 1638f5d528..932425e813 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1930,23 +1930,33 @@ __cgfsng_ops static int cgfsng_nrtasks(struct cgroup_ops *ops)
 
 /* Only root needs to escape to the cgroup of its init. */
 __cgfsng_ops static bool cgfsng_escape(const struct cgroup_ops *ops,
-					 struct lxc_conf *conf)
+				       struct lxc_conf *conf)
 {
-	if (conf->cgroup_meta.relative || geteuid() || !ops->hierarchies)
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
+	if (!ops->hierarchies)
+		return true;
+
+	if (!conf)
+		return ret_set_errno(false, EINVAL);
+
+	if (conf->cgroup_meta.relative || geteuid())
 		return true;
 
 	for (int i = 0; ops->hierarchies[i]; i++) {
-		int ret;
 		__do_free char *fullpath = NULL;
+		int ret;
 
-		fullpath = must_make_path(ops->hierarchies[i]->mountpoint,
-					  ops->hierarchies[i]->container_base_path,
-					  "cgroup.procs", NULL);
+		fullpath =
+		    must_make_path(ops->hierarchies[i]->mountpoint,
+				   ops->hierarchies[i]->container_base_path,
+				   "cgroup.procs", NULL);
 		ret = lxc_write_to_file(fullpath, "0", 2, false, 0666);
-		if (ret != 0) {
-			SYSERROR("Failed to escape to cgroup \"%s\"", fullpath);
-			return false;
-		}
+		if (ret != 0)
+			return log_error_errno(false,
+					       errno, "Failed to escape to cgroup \"%s\"",
+					       fullpath);
 	}
 
 	return true;

From e3ffb28bd03b6ed491367f81fbf1e7889fb3e5b0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:17:58 +0100
Subject: [PATCH 33/44] cgroups/cgfsng: rework cgfsng_num_hierarchies()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 932425e813..f52d61dad5 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1966,6 +1966,9 @@ __cgfsng_ops static int cgfsng_num_hierarchies(struct cgroup_ops *ops)
 {
 	int i = 0;
 
+	if (!ops)
+		return ret_set_errno(-1, ENOENT);
+
 	if (!ops->hierarchies)
 		return 0;
 

From aa48a34fac85d825d4bbf116521e1176db1230f2 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:18:52 +0100
Subject: [PATCH 34/44] cgroups/cgfsng: rework cgfsng_get_hierarchies()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index f52d61dad5..a3611c1308 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1978,24 +1978,27 @@ __cgfsng_ops static int cgfsng_num_hierarchies(struct cgroup_ops *ops)
 	return i;
 }
 
-__cgfsng_ops static bool cgfsng_get_hierarchies(struct cgroup_ops *ops, int n, char ***out)
+__cgfsng_ops static bool cgfsng_get_hierarchies(struct cgroup_ops *ops, int n,
+						char ***out)
 {
 	int i;
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	if (!ops->hierarchies)
 		return false;
 
 	/* sanity check n */
 	for (i = 0; i < n; i++)
 		if (!ops->hierarchies[i])
-			return false;
+			return ret_set_errno(false, ENOENT);
 
 	*out = ops->hierarchies[i]->controllers;
 
 	return true;
 }
 
-
 static bool cg_legacy_freeze(struct cgroup_ops *ops)
 {
 	__do_free char *path = NULL;

From 6bdf9691525b11f5a418a04fee363875901bb295 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:20:02 +0100
Subject: [PATCH 35/44] cgroups/cgfsng: rework cgfsng_unfreeze()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index a3611c1308..3cb2fe08de 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2176,18 +2176,19 @@ __cgfsng_ops static int cgfsng_unfreeze(struct cgroup_ops *ops, int timeout)
 }
 
 __cgfsng_ops static const char *cgfsng_get_cgroup(struct cgroup_ops *ops,
-						    const char *controller)
+						  const char *controller)
 {
 	struct hierarchy *h;
 
 	h = get_hierarchy(ops, controller);
-	if (!h) {
-		WARN("Failed to find hierarchy for controller \"%s\"",
-		     controller ? controller : "(null)");
-		return NULL;
-	}
+	if (!h)
+		return log_warn_errno(NULL,
+				      ENOENT, "Failed to find hierarchy for controller \"%s\"",
+				      controller ? controller : "(null)");
 
-	return h->container_full_path ? h->container_full_path + strlen(h->mountpoint) : NULL;
+	return h->container_full_path
+		   ? h->container_full_path + strlen(h->mountpoint)
+		   : NULL;
 }
 
 /* Given a cgroup path returned from lxc_cmd_get_cgroup_path, build a full path,

From a358028a7c1443a3bda816f950abaa156a8c758d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:24:20 +0100
Subject: [PATCH 36/44] cgroups/cgfsng: rework cgfsng_{get,set}()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 3cb2fe08de..30bf3093d4 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2353,6 +2353,9 @@ __cgfsng_ops static int cgfsng_get(struct cgroup_ops *ops, const char *filename,
 	struct hierarchy *h;
 	int ret = -1;
 
+	if (!ops)
+		return ret_set_errno(-1, ENOENT);
+
 	controller = must_copy_string(filename);
 	p = strchr(controller, '.');
 	if (p)
@@ -2493,6 +2496,9 @@ __cgfsng_ops static int cgfsng_set(struct cgroup_ops *ops,
 	struct hierarchy *h;
 	int ret = -1;
 
+	if (!ops)
+		return ret_set_errno(-1, ENOENT);
+
 	controller = must_copy_string(key);
 	p = strchr(controller, '.');
 	if (p)

From 92ca7eb54f05555b9480d471e6341fef504d7ef8 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:27:22 +0100
Subject: [PATCH 37/44] cgroups/cgfsng: rework cgfsng_setup_limits_legacy()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 30bf3093d4..f4d142d26d 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2664,11 +2664,18 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
 	struct lxc_cgroup *cg;
 	bool ret = false;
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
+	if (!conf)
+		return ret_set_errno(false, EINVAL);
+
+	cgroup_settings = &conf->cgroup;
 	if (lxc_list_empty(cgroup_settings))
 		return true;
 
 	if (!ops->hierarchies)
-		return false;
+		return ret_set_errno(false, EINVAL);
 
 	sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings);
 	if (!sorted_cgroup_settings)
@@ -2679,14 +2686,13 @@ __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
 
 		if (do_devices == !strncmp("devices", cg->subsystem, 7)) {
 			if (cg_legacy_set_data(ops, cg->subsystem, cg->value)) {
-				if (do_devices && (errno == EACCES || errno == EPERM)) {
-					WARN("Failed to set \"%s\" to \"%s\"",
-					     cg->subsystem, cg->value);
-					continue;
-				}
-				WARN("Failed to set \"%s\" to \"%s\"",
-				     cg->subsystem, cg->value);
-				goto out;
+				if (do_devices && (errno == EACCES || errno == EPERM))
+					log_warn_errno(continue,
+						       errno, "Failed to set \"%s\" to \"%s\"",
+						       cg->subsystem, cg->value);
+				log_warn_errno(goto out, errno,
+					       "Failed to set \"%s\" to \"%s\"",
+					       cg->subsystem, cg->value);
 			}
 			DEBUG("Set controller \"%s\" set to \"%s\"",
 			      cg->subsystem, cg->value);

From 7e31931f100b868a331c6143d99387804bf53998 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:33:24 +0100
Subject: [PATCH 38/44] cgroups/cgfsng: rework cgfsng_setup_limits()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index f4d142d26d..836b89f68d 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2738,16 +2738,30 @@ static int bpf_device_cgroup_prepare(struct cgroup_ops *ops,
 __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
 					     struct lxc_handler *handler)
 {
-	struct lxc_list *iterator;
-	struct hierarchy *h = ops->unified;
-	struct lxc_conf *conf = handler->conf;
-	struct lxc_list *cgroup_settings = &conf->cgroup2;
+	struct lxc_list *cgroup_settings, *iterator;
+	struct hierarchy *h;
+	struct lxc_conf *conf;
 
-	if (lxc_list_empty(cgroup_settings))
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
+	if (!ops->hierarchies)
 		return true;
 
-	if (!h)
+	if (!ops->container_cgroup)
+		return ret_set_errno(false, EINVAL);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+	conf = handler->conf;
+
+	if (lxc_list_empty(&conf->cgroup2))
+		return true;
+	cgroup_settings = &conf->cgroup2;
+
+	if (!ops->unified)
 		return false;
+	h = ops->unified;
 
 	lxc_list_for_each (iterator, cgroup_settings) {
 		__do_free char *fullpath = NULL;
@@ -2762,17 +2776,15 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
 						  cg->subsystem, NULL);
 			ret = lxc_write_to_file(fullpath, cg->value,
 						strlen(cg->value), false, 0666);
-			if (ret < 0) {
-				SYSERROR("Failed to set \"%s\" to \"%s\"",
-					 cg->subsystem, cg->value);
-				return false;
-			}
+			if (ret < 0)
+				return log_error_errno(false,
+						       errno, "Failed to set \"%s\" to \"%s\"",
+						       cg->subsystem, cg->value);
 		}
 		TRACE("Set \"%s\" to \"%s\"", cg->subsystem, cg->value);
 	}
 
-	INFO("Limits for the unified cgroup hierarchy have been setup");
-	return true;
+	return log_info(true, "Limits for the unified cgroup hierarchy have been setup");
 }
 
 __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,

From ab9a452ddbac831a6559e4988dec1c1b17fe0d1f Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:35:19 +0100
Subject: [PATCH 39/44] cgroups/cgfsng: rework cgfsng_attach()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 836b89f68d..db458c6820 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2303,6 +2303,9 @@ __cgfsng_ops static bool cgfsng_attach(struct cgroup_ops *ops, const char *name,
 	int len, ret;
 	char pidstr[INTTYPE_TO_STRLEN(pid_t)];
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	if (!ops->hierarchies)
 		return true;
 
@@ -2330,10 +2333,10 @@ __cgfsng_ops static bool cgfsng_attach(struct cgroup_ops *ops, const char *name,
 
 		fullpath = build_full_cgpath_from_monitorpath(h, path, "cgroup.procs");
 		ret = lxc_write_to_file(fullpath, pidstr, len, false, 0666);
-		if (ret < 0) {
-			SYSERROR("Failed to attach %d to %s", (int)pid, fullpath);
-			return false;
-		}
+		if (ret < 0)
+			return log_error_errno(false, errno,
+					       "Failed to attach %d to %s",
+					       (int)pid, fullpath);
 	}
 
 	return true;

From c98bbf7106469d4577f6bca8843ddc4b9e6bcb81 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:38:16 +0100
Subject: [PATCH 40/44] cgroups/cgfsng: rework cgfsng_chown()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index db458c6820..38513ca575 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1621,26 +1621,32 @@ static int chown_cgroup_wrapper(void *data)
 }
 
 __cgfsng_ops static bool cgfsng_chown(struct cgroup_ops *ops,
-					struct lxc_conf *conf)
+				      struct lxc_conf *conf)
 {
 	struct generic_userns_exec_data wrap;
 
-	if (lxc_list_empty(&conf->id_map))
-		return true;
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
 
 	if (!ops->hierarchies)
 		return true;
 
+	if (!ops->container_cgroup)
+		return ret_set_errno(false, ENOENT);
+
+	if (!conf)
+		return ret_set_errno(false, EINVAL);
+
+	if (lxc_list_empty(&conf->id_map))
+		return true;
+
 	wrap.origuid = geteuid();
 	wrap.path = NULL;
 	wrap.hierarchies = ops->hierarchies;
 	wrap.conf = conf;
 
-	if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
-			  "chown_cgroup_wrapper") < 0) {
-		ERROR("Error requesting cgroup chown in new user namespace");
-		return false;
-	}
+	if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap, "chown_cgroup_wrapper") < 0)
+		return log_error_errno(false, errno, "Error requesting cgroup chown in new user namespace");
 
 	return true;
 }

From 9585ccb3f03c7fa9c081fb07e66729ebed8016bc Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:40:29 +0100
Subject: [PATCH 41/44] cgroups/cgfsng: rework cgfsng_mount()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 38513ca575..0ce7258f0e 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1783,9 +1783,15 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops,
 	int ret;
 	bool has_cgns = false, retval = false, wants_force_mount = false;
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
 	if (!ops->hierarchies)
 		return true;
 
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+
 	if ((type & LXC_AUTO_CGROUP_MASK) == 0)
 		return true;
 
@@ -1845,10 +1851,10 @@ __cgfsng_ops static bool cgfsng_mount(struct cgroup_ops *ops,
 			continue;
 
 		ret = mkdir(controllerpath, 0755);
-		if (ret < 0) {
-			SYSERROR("Error creating cgroup path: %s", controllerpath);
-			goto on_error;
-		}
+		if (ret < 0)
+			log_error_errno(goto on_error, errno,
+					"Error creating cgroup path: %s",
+					controllerpath);
 
 		if (has_cgns && wants_force_mount) {
 			/* If cgroup namespaces are supported but the container

From 1aae36a98fa51b66f09807e1aa0bdd470ce2f8da Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:41:36 +0100
Subject: [PATCH 42/44] cgroups/cgfsng: rework cgfsng_nrtasks()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 0ce7258f0e..f6e7a9df6c 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1933,8 +1933,11 @@ __cgfsng_ops static int cgfsng_nrtasks(struct cgroup_ops *ops)
 {
 	__do_free char *path = NULL;
 
+	if (!ops)
+		return ret_set_errno(-1, ENOENT);
+
 	if (!ops->container_cgroup || !ops->hierarchies)
-		return -1;
+		return ret_set_errno(-1, EINVAL);
 
 	path = must_make_path(ops->hierarchies[0]->container_full_path, NULL);
 	return recursive_count_nrtasks(path);

From e552bd1a34a929557fe13d32fb41e7da502c96b3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 00:43:40 +0100
Subject: [PATCH 43/44] cgroups/cgfsng: cgfsng_devices_activate()

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

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index f6e7a9df6c..fd5ab0cf13 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -2810,12 +2810,26 @@ __cgfsng_ops bool cgfsng_devices_activate(struct cgroup_ops *ops,
 {
 #ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
 	__do_bpf_program_free struct bpf_program *devices = NULL;
-	struct lxc_conf *conf = handler->conf;
-	struct hierarchy *unified = ops->unified;
 	int ret;
+	struct lxc_conf *conf;
+	struct hierarchy *unified;
 	struct lxc_list *it;
 	struct bpf_program *devices_old;
 
+	if (!ops)
+		return ret_set_errno(false, ENOENT);
+
+	if (!ops->hierarchies)
+		return true;
+
+	if (!ops->container_cgroup)
+		return ret_set_errno(false, EEXIST);
+
+	if (!handler || !handler->conf)
+		return ret_set_errno(false, EINVAL);
+	conf = handler->conf;
+
+	unified = ops->unified;
 	if (!unified || !unified->bpf_device_controller ||
 	    !unified->container_full_path || lxc_list_empty(&conf->devices))
 		return true;

From c04a6d4e7f9fe980fe537b9641a3d4d430b12bd1 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 8 Dec 2019 01:17:33 +0100
Subject: [PATCH 44/44] cgroups/cgfsng: replace lxc_write_file()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/cgroups/cgfsng.c | 81 +++++++++++++++++++---------------------
 src/lxc/file_utils.c     | 33 ++++++++++++++++
 src/lxc/file_utils.h     |  4 ++
 3 files changed, 75 insertions(+), 43 deletions(-)

diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index fd5ab0cf13..01b6f57131 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -500,13 +500,11 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
 
 copy_parent:
 	if (!am_initialized) {
-		fpath = must_make_path(path, "cpuset.cpus", NULL);
-		ret = lxc_write_to_file(fpath, cpulist, strlen(cpulist), false,
-					0666);
-		if (ret < 0) {
-			SYSERROR("Failed to write cpu list to \"%s\"", fpath);
-			return false;
-		}
+		ret = lxc_write_openat(path, "cpuset.cpus", cpulist, strlen(cpulist));
+		if (ret < 0)
+			return log_error_errno(false,
+					       errno, "Failed to write cpu list to \"%s/cpuset.cpus\"",
+					       path);
 
 		TRACE("Copied cpu settings of parent cgroup");
 	}
@@ -517,7 +515,7 @@ static bool cg_legacy_filter_and_set_cpus(char *path, bool am_initialized)
 /* Copy contents of parent(@path)/@file to @path/@file */
 static bool copy_parent_file(char *path, char *file)
 {
-	__do_free char *child_path = NULL, *parent_path = NULL, *value = NULL;
+	__do_free char *parent_path = NULL, *value = NULL;
 	int ret;
 	char oldv;
 	int len = 0;
@@ -545,13 +543,17 @@ static bool copy_parent_file(char *path, char *file)
 	}
 
 	*lastslash = oldv;
-	child_path = must_make_path(path, file, NULL);
-	ret = lxc_write_to_file(child_path, value, len, false, 0666);
+	ret = lxc_write_openat(path, file, value, len);
 	if (ret < 0)
-		SYSERROR("Failed to write \"%s\" to file \"%s\"", value, child_path);
+		SYSERROR("Failed to write \"%s\" to file \"%s/%s\"", value, path, file);
 	return ret >= 0;
 }
 
+static bool is_unified_hierarchy(const struct hierarchy *h)
+{
+	return h->version == CGROUP2_SUPER_MAGIC;
+}
+
 /* Initialize the cpuset hierarchy in first directory of @gname and set
  * cgroup.clone_children so that children inherit settings. Since the
  * h->base_path is populated by init or ourselves, we know it is already
@@ -559,11 +561,15 @@ static bool copy_parent_file(char *path, char *file)
  */
 static bool cg_legacy_handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 {
-	__do_free char *cgpath = NULL, *clonechildrenpath = NULL;
+	__do_free char *cgpath = NULL;
+	__do_close_prot_errno int cgroup_fd = -EBADF;
 	int ret;
 	char v;
 	char *slash;
 
+	if (is_unified_hierarchy(h))
+		return true;
+
 	if (!string_in_list(h->controllers, "cpuset"))
 		return true;
 
@@ -585,14 +591,13 @@ static bool cg_legacy_handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 		}
 	}
 
-	clonechildrenpath = must_make_path(cgpath, "cgroup.clone_children", NULL);
-	/* unified hierarchy doesn't have clone_children */
-	if (!file_exists(clonechildrenpath))
-		return true;
+	cgroup_fd = lxc_open_dirfd(cgpath);
+	if (cgroup_fd < 0)
+		return false;
 
-	ret = lxc_read_from_file(clonechildrenpath, &v, 1);
+	ret = lxc_readat(cgroup_fd, "cgroup.clone_children", &v, 1);
 	if (ret < 0) {
-		SYSERROR("Failed to read file \"%s\"", clonechildrenpath);
+		SYSERROR("Failed to read file \"%s/cgroup.clone_children\"", cgpath);
 		return false;
 	}
 
@@ -612,10 +617,10 @@ static bool cg_legacy_handle_cpuset_hierarchy(struct hierarchy *h, char *cgname)
 		return false;
 	}
 
-	ret = lxc_write_to_file(clonechildrenpath, "1", 1, false, 0666);
+	ret = lxc_writeat(cgroup_fd, "cgroup.clone_children", "1", 1);
 	if (ret < 0) {
 		/* Set clone_children so children inherit our settings */
-		SYSERROR("Failed to write 1 to \"%s\"", clonechildrenpath);
+		SYSERROR("Failed to write 1 to \"%s/cgroup.clone_children\"", cgpath);
 		return false;
 	}
 
@@ -2016,15 +2021,14 @@ __cgfsng_ops static bool cgfsng_get_hierarchies(struct cgroup_ops *ops, int n,
 
 static bool cg_legacy_freeze(struct cgroup_ops *ops)
 {
-	__do_free char *path = NULL;
 	struct hierarchy *h;
 
 	h = get_hierarchy(ops, "freezer");
 	if (!h)
 		return ret_set_errno(-1, ENOENT);
 
-	path = must_make_path(h->container_full_path, "freezer.state", NULL);
-	return lxc_write_to_file(path, "FROZEN", STRLITERALLEN("FROZEN"), false, 0666);
+	return lxc_write_openat(h->container_full_path, "freezer.state",
+				"FROZEN", STRLITERALLEN("FROZEN"));
 }
 
 static int freezer_cgroup_events_cb(int fd, uint32_t events, void *cbdata,
@@ -2064,7 +2068,6 @@ static int freezer_cgroup_events_cb(int fd, uint32_t events, void *cbdata,
 static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 {
 	__do_close_prot_errno int fd = -EBADF;
-	__do_free char *path = NULL;
 	__do_lxc_mainloop_close struct lxc_epoll_descr *descr_ptr = NULL;
 	int ret;
 	struct lxc_epoll_descr descr;
@@ -2097,8 +2100,7 @@ static int cg_unified_freeze(struct cgroup_ops *ops, int timeout)
 			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}
 
-	path = must_make_path(h->container_full_path, "cgroup.freeze", NULL);
-	ret = lxc_write_to_file(path, "1", 1, false, 0666);
+	ret = lxc_write_openat(h->container_full_path, "cgroup.freeze", "1", 1);
 	if (ret < 0)
 		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
 
@@ -2121,21 +2123,19 @@ __cgfsng_ops static int cgfsng_freeze(struct cgroup_ops *ops, int timeout)
 
 static int cg_legacy_unfreeze(struct cgroup_ops *ops)
 {
-	__do_free char *path = NULL;
 	struct hierarchy *h;
 
 	h = get_hierarchy(ops, "freezer");
 	if (!h)
 		return ret_set_errno(-1, ENOENT);
 
-	path = must_make_path(h->container_full_path, "freezer.state", NULL);
-	return lxc_write_to_file(path, "THAWED", STRLITERALLEN("THAWED"), false, 0666);
+	return lxc_write_openat(h->container_full_path, "freezer.state",
+				"THAWED", STRLITERALLEN("THAWED"));
 }
 
 static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 {
 	__do_close_prot_errno int fd = -EBADF;
-	__do_free char *path = NULL;
 	__do_lxc_mainloop_close struct lxc_epoll_descr *descr_ptr = NULL;
 	int ret;
 	struct lxc_epoll_descr descr;
@@ -2168,8 +2168,7 @@ static int cg_unified_unfreeze(struct cgroup_ops *ops, int timeout)
 			return log_error_errno(-1, errno, "Failed to add cgroup.events fd handler to mainloop");
 	}
 
-	path = must_make_path(h->container_full_path, "cgroup.freeze", NULL);
-	ret = lxc_write_to_file(path, "0", 1, false, 0666);
+	ret = lxc_write_openat(h->container_full_path, "cgroup.freeze", "0", 1);
 	if (ret < 0)
 		return log_error_errno(-1, errno, "Failed to open cgroup.freeze file");
 
@@ -2638,12 +2637,10 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename,
 			      const char *value)
 {
 	__do_free char *controller = NULL;
-	__do_free char *fullpath = NULL;
 	char *p;
 	/* "b|c <2^64-1>:<2^64-1> r|w|m" = 47 chars max */
 	char converted_value[50];
 	struct hierarchy *h;
-	int ret = 0;
 
 	controller = must_copy_string(filename);
 	p = strchr(controller, '.');
@@ -2651,6 +2648,8 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename,
 		*p = '\0';
 
 	if (strcmp("devices.allow", filename) == 0 && value[0] == '/') {
+		int ret;
+
 		ret = convert_devpath(value, converted_value);
 		if (ret < 0)
 			return ret;
@@ -2667,9 +2666,7 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename,
 		return -ENOENT;
 	}
 
-	fullpath = must_make_path(h->container_full_path, filename, NULL);
-	ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666);
-	return ret;
+	return lxc_write_openat(h->container_full_path, filename, value, strlen(value));
 }
 
 __cgfsng_ops static bool cgfsng_setup_limits_legacy(struct cgroup_ops *ops,
@@ -2782,18 +2779,16 @@ __cgfsng_ops static bool cgfsng_setup_limits(struct cgroup_ops *ops,
 	h = ops->unified;
 
 	lxc_list_for_each (iterator, cgroup_settings) {
-		__do_free char *fullpath = NULL;
-		int ret;
 		struct lxc_cgroup *cg = iterator->elem;
+		int ret;
 
 		if (strncmp("devices", cg->subsystem, 7) == 0) {
 			ret = bpf_device_cgroup_prepare(ops, conf, cg->subsystem,
 							cg->value);
 		} else {
-			fullpath = must_make_path(h->container_full_path,
-						  cg->subsystem, NULL);
-			ret = lxc_write_to_file(fullpath, cg->value,
-						strlen(cg->value), false, 0666);
+			ret = lxc_write_openat(h->container_full_path,
+					       cg->subsystem, cg->value,
+					       strlen(cg->value));
 			if (ret < 0)
 				return log_error_errno(false,
 						       errno, "Failed to set \"%s\" to \"%s\"",
diff --git a/src/lxc/file_utils.c b/src/lxc/file_utils.c
index cd1b732a3a..cb7e9c84f9 100644
--- a/src/lxc/file_utils.c
+++ b/src/lxc/file_utils.c
@@ -18,6 +18,27 @@
 #include "string_utils.h"
 #include "utils.h"
 
+int lxc_open_dirfd(const char *dir)
+{
+	return open(dir, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+}
+
+int lxc_readat(int dirfd, const char *filename, void *buf, size_t count)
+{
+	__do_close_prot_errno int fd = -EBADF;
+	ssize_t ret;
+
+	fd = openat(dirfd, filename, O_RDONLY | O_CLOEXEC);
+	if (fd < 0)
+		return -1;
+
+	ret = lxc_read_nointr(fd, buf, count);
+	if (ret < 0 || (size_t)ret != count)
+		return -1;
+
+	return 0;
+}
+
 int lxc_writeat(int dirfd, const char *filename, const void *buf, size_t count)
 {
 	__do_close_prot_errno int fd = -EBADF;
@@ -34,6 +55,18 @@ int lxc_writeat(int dirfd, const char *filename, const void *buf, size_t count)
 	return 0;
 }
 
+int lxc_write_openat(const char *dir, const char *filename, const void *buf,
+		     size_t count)
+{
+	__do_close_prot_errno int dirfd = -EBADF;
+
+	dirfd = open(dir, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
+	if (dirfd < 0)
+		return -1;
+
+	return lxc_writeat(dirfd, filename, buf, count);
+}
+
 int lxc_write_to_file(const char *filename, const void *buf, size_t count,
 		      bool add_newline, mode_t mode)
 {
diff --git a/src/lxc/file_utils.h b/src/lxc/file_utils.h
index d277005328..9faf41d36d 100644
--- a/src/lxc/file_utils.h
+++ b/src/lxc/file_utils.h
@@ -15,8 +15,11 @@
 /* read and write whole files */
 extern int lxc_write_to_file(const char *filename, const void *buf,
 			     size_t count, bool add_newline, mode_t mode);
+extern int lxc_readat(int dirfd, const char *filename, void *buf, size_t count);
 extern int lxc_writeat(int dirfd, const char *filename, const void *buf,
 		       size_t count);
+extern int lxc_write_openat(const char *dir, const char *filename,
+			    const void *buf, size_t count);
 extern int lxc_read_from_file(const char *filename, void *buf, size_t count);
 
 /* send and receive buffers completely */
@@ -47,5 +50,6 @@ 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);
+extern int lxc_open_dirfd(const char *dir);
 
 #endif /* __LXC_FILE_UTILS_H */


More information about the lxc-devel mailing list