[lxc-devel] [lxc/master] improve detect_ramfs_rootfs() and add test

brauner on Github lxc-bot at linuxcontainers.org
Tue Sep 6 12:54:09 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160906/48bc9017/attachment.bin>
-------------- next part --------------
From 65ae2cf8388ed12e0b93357db02eb113c556da5c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 13:49:13 +0200
Subject: [PATCH 1/2] utils: make detect_ramfs_rootfs() return bool

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/lxc/utils.c | 28 ++++++++++++++++------------
 src/lxc/utils.h |  2 +-
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 27362da..e56a7e0 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1108,36 +1108,40 @@ bool switch_to_ns(pid_t pid, const char *ns) {
  * IIUC, so long as we've chrooted so that rootfs is not our root,
  * the rootfs entry should always be skipped in mountinfo contents.
  */
-int detect_ramfs_rootfs(void)
+bool detect_ramfs_rootfs(void)
 {
-	char buf[LINELEN], *p;
 	FILE *f;
+	char *p, *p2;
+	char *line = NULL;
+	size_t len = 0;
 	int i;
-	char *p2;
 
 	f = fopen("/proc/self/mountinfo", "r");
 	if (!f)
-		return 0;
-	while (fgets(buf, LINELEN, f)) {
-		for (p = buf, i=0; p && i < 4; i++)
-			p = strchr(p+1, ' ');
+		return false;
+
+	while (getline(&line, &len, f) != -1) {
+		for (p = line, i = 0; p && i < 4; i++)
+			p = strchr(p + 1, ' ');
 		if (!p)
 			continue;
-		p2 = strchr(p+1, ' ');
+		p2 = strchr(p + 1, ' ');
 		if (!p2)
 			continue;
 		*p2 = '\0';
-		if (strcmp(p+1, "/") == 0) {
+		if (strcmp(p + 1, "/") == 0) {
 			// this is '/'.  is it the ramfs?
-			p = strchr(p2+1, '-');
+			p = strchr(p2 + 1, '-');
 			if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) {
+				free(line);
 				fclose(f);
-				return 1;
+				return true;
 			}
 		}
 	}
+	free(line);
 	fclose(f);
-	return 0;
+	return false;
 }
 
 char *on_path(char *cmd, const char *rootfs) {
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 98b4e13..84b9d55 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -291,7 +291,7 @@ extern bool dir_exists(const char *path);
 uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
 
 int detect_shared_rootfs(void);
-int detect_ramfs_rootfs(void);
+bool detect_ramfs_rootfs(void);
 char *on_path(char *cmd, const char *rootfs);
 bool file_exists(const char *f);
 bool cgns_supported(void);

From f7e61003cdf1376dd0a3d1cc2fb3e8599920b9ee Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at canonical.com>
Date: Tue, 6 Sep 2016 14:51:01 +0200
Subject: [PATCH 2/2] tests: add test for detect_ramfs_rootfs()

Signed-off-by: Christian Brauner <christian.brauner at canonical.com>
---
 src/tests/lxc-test-utils.c | 118 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c
index 4c1c373..46d72ff 100644
--- a/src/tests/lxc-test-utils.c
+++ b/src/tests/lxc-test-utils.c
@@ -21,13 +21,131 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include "lxctest.h"
 #include "utils.h"
 
+void test_detect_ramfs_rootfs(void)
+{
+	size_t i;
+	int ret;
+	int fret = EXIT_FAILURE;
+	size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 7 /* /ns/mnt */ + 1 /* \0 */;
+	char path[len];
+	int init_ns = -1;
+	char tmpf[] = "/tmp/tmpf_XXXXXX";
+	int fd = -1;
+	FILE *fp = NULL;
+	char *mountinfo[] = {
+		"18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw",
+		"19 24 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:13 - proc proc rw",
+		"20 24 0:6 / /dev rw,nosuid,relatime shared:2 - devtmpfs udev rw,size=4019884k,nr_inodes=1004971,mode=755",
+		"21 20 0:14 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000",
+		"22 24 0:18 / /run rw,nosuid,noexec,relatime shared:5 - tmpfs tmpfs rw,size=807912k,mode=755",
+
+		/* This is what we care about. */
+		"24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099",
+
+		"25 18 0:12 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw",
+		"26 20 0:20 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw",
+		"27 22 0:21 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k",
+		"28 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755",
+		"29 28 0:23 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd",
+		"30 18 0:24 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:11 - pstore pstore rw",
+		"31 18 0:25 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:12 - efivarfs efivarfs rw",
+		"32 28 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,cpu,cpuacct",
+		"33 28 0:27 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,net_cls,net_prio",
+		"34 28 0:28 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,blkio",
+		"35 28 0:29 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,freezer",
+		"36 28 0:30 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,memory",
+		"37 28 0:31 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb",
+		"38 28 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,cpuset",
+		"39 28 0:33 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,devices",
+		"40 28 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,pids",
+		"41 28 0:35 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,perf_event",
+		"42 19 0:36 / /proc/sys/fs/binfmt_misc rw,relatime shared:24 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct",
+		"43 18 0:7 / /sys/kernel/debug rw,relatime shared:25 - debugfs debugfs rw",
+		"44 20 0:37 / /dev/hugepages rw,relatime shared:26 - hugetlbfs hugetlbfs rw",
+		"45 20 0:16 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw",
+		"46 43 0:9 / /sys/kernel/debug/tracing rw,relatime shared:28 - tracefs tracefs rw",
+		"76 18 0:38 / /sys/fs/fuse/connections rw,relatime shared:29 - fusectl fusectl rw",
+		"78 24 8:1 / /boot/efi rw,relatime shared:30 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro",
+	};
+
+	ret = snprintf(path, len, "/proc/self/ns/mnt");
+	if (ret < 0 || (size_t)ret >= len) {
+		lxc_error("%s\n", "Failed to create path with snprintf().");
+		goto non_test_error;
+	}
+
+	init_ns = open(path, O_RDONLY | O_CLOEXEC);
+	if (init_ns < 0) {
+		lxc_error("%s\n", "Failed to open initial mount namespace.");
+		goto non_test_error;
+	}
+
+	if (unshare(CLONE_NEWNS) < 0) {
+		lxc_error("%s\n", "Could not unshare mount namespace.");
+		goto non_test_error;
+	}
+
+	fd = mkstemp(tmpf);
+	if (fd < 0) {
+		lxc_error("%s\n", "Could not create temporary file.");
+		goto non_test_error;
+	}
+
+	fp = fdopen(fd, "r+");
+	if (!fp) {
+		lxc_error("%s\n", "Could not fdopen() temporary file.");
+		goto non_test_error;
+	}
+
+	for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) {
+		if (fprintf(fp, "%s\n", mountinfo[i]) < 0) {
+			lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]);
+			goto non_test_error;
+		}
+	}
+	fclose(fp);
+	fp = NULL;
+
+	if (mount(tmpf, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) {
+		lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\".");
+		goto non_test_error;
+	}
+
+	lxc_test_assert_abort(detect_ramfs_rootfs());
+	fret = EXIT_SUCCESS;
+
+non_test_error:
+	if (fp)
+		fclose(fp);
+	else if (fd > 0)
+		close(fd);
+	if (init_ns > 0) {
+		if (setns(init_ns, 0) < 0) {
+			lxc_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno));
+			fret = EXIT_FAILURE;
+		}
+		close(init_ns);
+	}
+	if (fret == EXIT_SUCCESS)
+		return;
+	exit(fret);
+}
+
 void test_lxc_string_replace(void)
 {
 	char *s;


More information about the lxc-devel mailing list