diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2020-02-25 12:17:29 +0100 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2020-03-02 09:41:43 +0100 |
commit | ad6eaa28811f96ebc39b5723cc37abb144ae82e6 (patch) | |
tree | 713694b49877d045cd9110e9294bd420d9a82578 /lib | |
parent | b629240a352c4455e410c32aec1d67a00e2995db (diff) |
netns: Improve error checking
Change-Id: I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708
Diffstat (limited to 'lib')
-rw-r--r-- | lib/netns.c | 142 | ||||
-rw-r--r-- | lib/netns.h | 4 |
2 files changed, 90 insertions, 56 deletions
diff --git a/lib/netns.c b/lib/netns.c index 6734b5d..bd2076b 100644 --- a/lib/netns.c +++ b/lib/netns.c @@ -49,99 +49,133 @@ static int default_nsfd; int switch_ns(int nsfd, sigset_t *oldmask) { sigset_t intmask; + int rc; - sigfillset(&intmask); - sigprocmask(SIG_BLOCK, &intmask, oldmask); + if (sigfillset(&intmask) < 0) + return -errno; + if ((rc = sigprocmask(SIG_BLOCK, &intmask, oldmask)) != 0) + return -rc; - return setns(nsfd, CLONE_NEWNET); + if (setns(nsfd, CLONE_NEWNET) < 0) + return -errno; + return 0; } -void restore_ns(sigset_t *oldmask) +int restore_ns(sigset_t *oldmask) { - setns(default_nsfd, CLONE_NEWNET); + int rc; + if (setns(default_nsfd, CLONE_NEWNET) < 0) + return -errno; - sigprocmask(SIG_SETMASK, oldmask, NULL); + if ((rc = sigprocmask(SIG_SETMASK, oldmask, NULL)) != 0) + return -rc; + return 0; } int open_ns(int nsfd, const char *pathname, int flags) { sigset_t intmask, oldmask; int fd; - int errsv; - - sigfillset(&intmask); - sigprocmask(SIG_BLOCK, &intmask, &oldmask); - - setns(nsfd, CLONE_NEWNET); - fd = open(pathname, flags); - errsv = errno; - setns(default_nsfd, CLONE_NEWNET); - - sigprocmask(SIG_SETMASK, &oldmask, NULL); + int rc; + + if (sigfillset(&intmask) < 0) + return -errno; + if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0) + return -rc; + + if (setns(nsfd, CLONE_NEWNET) < 0) + return -errno; + if ((fd = open(pathname, flags)) < 0) + return -errno; + if (setns(default_nsfd, CLONE_NEWNET) < 0) { + close(fd); + return -errno; + } + if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) { + close(fd); + return -rc; + } - errno = errsv; - return fd; + return 0; } int socket_ns(int nsfd, int domain, int type, int protocol) { sigset_t intmask, oldmask; int sk; - int errsv; - - sigfillset(&intmask); - sigprocmask(SIG_BLOCK, &intmask, &oldmask); - - setns(nsfd, CLONE_NEWNET); - sk = socket(domain, type, protocol); - errsv = errno; - setns(default_nsfd, CLONE_NEWNET); - - sigprocmask(SIG_SETMASK, &oldmask, NULL); + int rc; + + if (sigfillset(&intmask) < 0) + return -errno; + if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0) + return -rc; + + if (setns(nsfd, CLONE_NEWNET) < 0) + return -errno; + if ((sk = socket(domain, type, protocol)) < 0) + return -errno; + if (setns(default_nsfd, CLONE_NEWNET) < 0) { + close(sk); + return -errno; + } - errno = errsv; + if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) { + close(sk); + return -rc; + } return sk; } -void init_netns() +int init_netns() { - if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0) { - perror("init_netns"); - exit(EXIT_FAILURE); - } + if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0) + return -errno; + return 0; } int get_nsfd(const char *name) { - int r; + int rc; + int fd; sigset_t intmask, oldmask; char path[MAXPATHLEN] = NETNS_PATH; - r = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); - if (r < 0 && errno != EEXIST) - return r; + rc = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); + if (rc < 0 && errno != EEXIST) + return rc; snprintf(path, sizeof(path), "%s/%s", NETNS_PATH, name); - r = open(path, O_RDONLY|O_CREAT|O_EXCL, 0); - if (r < 0) { - if (errno == EEXIST) - return open(path, O_RDONLY); - - return r; + fd = open(path, O_RDONLY|O_CREAT|O_EXCL, 0); + if (fd < 0) { + if (errno == EEXIST) { + if ((fd = open(path, O_RDONLY)) < 0) + return -errno; + return fd; + } + return -errno; } - close(r); + if (close(fd) < 0) + return -errno; - sigfillset(&intmask); - sigprocmask(SIG_BLOCK, &intmask, &oldmask); + if (sigfillset(&intmask) < 0) + return -errno; + if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0) + return -rc; - unshare(CLONE_NEWNET); - mount("/proc/self/ns/net", path, "none", MS_BIND, NULL); + if (unshare(CLONE_NEWNET) < 0) + return -errno; + if (mount("/proc/self/ns/net", path, "none", MS_BIND, NULL) < 0) + return -errno; - setns(default_nsfd, CLONE_NEWNET); + if (setns(default_nsfd, CLONE_NEWNET) < 0) + return -errno; - sigprocmask(SIG_SETMASK, &oldmask, NULL); + if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) + return -rc; - return open(path, O_RDONLY); + if ((fd = open(path, O_RDONLY)) < 0) + return -errno; + return fd; } #endif diff --git a/lib/netns.h b/lib/netns.h index 168e44f..3b91ba3 100644 --- a/lib/netns.h +++ b/lib/netns.h @@ -21,10 +21,10 @@ #if defined(__linux__) -void init_netns(void); +int init_netns(void); int switch_ns(int nsfd, sigset_t *oldmask); -void restore_ns(sigset_t *oldmask); +int restore_ns(sigset_t *oldmask); int open_ns(int nsfd, const char *pathname, int flags); int socket_ns(int nsfd, int domain, int type, int protocol); |