From ad6eaa28811f96ebc39b5723cc37abb144ae82e6 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 25 Feb 2020 12:17:29 +0100 Subject: netns: Improve error checking Change-Id: I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708 --- lib/netns.c | 142 +++++++++++++++++++++++++++++++++--------------------- lib/netns.h | 4 +- sgsnemu/sgsnemu.c | 51 ++++++++++++++++---- 3 files changed, 132 insertions(+), 65 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); diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index 2c0ce1b..fce5059 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -1323,19 +1323,29 @@ static int create_ping(void *gsn, struct pdp_t *pdp, static int delete_context(struct pdp_t *pdp) { + int rc; + if (tun && options.ipdown) { #if defined(__linux__) sigset_t oldmask; if ((options.netns)) { - switch_ns(netns, &oldmask); + if ((rc = switch_ns(netns, &oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, + "Failed to switch to netns %s: %s\n", + options.netns, strerror(-rc)); + } } #endif tun_runscript(tun, options.ipdown); #if defined(__linux__) if ((options.netns)) { - restore_ns(&oldmask); + if ((rc = restore_ns(&oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, + "Failed to switch to original netns: %s\n", + strerror(-rc)); + } } #endif } @@ -1399,6 +1409,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) { + int rc; struct in46_addr addr; #if defined(__linux__) sigset_t oldmask; @@ -1458,7 +1469,11 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) #if defined(__linux__) if ((options.createif) && (options.netns)) { - switch_ns(netns, &oldmask); + if ((rc = switch_ns(netns, &oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, + "Failed to switch to netns %s: %s\n", + options.netns, strerror(-rc)); + } } #endif @@ -1504,7 +1519,10 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) #if defined(__linux__) if ((options.createif) && (options.netns)) { - restore_ns(&oldmask); + if ((rc = restore_ns(&oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to original netns: %s\n", + strerror(-rc)); + } } #endif @@ -1572,7 +1590,7 @@ int main(int argc, char **argv) fd_set fds; /* For select() */ struct timeval idleTime; /* How long to select() */ struct pdp_t *pdp; - int n; + int n, rc; int starttime = time(NULL); /* Time program was started */ int stoptime = 0; /* Time to exit */ int pingtimeout = 0; /* Time to print ping statistics */ @@ -1594,7 +1612,10 @@ int main(int argc, char **argv) osmo_init_logging2(tall_sgsnemu_ctx, &log_info); #if defined(__linux__) - init_netns(); + if ((rc = init_netns()) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to initialize netns: %s", strerror(-rc)); + exit(1); + } #endif /* Process options given in configuration file and command line */ @@ -1622,8 +1643,16 @@ int main(int argc, char **argv) #if defined(__linux__) if ((options.createif) && (options.netns)) { - netns = get_nsfd(options.netns); - switch_ns(netns, &oldmask); + if ((netns = get_nsfd(options.netns)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to obtain fd for netns %s: %s\n", + options.netns, strerror(-netns)); + exit(1); + } + if ((rc = switch_ns(netns, &oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to netns %s: %s\n", + options.netns, strerror(-rc)); + exit(1); + } } #endif @@ -1654,7 +1683,11 @@ int main(int argc, char **argv) #if defined(__linux__) if ((options.createif) && (options.netns)) { - restore_ns(&oldmask); + if ((rc = restore_ns(&oldmask)) < 0) { + SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed to switch to original netns: %s\n", + strerror(-rc)); + exit(1); + } } #endif -- cgit v1.2.3