[CRIU] [PATCH] creds: restore -- Honor rst_mem_alloc rules

Cyrill Gorcunov gorcunov at openvz.org
Thu Dec 24 11:42:45 PST 2015


rst_mem_alloc rules might move previously allocated
blocks which means we can't reuse previously allocated
pointer if new block is created. Thus remember pointers
positions where needed and adjust them accordingly.

https://github.com/xemul/criu/issues/97

Reported-by: Andrew Vagin <avagin at virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 cr-restore.c | 33 ++++++++++++++++++++++++---------
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 0166f1ca47f2..ba3cbe604ce6 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -2807,7 +2807,7 @@ static void rst_reloc_creds(struct thread_restore_args *thread_args,
 }
 
 static struct thread_creds_args *
-rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce)
+rst_prep_creds_args(CredsEntry *ce, unsigned long *prev_pos)
 {
 	unsigned long this_pos = rst_mem_cpos(RM_PRIVATE);
 	struct thread_creds_args *args;
@@ -2839,18 +2839,21 @@ rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce)
 
 		if (profile) {
 			size_t lsm_profile_len;
+			char *lsm_profile;
 
 			if (render_lsm_profile(profile, &rendered))
 				return ERR_PTR(-EINVAL);
 
 			args->mem_lsm_profile_pos = rst_mem_cpos(RM_PRIVATE);
 			lsm_profile_len = strlen(rendered);
-			args->lsm_profile = rst_mem_alloc(lsm_profile_len + 1, RM_PRIVATE);
-			if (!args->lsm_profile) {
+			lsm_profile = rst_mem_alloc(lsm_profile_len + 1, RM_PRIVATE);
+			if (!lsm_profile) {
 				xfree(rendered);
 				return ERR_PTR(-ENOMEM);
 			}
 
+			args = rst_mem_remap_ptr(this_pos, RM_PRIVATE);
+			args->lsm_profile = lsm_profile;
 			strncpy(args->lsm_profile, rendered, lsm_profile_len);
 			xfree(rendered);
 		}
@@ -2875,10 +2878,14 @@ rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce)
 	memcpy(args->cap_bnd, ce->cap_bnd, sizeof(args->cap_bnd));
 
 	if (ce->n_groups) {
+		unsigned int *groups;
+
 		args->mem_groups_pos = rst_mem_cpos(RM_PRIVATE);
-		args->groups = rst_mem_alloc(ce->n_groups * sizeof(u32), RM_PRIVATE);
-		if (!args->groups)
+		groups = rst_mem_alloc(ce->n_groups * sizeof(u32), RM_PRIVATE);
+		if (!groups)
 			return ERR_PTR(-ENOMEM);
+		args = rst_mem_remap_ptr(this_pos, RM_PRIVATE);
+		args->groups = groups;
 		memcpy(args->groups, ce->groups, ce->n_groups * sizeof(u32));
 	} else {
 		args->groups = NULL;
@@ -2887,8 +2894,15 @@ rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce)
 
 	args->mem_pos_next = 0;
 
-	if (prev)
-		prev->mem_pos_next = this_pos;
+	if (prev_pos) {
+		if (*prev_pos) {
+			struct thread_creds_args *prev;
+
+			prev = rst_mem_remap_ptr(*prev_pos, RM_PRIVATE);
+			prev->mem_pos_next = this_pos;
+		}
+		*prev_pos = this_pos;
+	}
 	return args;
 }
 
@@ -2908,7 +2922,7 @@ static int rst_prep_creds_from_img(pid_t pid)
 	if (ret > 0) {
 		struct thread_creds_args *args;
 
-		args = rst_prep_creds_args(NULL, ce);
+		args = rst_prep_creds_args(ce, NULL);
 		if (IS_ERR(args))
 			ret = PTR_ERR(args);
 		else
@@ -2921,6 +2935,7 @@ static int rst_prep_creds_from_img(pid_t pid)
 static int rst_prep_creds(pid_t pid, CoreEntry *core, unsigned long *creds_pos)
 {
 	struct thread_creds_args *args = NULL;
+	unsigned long this_pos = 0;
 	size_t i;
 
 	/*
@@ -2946,7 +2961,7 @@ static int rst_prep_creds(pid_t pid, CoreEntry *core, unsigned long *creds_pos)
 	for (i = 0; i < current->nr_threads; i++) {
 		CredsEntry *ce = current->core[i]->thread_core->creds;
 
-		args = rst_prep_creds_args(args, ce);
+		args = rst_prep_creds_args(ce, &this_pos);
 		if (IS_ERR(args))
 			return PTR_ERR(args);
 	}
-- 
2.5.0



More information about the CRIU mailing list