[CRIU] [PATCH v2 1/3] kerndat: add has_loginuid to kerndat_s

Dmitry Safonov dsafonov at odin.com
Thu Dec 24 03:43:43 PST 2015


This value will differ on C/R:
  - on checkpoint it means that it's possible to dump logiuid values;
  - on restore it means that it's possible to unset loginuid and write
    saved value to unsetted loginuid.

Signed-off-by: Dmitry Safonov <dsafonov at odin.com>
---
 cr-restore.c         | 19 -------------------
 include/kerndat.h    |  2 ++
 include/proc_parse.h |  1 +
 kerndat.c            | 37 +++++++++++++++++++++++++++++++++++++
 proc_parse.c         | 19 +++++++++++++++++++
 5 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 9fc1e3d..52d70a9 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -860,25 +860,6 @@ static int prepare_oom_score_adj(int value)
 	return ret;
 }
 
-static int prepare_loginuid(unsigned int value)
-{
-	int fd, ret = 0;
-	char buf[11]; /* 4294967295 is maximum for u32 */
-
-	fd = open_proc_rw(PROC_SELF, "loginuid");
-	if (fd < 0)
-		return -1;
-
-	snprintf(buf, 11, "%u", value);
-
-	if (write(fd, buf, 11) < 0) {
-		pr_perror("Write %s to /proc/self/loginuid failed", buf);
-		ret = -1;
-	}
-	close(fd);
-	return ret;
-}
-
 static int prepare_proc_misc(pid_t pid, TaskCoreEntry *tc)
 {
 	int ret;
diff --git a/include/kerndat.h b/include/kerndat.h
index 076804c..23d9104 100644
--- a/include/kerndat.h
+++ b/include/kerndat.h
@@ -14,6 +14,7 @@ extern int kerndat_init(void);
 extern int kerndat_init_rst(void);
 extern int kerndat_get_dirty_track(void);
 extern int kerndat_fdinfo_has_lock(void);
+extern int kerndat_loginuid(bool only_dump);
 
 struct kerndat_s {
 	dev_t shmem_dev;
@@ -25,6 +26,7 @@ struct kerndat_s {
 	bool has_fdinfo_lock;
 	unsigned long task_size;
 	bool ipv6;
+	bool has_loginuid;
 };
 
 extern struct kerndat_s kdat;
diff --git a/include/proc_parse.h b/include/proc_parse.h
index b0bdac5..d65a4a8 100644
--- a/include/proc_parse.h
+++ b/include/proc_parse.h
@@ -122,6 +122,7 @@ extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool fo
 extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
 extern unsigned int parse_pid_loginuid(pid_t pid, int *err);
 extern int parse_pid_oom_score_adj(pid_t pid, int *err);
+extern int prepare_loginuid(unsigned int value);
 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);
 extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
diff --git a/kerndat.c b/kerndat.c
index 4605470..6061194 100644
--- a/kerndat.c
+++ b/kerndat.c
@@ -19,6 +19,7 @@
 #include "cr_options.h"
 #include "util.h"
 #include "lsm.h"
+#include "proc_parse.h"
 
 struct kerndat_s kdat = {
 	/*
@@ -353,6 +354,38 @@ static int get_ipv6()
 	return 0;
 }
 
+int kerndat_loginuid(bool only_dump)
+{
+	unsigned int saved_loginuid;
+	int ret;
+
+	kdat.has_loginuid = false;
+
+	/* No such file, or perm fault: CONFIG_AUDITSYSCALL disabled */
+	saved_loginuid = parse_pid_loginuid(getpid(), &ret);
+	if (ret < 0)
+		return 0;
+
+	if (only_dump) {
+		kdat.has_loginuid = true;
+		return 0;
+	}
+
+	/*
+	 * From kernel v3.13-rc2 it's possible to unset loginuid value,
+	 * on that rely dump/restore code.
+	 * See also: marc.info/?l=git-commits-head&m=138509506407067
+	 */
+	if (prepare_loginuid(INVALID_UID) < 0)
+		return 0;
+	/* Cleaning value back as it was */
+	if (prepare_loginuid(saved_loginuid) < 0)
+		return 0;
+
+	kdat.has_loginuid = true;
+	return 0;
+}
+
 int kerndat_init(void)
 {
 	int ret;
@@ -370,6 +403,8 @@ int kerndat_init(void)
 		ret = get_task_size();
 	if (!ret)
 		ret = get_ipv6();
+	if (!ret)
+		ret = kerndat_loginuid(true);
 
 	kerndat_lsm();
 
@@ -395,6 +430,8 @@ int kerndat_init_rst(void)
 		ret = get_task_size();
 	if (!ret)
 		ret = get_ipv6();
+	if (!ret)
+		ret = kerndat_loginuid(false);
 
 	kerndat_lsm();
 
diff --git a/proc_parse.c b/proc_parse.c
index 2eef21a..fa3f0d3 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -724,6 +724,25 @@ err:
 	return -1;
 }
 
+int prepare_loginuid(unsigned int value)
+{
+	int fd, ret = 0;
+	char buf[11]; /* 4294967295 is maximum for u32 */
+
+	fd = open_proc_rw(PROC_SELF, "loginuid");
+	if (fd < 0)
+		return -1;
+
+	snprintf(buf, 11, "%u", value);
+
+	if (write(fd, buf, 11) < 0) {
+		pr_perror("Write %s to /proc/self/loginuid failed", buf);
+		ret = -1;
+	}
+	close(fd);
+	return ret;
+}
+
 unsigned int parse_pid_loginuid(pid_t pid, int *err)
 {
 	int fd;
-- 
2.6.4



More information about the CRIU mailing list