[lxc-devel] [lxd/master] forksyscall: mknod fixes

brauner on Github lxc-bot at linuxcontainers.org
Mon Jul 15 11:53:44 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190715/45e991ce/attachment-0001.bin>
-------------- next part --------------
From 048dc04614931c3fc58ec7e4a8756f892eb870d0 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 15 Jul 2019 13:35:13 +0200
Subject: [PATCH 1/3] forksyscall: avoid calling close on garbage fd

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/main_forksyscall.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/main_forksyscall.go b/lxd/main_forksyscall.go
index f40e87e196..1c07bc0cd7 100644
--- a/lxd/main_forksyscall.go
+++ b/lxd/main_forksyscall.go
@@ -102,7 +102,7 @@ static int fstat_fstatfs(int fd, struct stat *s, struct statfs *sfs)
 // <PID> <root-uid> <root-gid> <path> <mode> <dev>
 static void forkmknod()
 {
-	__do_close_prot_errno int target_fd = -EBADF, host_target_fd;
+	__do_close_prot_errno int target_fd = -EBADF, host_target_fd = -EBADF;
 	int ret;
 	char *cur = NULL, *target = NULL, *target_host = NULL;
 	char cwd[256];

From 2f7960044384a2bd78c955d58a10e4076f7546e6 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 15 Jul 2019 13:38:51 +0200
Subject: [PATCH 2/3] forksyscall: s/target_fd/cwd_fd/g

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/main_forksyscall.go | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/lxd/main_forksyscall.go b/lxd/main_forksyscall.go
index 1c07bc0cd7..7cd6e9b3f4 100644
--- a/lxd/main_forksyscall.go
+++ b/lxd/main_forksyscall.go
@@ -102,10 +102,10 @@ static int fstat_fstatfs(int fd, struct stat *s, struct statfs *sfs)
 // <PID> <root-uid> <root-gid> <path> <mode> <dev>
 static void forkmknod()
 {
-	__do_close_prot_errno int target_fd = -EBADF, host_target_fd = -EBADF;
+	__do_close_prot_errno int cwd_fd = -EBADF, host_target_fd = -EBADF;
 	int ret;
 	char *cur = NULL, *target = NULL, *target_host = NULL;
-	char cwd[256];
+	char path[PATH_MAX];
 	mode_t mode = 0;
 	dev_t dev = 0;
 	pid_t pid = 0;
@@ -125,9 +125,9 @@ static void forkmknod()
 	gid = atoi(advance_arg(true));
 	chk_perm_only = atoi(advance_arg(true));
 
-	snprintf(cwd, sizeof(cwd), "/proc/%d/cwd", pid);
-	target_fd = open(cwd, O_PATH | O_RDONLY | O_CLOEXEC);
-	if (target_fd < 0) {
+	snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
+	cwd_fd = open(path, O_PATH | O_RDONLY | O_CLOEXEC);
+	if (cwd_fd < 0) {
 		fprintf(stderr, "%d", ENOANO);
 		_exit(EXIT_FAILURE);
 	}
@@ -174,7 +174,7 @@ static void forkmknod()
 		_exit(EXIT_FAILURE);
 	}
 
-	ret = fstat_fstatfs(target_fd, &s2, &sfs2);
+	ret = fstat_fstatfs(cwd_fd, &s2, &sfs2);
 	if (ret) {
 		fprintf(stderr, "%d", ENOANO);
 		_exit(EXIT_FAILURE);
@@ -203,7 +203,7 @@ static void forkmknod()
 
 	// basename() can modify its argument so accessing target_host is
 	// invalid from now on.
-	ret = mknodat(target_fd, target, mode, dev);
+	ret = mknodat(cwd_fd, target, mode, dev);
 	if (ret) {
 		fprintf(stderr, "%d", errno);
 		_exit(EXIT_FAILURE);

From 49fe45596b7b39eae57c3757d695618c0bc0362b Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 15 Jul 2019 13:40:11 +0200
Subject: [PATCH 3/3] forksyscall: add chdirchroot()

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/main_forksyscall.go | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/lxd/main_forksyscall.go b/lxd/main_forksyscall.go
index 7cd6e9b3f4..35d134d706 100644
--- a/lxd/main_forksyscall.go
+++ b/lxd/main_forksyscall.go
@@ -98,13 +98,28 @@ static int fstat_fstatfs(int fd, struct stat *s, struct statfs *sfs)
 	return 0;
 }
 
+static bool chdirchroot(pid_t pid)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
+	if (chdir(path))
+		return false;
+
+	snprintf(path, sizeof(path), "/proc/%d/root", pid);
+	if (chroot(path))
+		return false;
+
+	return true;
+}
+
 // Expects command line to be in the form:
 // <PID> <root-uid> <root-gid> <path> <mode> <dev>
 static void forkmknod()
 {
 	__do_close_prot_errno int cwd_fd = -EBADF, host_target_fd = -EBADF;
 	int ret;
-	char *cur = NULL, *target = NULL, *target_host = NULL;
+	char *cur = NULL, *target = NULL, *target_dir = NULL, *target_host = NULL;
 	char path[PATH_MAX];
 	mode_t mode = 0;
 	dev_t dev = 0;
@@ -125,7 +140,15 @@ static void forkmknod()
 	gid = atoi(advance_arg(true));
 	chk_perm_only = atoi(advance_arg(true));
 
-	snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
+	if (*target == '/') {
+		// user has specified an absolute path
+		snprintf(path, sizeof(path), "%s", target);
+		target_dir = dirname(path);
+	} else {
+		// user has specified a relative path
+		snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
+		target_dir = path;
+	}
 	cwd_fd = open(path, O_PATH | O_RDONLY | O_CLOEXEC);
 	if (cwd_fd < 0) {
 		fprintf(stderr, "%d", ENOANO);
@@ -138,7 +161,15 @@ static void forkmknod()
 		_exit(EXIT_FAILURE);
 	}
 
-	(void)dosetns(pid, "mnt");
+	if (dosetns(pid, "mnt")) {
+		fprintf(stderr, "%d", ENOANO);
+		_exit(EXIT_FAILURE);
+	}
+
+	if (chdirchroot(pid)) {
+		fprintf(stderr, "%d", ENOANO);
+		_exit(EXIT_FAILURE);
+	}
 
 	caps = cap_get_pid(pid);
 	if (!caps) {
@@ -208,7 +239,6 @@ static void forkmknod()
 		fprintf(stderr, "%d", errno);
 		_exit(EXIT_FAILURE);
 	}
-
 }
 
 void forksyscall()


More information about the lxc-devel mailing list