[CRIU] [PATCH 3/3] criu: unset loginuid value before creating userns

Dmitry Safonov dsafonov at odin.com
Mon Dec 7 06:17:10 PST 2015


One can change loginuid value if it's not set _always_,
but can not change inside userns if it was set.

See http://lxr.free-electrons.com/source/kernel/audit.c#L635
https://jira.sw.ru/browse/PSBM-41993

Signed-off-by: Dmitry Safonov <dsafonov at odin.com>
---
 cr-restore.c         | 19 +------------------
 include/proc_parse.h |  1 +
 namespaces.c         | 27 +++++++++++++++++++++++++++
 proc_parse.c         | 17 +++++++++++++++++
 4 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 11e86cd..76a368d 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -857,27 +857,10 @@ static void prepare_pid_oom_score_adj(pid_t pid, int value)
 	close(fd);
 }
 
-static void prepare_pid_loginuid(pid_t pid, unsigned int value)
-{
-	int fd;
-	char buf[11]; /* 4294967295 is maximum for u32 */
-
-	fd = open_proc_rw(pid, "loginuid");
-	if (fd < 0) {
-		pr_err("Can't open /proc/%d/loginuid to restore\n", pid);
-		return;
-	}
-	snprintf(buf, 11, "%u", value);
-	if (write(fd, buf, 11) < 0) {
-		pr_perror("Write %s to /proc/%d/loginuid failed", buf, pid);
-	}
-	close(fd);
-}
-
 static int prepare_proc_misc(pid_t pid, TaskCoreEntry *tc)
 {
 	if (tc->has_loginuid)
-		prepare_pid_loginuid(pid, tc->loginuid);
+		set_pid_loginuid(pid, tc->loginuid);
 	if (tc->has_oom_score_adj)
 		prepare_pid_oom_score_adj(pid, tc->oom_score_adj);
 	return 0;
diff --git a/include/proc_parse.h b/include/proc_parse.h
index 3cc821b..e724fb3 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -115,6 +115,7 @@ extern bool add_skip_mount(const char *mountpoint);
 extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump);
 extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
 extern unsigned int parse_pid_loginuid(pid_t pid);
+extern void set_pid_loginuid(int pid, unsigned int value);
 extern int parse_pid_oom_score_adj(pid_t pid);
 extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list);
 extern int parse_self_maps_lite(struct vm_area_list *vms);
diff --git a/namespaces.c b/namespaces.c
index a874fb1..1e38a03 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -19,6 +19,7 @@
 #include "pstree.h"
 #include "namespaces.h"
 #include "net.h"
+#include "proc_parse.h"
 
 #include "protobuf.h"
 #include "protobuf/ns.pb-c.h"
@@ -1089,6 +1090,28 @@ out:
 	return ret;
 }
 
+static unsigned int saved_loginuid = 0;
+
+static void prepare_userns_hook(void)
+{
+	pid_t pid = getpid();
+
+	/*
+	 * Save old loginuid and set it to 4294967295:
+	 * this value means that loginuid is unset and it will be inherited.
+	 * After you set some value to /proc/<>/loginuid it can't be changed
+	 * inside container due to permissions.
+	 * But you still can set this value if it was unset (4294967295/-1).
+	 */
+	saved_loginuid = parse_pid_loginuid(pid);
+	set_pid_loginuid(pid, 4294967295);
+}
+
+static void restore_origin_ns_hook(void)
+{
+	set_pid_loginuid(getpid(), saved_loginuid);
+}
+
 static int start_usernsd(void)
 {
 	int sk[2];
@@ -1125,6 +1148,8 @@ static int start_usernsd(void)
 		return -1;
 	}
 
+	prepare_userns_hook();
+
 	usernsd_pid = fork();
 	if (usernsd_pid < 0) {
 		pr_perror("Can't fork usernsd");
@@ -1141,6 +1166,8 @@ static int start_usernsd(void)
 		exit(ret);
 	}
 
+	restore_origin_ns_hook();
+
 	close(sk[1]);
 	if (install_service_fd(USERNSD_SK, sk[0]) < 0) {
 		kill(usernsd_pid, SIGKILL);
diff --git a/proc_parse.c b/proc_parse.c
index c40a1b1..f730082 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -743,6 +743,23 @@ out:
 	return ret;
 }
 
+void set_pid_loginuid(pid_t pid, unsigned int value)
+{
+	int fd;
+	char buf[11]; /* 4294967295 is maximum for u32 */
+
+	fd = open_proc_rw(pid, "loginuid");
+	if (fd < 0) {
+		pr_err("Can't open /proc/%d/loginuid to restore\n", pid);
+		return;
+	}
+	snprintf(buf, 11, "%u", value);
+	if (write(fd, buf, 11) < 0) {
+		pr_perror("Write %s to /proc/%d/loginuid failed", buf, pid);
+	}
+	close(fd);
+}
+
 int parse_pid_oom_score_adj(pid_t pid)
 {
 	int ret = 0;
-- 
2.6.3



More information about the CRIU mailing list