[CRIU] [PATCH 04/17] dump: get tasks ids from parasite

Andrey Vagin avagin at openvz.org
Fri Oct 31 02:14:22 PDT 2014


We have two reason for that:
* parsing of /proc/pid/status is slow
* parasite returns ids from a target userns

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 arch/arm/syscall.def        |  2 ++
 arch/x86/syscall-x86-64.def |  2 ++
 cr-dump.c                   | 31 ++++++++++++-------------------
 include/crtools.h           |  1 +
 include/parasite.h          | 10 +++++-----
 parasite-syscall.c          | 10 ++++++++++
 pie/parasite.c              | 16 ++++++++++++++++
 security.c                  |  5 +++++
 8 files changed, 53 insertions(+), 24 deletions(-)

diff --git a/arch/arm/syscall.def b/arch/arm/syscall.def
index 3b2d1ed..2eed6cf 100644
--- a/arch/arm/syscall.def
+++ b/arch/arm/syscall.def
@@ -54,7 +54,9 @@ readlink			78	85	(const char *path, char *buf, int bufsize)
 umask				166	60	(int mask)
 getgroups			158	205	(int gsize, unsigned int *groups)
 setresuid			147	164	(int uid, int euid, int suid)
+getresuid			148	165	(int *uid, int *euid, int *suid)
 setresgid			149	170	(int gid, int egid, int sgid)
+getresgid			150	171	(int *gid, int *egid, int *sgid)
 getpgid				155	132	(pid_t pid)
 setfsuid			151	138	(int fsuid)
 setfsgid			152	139	(int fsgid)
diff --git a/arch/x86/syscall-x86-64.def b/arch/x86/syscall-x86-64.def
index c780c40..1404123 100644
--- a/arch/x86/syscall-x86-64.def
+++ b/arch/x86/syscall-x86-64.def
@@ -54,7 +54,9 @@ __NR_readlink		89		sys_readlink		(const char *path, char *buf, int bufsize)
 __NR_umask		95		sys_umask		(int mask)
 __NR_getgroups		115		sys_getgroups		(int gsize, unsigned int *groups)
 __NR_setresuid		117		sys_setresuid		(int uid, int euid, int suid)
+__NR_getresuid		118		sys_getresuid		(int *uid, int *euid, int *suid)
 __NR_setresgid		119		sys_setresgid		(int gid, int egid, int sgid)
+__NR_getresgid		120		sys_getresgid		(int *gid, int *egid, int *sgid)
 __NR_getpgid		121		sys_getpgid		(pid_t pid)
 __NR_setfsuid		122		sys_setfsuid		(int fsuid)
 __NR_setfsgid		123		sys_setfsgid		(int fsgid)
diff --git a/cr-dump.c b/cr-dump.c
index 7d33e3d..a40b5ae 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -501,20 +501,10 @@ err:
 }
 
 static int dump_task_creds(struct parasite_ctl *ctl,
-			   const struct cr_imgset *fds,
-			   struct proc_status_creds *cr)
+			   const struct cr_imgset *fds)
 {
 	CredsEntry ce = CREDS_ENTRY__INIT;
 
-	ce.uid   = cr->uids[0];
-	ce.gid   = cr->gids[0];
-	ce.euid  = cr->uids[1];
-	ce.egid  = cr->gids[1];
-	ce.suid  = cr->uids[2];
-	ce.sgid  = cr->gids[2];
-	ce.fsuid = cr->uids[3];
-	ce.fsgid = cr->gids[3];
-
 	pr_info("\n");
 	pr_info("Dumping creds for %d)\n", ctl->pid.real);
 	pr_info("----------------------------------------\n");
@@ -1475,7 +1465,6 @@ static int dump_one_task(struct pstree_item *item)
 	struct cr_imgset *cr_imgset = NULL;
 	struct parasite_drain_fd *dfds = NULL;
 	struct proc_posix_timers_stat proc_args;
-	struct proc_status_creds cr;
 
 	INIT_LIST_HEAD(&vmas.h);
 	vmas.nr = 0;
@@ -1495,13 +1484,17 @@ static int dump_one_task(struct pstree_item *item)
 	if (ret < 0)
 		goto err;
 
-	ret = parse_pid_status(pid, &cr);
-	if (ret)
-		goto err;
+	if (!cr_user_is_root()) {
+		struct proc_status_creds cr;
 
-	if (!may_dump(&cr)) {
-		pr_err("Check uid (pid: %d) failed\n", pid);
-		goto err;
+		ret = parse_pid_status(pid, &cr);
+		if (ret)
+			goto err;
+
+		if (!may_dump(&cr)) {
+			pr_err("Check uid (pid: %d) failed\n", pid);
+			goto err;
+		}
 	}
 
 	ret = collect_mappings(pid, &vmas);
@@ -1626,7 +1619,7 @@ static int dump_one_task(struct pstree_item *item)
 		goto err_cure;
 	}
 
-	ret = dump_task_creds(parasite_ctl, cr_imgset, &cr);
+	ret = dump_task_creds(parasite_ctl, cr_imgset);
 	if (ret) {
 		pr_err("Dump creds (pid: %d) failed with %d\n", pid, ret);
 		goto err;
diff --git a/include/crtools.h b/include/crtools.h
index a51886e..f4b09a3 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -29,5 +29,6 @@ struct proc_status_creds;
 extern bool may_dump(struct proc_status_creds *);
 struct _CredsEntry;
 extern bool may_restore(struct _CredsEntry *);
+extern bool cr_user_is_root(void);
 
 #endif /* __CR_CRTOOLS_H__ */
diff --git a/include/parasite.h b/include/parasite.h
index 44be00c..7b3e668 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -169,10 +169,8 @@ struct parasite_dump_misc {
  * and still fit the struct in one page
  */
 #define PARASITE_MAX_GROUPS							\
-	(PAGE_SIZE								\
-	 - sizeof(unsigned int)			/* cap_last_cap */		\
-	 - 4 * CR_CAP_SIZE * sizeof(u32)	/* cap_{inh,prm,eff,bnd} */ 	\
-	 - 2 * sizeof(unsigned int)		/* secbits, ngroups*/		\
+	(PAGE_SIZE -								\
+	 offsetof(struct parasite_dump_creds, groups)				\
 	) / sizeof(unsigned int)		/* groups */
 
 struct parasite_dump_creds {
@@ -183,9 +181,11 @@ struct parasite_dump_creds {
 	u32			cap_eff[CR_CAP_SIZE];
 	u32			cap_bnd[CR_CAP_SIZE];
 
+	int			uids[4];
+	int			gids[4];
 	unsigned int		secbits;
 	unsigned int		ngroups;
-	unsigned int		groups[PARASITE_MAX_GROUPS];
+	unsigned int		groups[0];
 };
 
 static inline void copy_sas(ThreadSasEntry *dst, const stack_t *src)
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 063cf47..d17db0b 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -762,6 +762,16 @@ int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce)
 
 	BUILD_BUG_ON(sizeof(ce->groups[0]) != sizeof(pc->groups[0]));
 	ce->groups = pc->groups;
+
+	ce->uid   = pc->uids[0];
+	ce->gid   = pc->gids[0];
+	ce->euid  = pc->uids[1];
+	ce->egid  = pc->gids[1];
+	ce->suid  = pc->uids[2];
+	ce->sgid  = pc->gids[2];
+	ce->fsuid = pc->uids[3];
+	ce->fsgid = pc->gids[3];
+
 	return 0;
 }
 
diff --git a/pie/parasite.c b/pie/parasite.c
index 7f1b80a..9557c55 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -236,6 +236,22 @@ static int dump_creds(struct parasite_dump_creds *args)
 		return -1;
 	}
 
+	ret = sys_getresuid(&args->uids[0], &args->uids[1], &args->uids[2]);
+	if (ret) {
+		pr_err("Unable to get uids: %d\n", ret);
+		return -1;
+	}
+
+	args->uids[3] = sys_setfsuid(-1L);
+
+	ret = sys_getresgid(&args->gids[0], &args->gids[1], &args->gids[2]);
+	if (ret) {
+		pr_err("Unable to get uids: %d\n", ret);
+		return -1;
+	}
+
+	args->gids[3] = sys_setfsgid(-1L);
+
 	return 0;
 
 grps_err:
diff --git a/security.c b/security.c
index a801005..5189846 100644
--- a/security.c
+++ b/security.c
@@ -150,6 +150,11 @@ static bool check_caps(u32 *inh, u32 *eff, u32 *prm)
 	return true;
 }
 
+bool cr_user_is_root()
+{
+	return cr_uid == 0 && cr_gid == 0;
+}
+
 bool may_dump(struct proc_status_creds *creds)
 {
 	return check_uids(creds->uids[0], creds->uids[1], creds->uids[2]) &&
-- 
1.9.3



More information about the CRIU mailing list