Implement defer()
authorRobert Swiecki <swiecki@google.com>
Tue, 8 Mar 2016 17:22:50 +0000 (18:22 +0100)
committerRobert Swiecki <swiecki@google.com>
Tue, 8 Mar 2016 17:22:50 +0000 (18:22 +0100)
Makefile
common.h
net.c

index c225118b5cb7dbcc9488287b402df38bf25d9f12..9236c644a2cd9de6784ef49e04ae006a50a44463 100644 (file)
--- a/Makefile
+++ b/Makefile
 #
 
 CC ?= gcc
-CFLAGS += -O2 -g -ggdb -c -std=c11 \
+
+CFLAGS += -O2 -g -ggdb -c -std=gnu11 \
        -D_GNU_SOURCE \
-       -fstack-protector-all -Wformat -Wformat=2 -Wformat-security -fPIE -Wa,--noexecstack \
+       -fstack-protector-all -Wformat -Wformat=2 -Wformat-security -fPIE \
        -Wall -Wextra -Werror
 
-LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie
+LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -Wa,--noexecstack
+
+COMPILER_CLANG = $(shell $(CC) -v 2>&1 | grep version | head -n1 | egrep -o clang)
+ifeq ($(COMPILER_CLANG),clang)
+       CFLAGS += -fblocks
+       LDFLAGS += -lBlocksRuntime
+endif
 
 SRCS = nsjail.c cmdline.c contain.c log.c net.c mount.c user.c subproc.c sandbox.c util.c uts.c seccomp/bpf-helper.c
 OBJS = $(SRCS:.c=.o)
index 0f3eb88e59350a5077df1a9b2aa65180fa14539b..ca9534202eeba40bfd6b6a903120458d5778729e 100644 (file)
--- a/common.h
+++ b/common.h
 
 #define ARRAYSIZE(array) (sizeof(array) / sizeof(*array))
 
+#define _STRMERGE(a, b) a##b
+
+#ifdef __clang__
+  static void __attribute__((unused)) _clang_cleanup_func(void (^*dfunc)(void)) { (*dfunc)(); }
+  #define defer(a) void (^_STRMERGE(__df_, __COUNTER__))(void) __attribute__((cleanup(_clang_cleanup_func))) __attribute__((unused)) = ^{ a; }
+#else
+  #define __block
+  #define defer(a) void _STRMERGE(_cleanup_func_, __LINE__)(void *_STRMERGE(_cleanup_unused_, __LINE__) __attribute__((unused))) { a; } ; int _STRMERGE(_cleanup_var_, __LINE__) __attribute__((cleanup(_STRMERGE(_cleanup_func_, __LINE__)))) __attribute__((unused))
+#endif
+
+
 struct pids_t {
        pid_t pid;
        time_t start;
diff --git a/net.c b/net.c
index 2719f2e2e9115cd9d3ba4e8994933e6a7d00299e..a41a4c6fc104375343326a20392260f6a7b14e27 100644 (file)
--- a/net.c
+++ b/net.c
@@ -322,11 +322,12 @@ void netConnToText(int fd, bool remote, char *buf, size_t s, struct sockaddr_in6
 
 static bool netIfaceUp(const char *ifacename)
 {
-       int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+       __block int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
        if (sock == -1) {
                PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
                return false;
        }
+        defer(close(sock));
 
        struct ifreq ifr;
        memset(&ifr, '\0', sizeof(ifr));
@@ -334,7 +335,6 @@ static bool netIfaceUp(const char *ifacename)
 
        if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
                PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
-               close(sock);
                return false;
        }
 
@@ -342,11 +342,9 @@ static bool netIfaceUp(const char *ifacename)
 
        if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
                PLOG_E("ioctl(iface='%s', SIOCSIFFLAGS, IFF_UP)", ifacename);
-               close(sock);
                return false;
        }
 
-       close(sock);
        return true;
 }
 
@@ -357,21 +355,19 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
        snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", IFACE_NAME);
        struct in_addr addr;
 
-       int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+       __block int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
        if (sock == -1) {
                PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
-               close(sock);
                return false;
        }
+       defer(close(sock));
 
        if (inet_pton(AF_INET, nsjconf->iface_vs_ip, &addr) != 1) {
                PLOG_E("Cannot convert '%s' into an IPv4 address", nsjconf->iface_vs_ip);
-               close(sock);
                return false;
        }
        if (addr.s_addr == INADDR_ANY) {
                LOG_I("IPv4 address for interface '%s' not set", IFACE_NAME);
-               close(sock);
                return true;
        }
 
@@ -380,20 +376,17 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
        sa->sin_addr = addr;
        if (ioctl(sock, SIOCSIFADDR, &ifr) == -1) {
                PLOG_E("ioctl(iface='%s', SIOCSIFADDR, '%s')", IFACE_NAME, nsjconf->iface_vs_ip);
-               close(sock);
                return false;
        }
 
        if (inet_pton(AF_INET, nsjconf->iface_vs_nm, &addr) != 1) {
                PLOG_E("Cannot convert '%s' into a IPv4 netmask", nsjconf->iface_vs_nm);
-               close(sock);
                return false;
        }
        sa->sin_family = AF_INET;
        sa->sin_addr = addr;
        if (ioctl(sock, SIOCSIFNETMASK, &ifr) == -1) {
                PLOG_E("ioctl(iface='%s', SIOCSIFNETMASK, '%s')", IFACE_NAME, nsjconf->iface_vs_nm);
-               close(sock);
                return false;
        }
 
@@ -403,12 +396,10 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
 
        if (inet_pton(AF_INET, nsjconf->iface_vs_gw, &addr) != 1) {
                PLOG_E("Cannot convert '%s' into a IPv4 GW address", nsjconf->iface_vs_gw);
-               close(sock);
                return false;
        }
        if (addr.s_addr == INADDR_ANY) {
                LOG_I("Gateway address for '%s' is not set", IFACE_NAME);
-               close(sock);
                return true;
        }
 
@@ -430,11 +421,9 @@ static bool netConfigureVs(struct nsjconf_t *nsjconf)
 
        if (ioctl(sock, SIOCADDRT, &rt) == -1) {
                PLOG_E("ioctl(SIOCADDRT, '%s')", nsjconf->iface_vs_gw);
-               close(sock);
                return false;
        }
 
-       close(sock);
        return true;
 }