From: Serge E. Hallyn <se...@us.ibm.com>

unsigned longs are not a good value to checkpoint between
x86-32 and x86-64 32-bit tasks :)

Signed-off-by: Serge E. Hallyn <se...@us.ibm.com>
---
 checkpoint/checkpoint.c        |    5 +--
 checkpoint/memory.c            |   53 +++++++++++++++++++++++++++++++++++++--
 checkpoint/restart.c           |    6 ++--
 include/linux/checkpoint_hdr.h |    2 +-
 4 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/checkpoint/checkpoint.c b/checkpoint/checkpoint.c
index b4e0021..b3c1c4f 100644
--- a/checkpoint/checkpoint.c
+++ b/checkpoint/checkpoint.c
@@ -103,13 +103,12 @@ int ckpt_write_string(struct ckpt_ctx *ctx, char *str, 
int len)
 static void fill_kernel_const(struct ckpt_const *h)
 {
        struct task_struct *tsk;
-       struct mm_struct *mm;
        struct new_utsname *uts;
 
        /* task */
        h->task_comm_len = sizeof(tsk->comm);
-       /* mm */
-       h->mm_saved_auxv_len = sizeof(mm->saved_auxv);
+       /* mm->saved_auxv size */
+       h->at_vector_size = AT_VECTOR_SIZE;
        /* signal */
        h->signal_nsig = _NSIG;
        /* uts */
diff --git a/checkpoint/memory.c b/checkpoint/memory.c
index d51f94b..5058ab3 100644
--- a/checkpoint/memory.c
+++ b/checkpoint/memory.c
@@ -661,6 +661,25 @@ static int checkpoint_vmas(struct ckpt_ctx *ctx, struct 
mm_struct *mm)
        return ret < 0 ? ret : map_count;
 }
 
+#define CKPT_AT_SZ (AT_VECTOR_SIZE * sizeof(u64))
+/*
+ * We always write saved_auxv out as an array of u64s, though it is
+ * an array of u32s on 32-bit arch.
+ */
+static int ckpt_write_auxv(struct ckpt_ctx *ctx, struct mm_struct *mm)
+{
+       int i, ret;
+       u64 *buf = kzalloc(CKPT_AT_SZ, GFP_KERNEL);
+
+       if (!buf)
+               return -ENOMEM;
+       for (i=0; i<AT_VECTOR_SIZE; i++)
+               buf[i] = mm->saved_auxv[i];
+       ret = ckpt_write_buffer(ctx, buf, CKPT_AT_SZ);
+       kfree(buf);
+       return ret;
+}
+
 static int do_checkpoint_mm(struct ckpt_ctx *ctx, struct mm_struct *mm)
 {
        struct ckpt_hdr_mm *h;
@@ -718,7 +737,7 @@ static int do_checkpoint_mm(struct ckpt_ctx *ctx, struct 
mm_struct *mm)
        if (ret < 0)
                goto out;
 
-       ret = ckpt_write_buffer(ctx, mm->saved_auxv, sizeof(mm->saved_auxv));
+       ret = ckpt_write_auxv(ctx, mm);
        if (ret < 0)
                return ret;
 
@@ -1205,6 +1224,32 @@ static int restore_vma(struct ckpt_ctx *ctx, struct 
mm_struct *mm)
        return ret;
 }
 
+static int ckpt_read_auxv(struct ckpt_ctx *ctx, struct mm_struct *mm)
+{
+       int i, ret;
+       u64 *buf = kmalloc(CKPT_AT_SZ, GFP_KERNEL);
+
+       if (!buf)
+               return -ENOMEM;
+       ret = _ckpt_read_buffer(ctx, buf, CKPT_AT_SZ);
+       if (ret < 0) {
+               kfree(buf);
+               return ret;
+       }
+
+       for (i=0; i<AT_VECTOR_SIZE; i++)
+               if (buf[i] > (u64) ULONG_MAX) {
+                       kfree(buf);
+                       return -E2BIG;
+               }
+
+       for (i=0; i<AT_VECTOR_SIZE; i++)
+               mm->saved_auxv[i] = buf[i];
+
+       kfree(buf);
+       return 0;
+}
+
 static struct mm_struct *do_restore_mm(struct ckpt_ctx *ctx)
 {
        struct ckpt_hdr_mm *h;
@@ -1270,9 +1315,11 @@ static struct mm_struct *do_restore_mm(struct ckpt_ctx 
*ctx)
        }
        up_write(&mm->mmap_sem);
 
-       ret = _ckpt_read_buffer(ctx, mm->saved_auxv, sizeof(mm->saved_auxv));
-       if (ret < 0)
+       ret = ckpt_read_auxv(ctx, mm);
+       if (ret < 0) {
+               ckpt_err(ctx, ret, "Error restoring auxv\n");
                goto out;
+       }
 
        for (nr = h->map_count; nr; nr--) {
                ret = restore_vma(ctx, mm);
diff --git a/checkpoint/restart.c b/checkpoint/restart.c
index 9bb17fc..a5f30f2 100644
--- a/checkpoint/restart.c
+++ b/checkpoint/restart.c
@@ -552,15 +552,15 @@ int ckpt_read_consume(struct ckpt_ctx *ctx, int len, int 
type)
 static int check_kernel_const(struct ckpt_const *h)
 {
        struct task_struct *tsk;
-       struct mm_struct *mm;
        struct new_utsname *uts;
 
        /* task */
        if (h->task_comm_len != sizeof(tsk->comm))
                return -EINVAL;
-       /* mm */
-       if (h->mm_saved_auxv_len != sizeof(mm->saved_auxv))
+       /* mm->saved_auxv size */
+       if (h->at_vector_size != AT_VECTOR_SIZE)
                return -EINVAL;
+
        /* signal */
        if (h->signal_nsig != _NSIG)
                return -EINVAL;
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 5a68178..b5dd95c 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -262,7 +262,7 @@ struct ckpt_const {
        /* task */
        __u16 task_comm_len;
        /* mm */
-       __u16 mm_saved_auxv_len;
+       __u16 at_vector_size;
        /* signal */
        __u16 signal_nsig;
        /* uts */
-- 
1.6.0.4

_______________________________________________
Containers mailing list
contain...@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
Devel@openvz.org
https://openvz.org/mailman/listinfo/devel

Reply via email to