Commit f7e6e63b authored by Cyrill Gorcunov's avatar Cyrill Gorcunov

kernel, dump: Obtain brk value

Also re-make image to be 2 pages in size
which should be enough for basic params we
need to restore tasks.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
parent 116b00ee
......@@ -547,6 +547,7 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
user_regs_struct_t regs = {-1};
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
int ret = -1;
unsigned long brk;
pr_info("\n");
pr_info("Dumping core (pid: %d)\n", pid);
......@@ -623,6 +624,13 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
goto err_free;
pr_info("OK\n");
pr_info("Obtainting task brk ... ");
brk = brk_seized(pid, 0);
if ((long)brk < 0)
goto err_free;
core->mm_brk = brk;
pr_info("OK\n");
pr_info("Dumping header ... ");
core->header.version = HEADER_VERSION;
core->header.arch = HEADER_ARCH_X86_64;
......
......@@ -107,6 +107,7 @@ static void show_core_rest(struct cr_fdset *cr_fdset)
int fd_core, i;
u32 personality;
char comm[TASK_COMM_LEN];
u64 mm_brk;
fd_core = cr_fdset->desc[CR_FD_CORE].fd;
if (fd_core < 0)
......@@ -118,8 +119,12 @@ static void show_core_rest(struct cr_fdset *cr_fdset)
lseek(fd_core, GET_FILE_OFF(struct core_entry, task_comm), SEEK_SET);
read_safe(fd_core, comm, TASK_COMM_LEN, err);
lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_brk), SEEK_SET);
read_ptr_safe(fd_core, &mm_brk, err);
pr_info("Personality: %x\n", personality);
pr_info("Command: %s\n", comm);
pr_info("Brk: %lx\n", mm_brk);
err:
return;
}
......
......@@ -168,16 +168,23 @@ struct ckpt_arch_entry {
};
#define CKPT_ARCH_SIZE 2048
#define CKPT_CORE_SIZE 8192
struct core_entry {
union {
struct {
struct image_header header;
union {
struct ckpt_arch_entry arch; /* per-arch specific */
u8 __pad[CKPT_ARCH_SIZE]; /* should be enough for all */
u8 __arch_pad[CKPT_ARCH_SIZE]; /* should be enough for all */
} u;
u32 task_personality;
u8 task_comm[TASK_COMM_LEN];
u32 task_flags;
u64 mm_brk;
};
u8 __core_pad[CKPT_CORE_SIZE];
};
} __packed;
#endif /* CONFIG_X86_64 */
......
......@@ -30,7 +30,7 @@ void *mmap_seized(pid_t pid, user_regs_struct_t *regs,
int munmap_seized(pid_t pid, user_regs_struct_t *regs,
void *addr, size_t length);
int kill_seized(pid_t pid, user_regs_struct_t *where);
unsigned long brk_seized(pid_t pid, unsigned long addr);
int syscall_seized(pid_t pid,
user_regs_struct_t *where,
......
......@@ -109,6 +109,7 @@ static long syscall6(int nr, unsigned long arg0, unsigned long arg1,
#define __NR_mmap 9
#define __NR_mprotect 10
#define __NR_munmap 11
#define __NR_brk 12
#define __NR_mincore 27
#define __NR_dup 32
#define __NR_dup2 33
......
......@@ -27,16 +27,16 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
arch/x86/include/asm/elf.h | 3
arch/x86/include/asm/elf_ckpt.h | 80 ++++++++
arch/x86/kernel/Makefile | 2
arch/x86/kernel/elf_ckpt.c | 156 ++++++++++++++++
arch/x86/kernel/elf_ckpt.c | 161 +++++++++++++++++
arch/x86/vdso/vma.c | 22 ++
fs/Kconfig.binfmt | 11 +
fs/Makefile | 1
fs/binfmt_elf.c | 17 +
fs/binfmt_elf_ckpt.c | 381 ++++++++++++++++++++++++++++++++++++++++
fs/binfmt_elf_ckpt.c | 378 ++++++++++++++++++++++++++++++++++++++++
fs/exec.c | 27 +-
include/linux/binfmts.h | 1
include/linux/elf_ckpt.h | 90 +++++++++
12 files changed, 779 insertions(+), 12 deletions(-)
include/linux/elf_ckpt.h | 97 ++++++++++
12 files changed, 788 insertions(+), 12 deletions(-)
Index: linux-2.6.git/arch/x86/include/asm/elf.h
===================================================================
......@@ -154,7 +154,7 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
===================================================================
--- /dev/null
+++ linux-2.6.git/arch/x86/kernel/elf_ckpt.c
@@ -0,0 +1,156 @@
@@ -0,0 +1,161 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
......@@ -208,6 +208,11 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
+ mm_segment_t old_fs;
+ int i, ret;
+
+ if (core_entry->header.arch != CKPT_HEADER_ARCH_X86_64) {
+ pr_err("elf-ckpt-x86: Unsupported or corrupted header\n");
+ return -ENOEXEC;
+ }
+
+ BUILD_BUG_ON(CKPT_GDT_ENTRY_TLS_ENTRIES != GDT_ENTRY_TLS_ENTRIES);
+ BUILD_BUG_ON(sizeof(struct ckpt_arch_entry) > CKPT_ARCH_SIZE);
+
......@@ -424,7 +429,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
===================================================================
--- /dev/null
+++ linux-2.6.git/fs/binfmt_elf_ckpt.c
@@ -0,0 +1,381 @@
@@ -0,0 +1,378 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
......@@ -477,8 +482,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ unsigned long map_addr;
+
+ unsigned long start_code, end_code, start_data, end_data;
+ unsigned long start_brk, brk, start_stack;
+ unsigned long elf_bss, elf_brk;
+ unsigned long start_brk, start_stack;
+
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ unsigned long vdso = -1UL;
......@@ -490,15 +494,13 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+
+ BUILD_BUG_ON(CKPT_TASK_COMM_LEN != TASK_COMM_LEN);
+ BUILD_BUG_ON(CKPT_PAGE_SIZE != PAGE_SIZE);
+ BUILD_BUG_ON(CKPT_CORE_SIZE != sizeof(*core_entry));
+
+ elf_phdr_core = NULL;
+ elf_phdr_pages = NULL;
+ nr_vma_found = 0;
+ nr_vma_mapped = 0;
+
+ elf_bss = 0;
+ elf_brk = 0;
+
+ start_code = -1UL;
+ end_code = 0;
+
......@@ -507,7 +509,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+
+ start_stack = -1UL;
+ start_brk = -1UL;
+ brk = -1UL;
+
+ fa = flex_array_alloc(sizeof(vma_entry), elf_ex->e_phnum, GFP_KERNEL);
+ if (!fa || flex_array_prealloc(fa, 0, elf_ex->e_phnum, GFP_KERNEL)) {
......@@ -589,8 +590,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ goto out;
+ }
+
+ if (core_entry->header.version != CKPT_HEADER_VERSION ||
+ core_entry->header.arch != CKPT_HEADER_ARCH_X86_64) {
+ if (core_entry->header.version != CKPT_HEADER_VERSION) {
+ pr_err("elf-ckpt: Unsupported or corrupted header\n");
+ ret = -ENOEXEC;
+ goto out;
......@@ -604,7 +604,9 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ current->flags |= PF_RANDOMIZE;
+
+ /*
+ * FIXME: Note it flushes signal handlers as well.
+ * FIXME: Note it flushes signal handlers as well,
+ * so we need to dump queued signals and restore
+ * them here.
+ */
+ setup_new_exec(bprm);
+
......@@ -712,7 +714,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ current->mm->end_data = end_data;
+ current->mm->start_stack = start_stack;
+ current->mm->start_brk = start_brk;
+ current->mm->brk = brk;
+ current->mm->brk = core_entry->mm_brk;
+
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ ret = arch_setup_additional_pages_at(bprm, (void *)vdso, 0);
......@@ -873,7 +875,7 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
===================================================================
--- /dev/null
+++ linux-2.6.git/include/linux/elf_ckpt.h
@@ -0,0 +1,90 @@
@@ -0,0 +1,97 @@
+#ifndef _LINUX_ELF_CHECKPOINT_H
+#define _LINUX_ELF_CHECKPOINT_H
+
......@@ -941,13 +943,20 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
+} __packed;
+
+#define CKPT_ARCH_SIZE 2048
+#define CKPT_CORE_SIZE 8192
+
+struct core_entry {
+ union {
+ struct {
+ struct image_header header;
+ __u8 arch[CKPT_ARCH_SIZE]; /* should be enough for all archs */
+ __u32 task_personality;
+ __u8 task_comm[CKPT_TASK_COMM_LEN];
+ __u32 task_flags;
+ __u64 mm_brk;
+ };
+ __u8 __core_pad[CKPT_CORE_SIZE];
+ };
+} __packed;
+
+#ifdef CONFIG_BINFMT_ELF_CKPT
......
......@@ -100,6 +100,29 @@ int kill_seized(pid_t pid, user_regs_struct_t *where)
return ret;
}
unsigned long brk_seized(pid_t pid, unsigned long addr)
{
user_regs_struct_t params, regs_orig;
unsigned long ret = -1UL;
jerr(ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig), err);
params = regs_orig;
params.ax = (unsigned long)__NR_brk; /* brk */
params.di = (unsigned long)addr; /* @addr */
ret = syscall_seized(pid, &regs_orig, &params, &params);
if (!ret)
ret = (unsigned long)params.ax;
else
ret = -1UL;
if (ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig))
pr_panic("Can't restore registers (pid: %d)\n", pid);
err:
return ret;
}
int syscall_seized(pid_t pid,
user_regs_struct_t *where,
user_regs_struct_t *params,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment