[5/6] util: Add cr_set_root/cr_restore_root helpers

Submitted by Cyrill Gorcunov on Aug. 31, 2018, 10:10 a.m.

Details

Message ID 20180831101004.26940-6-gorcunov@gmail.com
State New
Series "unix: Setup sysct and fix path resolving"
Headers show

Commit Message

Cyrill Gorcunov Aug. 31, 2018, 10:10 a.m.
From: Andrew Vagin <avagin@virtuozzo.com>

Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
---
 criu/include/util.h |  3 +++
 criu/util.c         | 62 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/util.h b/criu/include/util.h
index 5c18e69f793d..71fc6f0a4c91 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -377,4 +377,7 @@  static inline void print_stack_trace(pid_t pid) {}
 		___ret;									\
 	})
 
+int cr_set_root(int fd, int *old_root);
+int cr_restore_root(int fd);
+
 #endif /* __CR_UTIL_H__ */
diff --git a/criu/util.c b/criu/util.c
index ab4d89aac2bc..0dbe75eac221 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -1562,3 +1562,65 @@  void print_stack_trace(pid_t pid)
 	free(strings);
 }
 #endif
+
+/*
+ * When reading symlinks via /proc/$pid/root/ we should make sure
+ * the path resolving is done via root as toplevel root, otherwive
+ * the path may be screwed.
+ *
+ * IOW, for any path resolving via /proc/$pid/root use this helper,
+ * and call cr_restore_root once you're done.
+ */
+int cr_set_root(int fd, int *old_root)
+{
+	int errno_save = errno;
+	int cwd = -1, old = -1;
+
+	if (old_root) {
+		old = open("/", O_PATH);
+		if (old < 0) {
+			pr_perror("Unable to open(/)");
+			return -1;
+		}
+	}
+
+	cwd = open(".", O_PATH);
+	if (cwd < 0) {
+		pr_perror("Unable to open(.)");
+		goto err;
+	}
+
+	/* implement fchroot() */
+	if (fchdir(fd)) {
+		pr_perror("Unable to fchdir(%d)", fd);
+		goto err;
+	}
+	if (chroot(".")) {
+		pr_perror("Unable to chroot(.)");
+		goto err;
+	}
+	if (fchdir(cwd)) {
+		pr_perror("Unable to fchdir(%d)", fd);
+		goto err;
+	}
+
+	close(cwd);
+	if (old_root)
+		*old_root = old;
+
+	errno = errno_save;
+	return 0;
+
+err:
+	close_safe(&cwd);
+	close_safe(&old);
+	errno = errno_save;
+	return -1;
+}
+
+int cr_restore_root(int root)
+{
+	int ret = cr_set_root(root, NULL);
+	close(root);
+	return ret;
+}