lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 30 Jun 2019 21:29:33 +0200
From:   Matteo Croce <mcroce@...hat.com>
To:     netdev@...r.kernel.org
Cc:     Alexander Aring <aring@...atatu.com>,
        Nicolas Dichtel <nicolas.dichtel@...nd.com>
Subject: [RFC iproute2] netns: add mounting state file for each netns

When ip creates a netns, there is a small time interval between the
placeholder file creation in NETNS_RUN_DIR and the bind mount from /proc.

Add a temporary file named .mounting-$netns which gets deleted after the
bind mount, so watching for delete event matching the .mounting-* name
will notify watchers only after the bind mount has been done.

Signed-off-by: Matteo Croce <mcroce@...hat.com>
---
 ip/ipnetns.c | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index a883f210..23b95173 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -24,6 +24,8 @@
 #include "namespace.h"
 #include "json_print.h"
 
+#define TMP_PREFIX ".mounting-"
+
 static int usage(void)
 {
 	fprintf(stderr,
@@ -47,6 +49,10 @@ static struct rtnl_handle rtnsh = { .fd = -1 };
 static int have_rtnl_getnsid = -1;
 static int saved_netns = -1;
 
+static int is_mounting_stab(const char *name) {
+	return !strncmp(name, TMP_PREFIX, sizeof(TMP_PREFIX) - 1);
+}
+
 static int ipnetns_accept_msg(struct rtnl_ctrl_data *ctrl,
 			      struct nlmsghdr *n, void *arg)
 {
@@ -379,6 +385,8 @@ static int netns_list(int argc, char **argv)
 			continue;
 		if (strcmp(entry->d_name, "..") == 0)
 			continue;
+		if (is_mounting_stab(entry->d_name))
+			continue;
 
 		open_json_object(NULL);
 		print_string(PRINT_ANY, "name",
@@ -676,7 +684,7 @@ static int netns_add(int argc, char **argv, bool create)
 	 * userspace tweaks like remounting /sys, or bind mounting
 	 * a new /etc/resolv.conf can be shared between users.
 	 */
-	char netns_path[PATH_MAX], proc_path[PATH_MAX];
+	char netns_path[PATH_MAX], tmp_path[PATH_MAX], proc_path[PATH_MAX];
 	const char *name;
 	pid_t pid;
 	int fd;
@@ -701,6 +709,7 @@ static int netns_add(int argc, char **argv, bool create)
 	name = argv[0];
 
 	snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
+	snprintf(tmp_path, sizeof(tmp_path), "%s/"TMP_PREFIX"%s", NETNS_RUN_DIR, name);
 
 	if (create_netns_dir())
 		return -1;
@@ -737,6 +746,14 @@ static int netns_add(int argc, char **argv, bool create)
 	}
 	close(fd);
 
+	fd = open(tmp_path, O_RDONLY|O_CREAT|O_EXCL, 0);
+	if (fd < 0) {
+		fprintf(stderr, "Cannot create namespace file \"%s\": %s\n",
+			tmp_path, strerror(errno));
+		goto out_delete;
+	}
+	close(fd);
+
 	if (create) {
 		netns_save();
 		if (unshare(CLONE_NEWNET) < 0) {
@@ -757,6 +774,7 @@ static int netns_add(int argc, char **argv, bool create)
 		goto out_delete;
 	}
 	netns_restore();
+	unlink(tmp_path);
 
 	return 0;
 out_delete:
@@ -767,6 +785,10 @@ out_delete:
 		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
 			netns_path, strerror(errno));
 	}
+	if (unlink(tmp_path) < 0) {
+		fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
+			tmp_path, strerror(errno));
+	}
 	return -1;
 }
 
@@ -849,7 +871,7 @@ static int netns_monitor(int argc, char **argv)
 	if (create_netns_dir())
 		return -1;
 
-	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) {
+	if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_DELETE) < 0) {
 		fprintf(stderr, "inotify_add_watch failed: %s\n",
 			strerror(errno));
 		return -1;
@@ -865,9 +887,9 @@ static int netns_monitor(int argc, char **argv)
 		for (event = (struct inotify_event *)buf;
 		     (char *)event < &buf[len];
 		     event = (struct inotify_event *)((char *)event + sizeof(*event) + event->len)) {
-			if (event->mask & IN_CREATE)
-				printf("add %s\n", event->name);
-			if (event->mask & IN_DELETE)
+			if (is_mounting_stab(event->name))
+				printf("add %s\n", event->name + sizeof(TMP_PREFIX) - 1);
+			else
 				printf("delete %s\n", event->name);
 		}
 	}
@@ -876,8 +898,9 @@ static int netns_monitor(int argc, char **argv)
 
 static int invalid_name(const char *name)
 {
-	return !*name || strlen(name) > NAME_MAX ||
-		strchr(name, '/') || !strcmp(name, ".") || !strcmp(name, "..");
+	return !*name || strlen(name) + sizeof(TMP_PREFIX) - 1 > NAME_MAX ||
+		strchr(name, '/') || !strcmp(name, ".") || !strcmp(name, "..") ||
+		is_mounting_stab(name);
 }
 
 int do_netns(int argc, char **argv)
-- 
2.21.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ