Change in osmo-ggsn[master]: netns: Improve error checking

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Mon Mar 2 13:32:24 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ggsn/+/17254 )

Change subject: netns: Improve error checking
......................................................................

netns: Improve error checking

Change-Id: I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708
---
M lib/netns.c
M lib/netns.h
M sgsnemu/sgsnemu.c
3 files changed, 128 insertions(+), 61 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



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 @@
 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;
+	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;
 
-	setns(nsfd, CLONE_NEWNET);
-	fd = open(pathname, flags);
-	errsv = errno;
-	setns(default_nsfd, CLONE_NEWNET);
+	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;
+	}
 
-	sigprocmask(SIG_SETMASK, &oldmask, NULL);
-
-	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;
+	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;
 
-	setns(nsfd, CLONE_NEWNET);
-	sk = socket(domain, type, protocol);
-	errsv = errno;
-	setns(default_nsfd, CLONE_NEWNET);
+	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;
+	}
 
-	sigprocmask(SIG_SETMASK, &oldmask, NULL);
-
-	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 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 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 @@
 
 #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 @@
 
 #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 @@
 	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 @@
 	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 @@
 
 #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 @@
 
 #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
 

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ggsn/+/17254
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708
Gerrit-Change-Number: 17254
Gerrit-PatchSet: 3
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200302/84591ee1/attachment.htm>


More information about the gerrit-log mailing list