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) ...@@ -547,6 +547,7 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
user_regs_struct_t regs = {-1}; user_regs_struct_t regs = {-1};
int fd_core = cr_fdset->desc[CR_FD_CORE].fd; int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
int ret = -1; int ret = -1;
unsigned long brk;
pr_info("\n"); pr_info("\n");
pr_info("Dumping core (pid: %d)\n", pid); 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) ...@@ -623,6 +624,13 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
goto err_free; goto err_free;
pr_info("OK\n"); 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 ... "); pr_info("Dumping header ... ");
core->header.version = HEADER_VERSION; core->header.version = HEADER_VERSION;
core->header.arch = HEADER_ARCH_X86_64; core->header.arch = HEADER_ARCH_X86_64;
......
...@@ -107,6 +107,7 @@ static void show_core_rest(struct cr_fdset *cr_fdset) ...@@ -107,6 +107,7 @@ static void show_core_rest(struct cr_fdset *cr_fdset)
int fd_core, i; int fd_core, i;
u32 personality; u32 personality;
char comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN];
u64 mm_brk;
fd_core = cr_fdset->desc[CR_FD_CORE].fd; fd_core = cr_fdset->desc[CR_FD_CORE].fd;
if (fd_core < 0) if (fd_core < 0)
...@@ -118,8 +119,12 @@ static void show_core_rest(struct cr_fdset *cr_fdset) ...@@ -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); lseek(fd_core, GET_FILE_OFF(struct core_entry, task_comm), SEEK_SET);
read_safe(fd_core, comm, TASK_COMM_LEN, err); 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("Personality: %x\n", personality);
pr_info("Command: %s\n", comm); pr_info("Command: %s\n", comm);
pr_info("Brk: %lx\n", mm_brk);
err: err:
return; return;
} }
......
...@@ -168,16 +168,23 @@ struct ckpt_arch_entry { ...@@ -168,16 +168,23 @@ struct ckpt_arch_entry {
}; };
#define CKPT_ARCH_SIZE 2048 #define CKPT_ARCH_SIZE 2048
#define CKPT_CORE_SIZE 8192
struct core_entry { struct core_entry {
union {
struct {
struct image_header header; struct image_header header;
union { union {
struct ckpt_arch_entry arch; /* per-arch specific */ 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; } u;
u32 task_personality; u32 task_personality;
u8 task_comm[TASK_COMM_LEN]; u8 task_comm[TASK_COMM_LEN];
u32 task_flags; u32 task_flags;
u64 mm_brk;
};
u8 __core_pad[CKPT_CORE_SIZE];
};
} __packed; } __packed;
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
......
...@@ -30,7 +30,7 @@ void *mmap_seized(pid_t pid, user_regs_struct_t *regs, ...@@ -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, int munmap_seized(pid_t pid, user_regs_struct_t *regs,
void *addr, size_t length); void *addr, size_t length);
int kill_seized(pid_t pid, user_regs_struct_t *where); 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, int syscall_seized(pid_t pid,
user_regs_struct_t *where, user_regs_struct_t *where,
......
...@@ -109,6 +109,7 @@ static long syscall6(int nr, unsigned long arg0, unsigned long arg1, ...@@ -109,6 +109,7 @@ static long syscall6(int nr, unsigned long arg0, unsigned long arg1,
#define __NR_mmap 9 #define __NR_mmap 9
#define __NR_mprotect 10 #define __NR_mprotect 10
#define __NR_munmap 11 #define __NR_munmap 11
#define __NR_brk 12
#define __NR_mincore 27 #define __NR_mincore 27
#define __NR_dup 32 #define __NR_dup 32
#define __NR_dup2 33 #define __NR_dup2 33
......
...@@ -27,16 +27,16 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> ...@@ -27,16 +27,16 @@ Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
arch/x86/include/asm/elf.h | 3 arch/x86/include/asm/elf.h | 3
arch/x86/include/asm/elf_ckpt.h | 80 ++++++++ arch/x86/include/asm/elf_ckpt.h | 80 ++++++++
arch/x86/kernel/Makefile | 2 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 ++ arch/x86/vdso/vma.c | 22 ++
fs/Kconfig.binfmt | 11 + fs/Kconfig.binfmt | 11 +
fs/Makefile | 1 fs/Makefile | 1
fs/binfmt_elf.c | 17 + fs/binfmt_elf.c | 17 +
fs/binfmt_elf_ckpt.c | 381 ++++++++++++++++++++++++++++++++++++++++ fs/binfmt_elf_ckpt.c | 378 ++++++++++++++++++++++++++++++++++++++++
fs/exec.c | 27 +- fs/exec.c | 27 +-
include/linux/binfmts.h | 1 include/linux/binfmts.h | 1
include/linux/elf_ckpt.h | 90 +++++++++ include/linux/elf_ckpt.h | 97 ++++++++++
12 files changed, 779 insertions(+), 12 deletions(-) 12 files changed, 788 insertions(+), 12 deletions(-)
Index: linux-2.6.git/arch/x86/include/asm/elf.h 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 ...@@ -154,7 +154,7 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
=================================================================== ===================================================================
--- /dev/null --- /dev/null
+++ linux-2.6.git/arch/x86/kernel/elf_ckpt.c +++ linux-2.6.git/arch/x86/kernel/elf_ckpt.c
@@ -0,0 +1,156 @@ @@ -0,0 +1,161 @@
+#include <linux/module.h> +#include <linux/module.h>
+#include <linux/kernel.h> +#include <linux/kernel.h>
+#include <linux/fs.h> +#include <linux/fs.h>
...@@ -208,6 +208,11 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c ...@@ -208,6 +208,11 @@ Index: linux-2.6.git/arch/x86/kernel/elf_ckpt.c
+ mm_segment_t old_fs; + mm_segment_t old_fs;
+ int i, ret; + 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(CKPT_GDT_ENTRY_TLS_ENTRIES != GDT_ENTRY_TLS_ENTRIES);
+ BUILD_BUG_ON(sizeof(struct ckpt_arch_entry) > CKPT_ARCH_SIZE); + 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 ...@@ -424,7 +429,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
=================================================================== ===================================================================
--- /dev/null --- /dev/null
+++ linux-2.6.git/fs/binfmt_elf_ckpt.c +++ linux-2.6.git/fs/binfmt_elf_ckpt.c
@@ -0,0 +1,381 @@ @@ -0,0 +1,378 @@
+#include <linux/module.h> +#include <linux/module.h>
+#include <linux/kernel.h> +#include <linux/kernel.h>
+#include <linux/fs.h> +#include <linux/fs.h>
...@@ -477,8 +482,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -477,8 +482,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ unsigned long map_addr; + unsigned long map_addr;
+ +
+ unsigned long start_code, end_code, start_data, end_data; + unsigned long start_code, end_code, start_data, end_data;
+ unsigned long start_brk, brk, start_stack; + unsigned long start_brk, start_stack;
+ unsigned long elf_bss, elf_brk;
+ +
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ unsigned long vdso = -1UL; + unsigned long vdso = -1UL;
...@@ -490,15 +494,13 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -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_TASK_COMM_LEN != TASK_COMM_LEN);
+ BUILD_BUG_ON(CKPT_PAGE_SIZE != PAGE_SIZE); + BUILD_BUG_ON(CKPT_PAGE_SIZE != PAGE_SIZE);
+ BUILD_BUG_ON(CKPT_CORE_SIZE != sizeof(*core_entry));
+ +
+ elf_phdr_core = NULL; + elf_phdr_core = NULL;
+ elf_phdr_pages = NULL; + elf_phdr_pages = NULL;
+ nr_vma_found = 0; + nr_vma_found = 0;
+ nr_vma_mapped = 0; + nr_vma_mapped = 0;
+ +
+ elf_bss = 0;
+ elf_brk = 0;
+
+ start_code = -1UL; + start_code = -1UL;
+ end_code = 0; + end_code = 0;
+ +
...@@ -507,7 +509,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -507,7 +509,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ +
+ start_stack = -1UL; + start_stack = -1UL;
+ start_brk = -1UL; + start_brk = -1UL;
+ brk = -1UL;
+ +
+ fa = flex_array_alloc(sizeof(vma_entry), elf_ex->e_phnum, GFP_KERNEL); + 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)) { + 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 ...@@ -589,8 +590,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ goto out; + goto out;
+ } + }
+ +
+ if (core_entry->header.version != CKPT_HEADER_VERSION || + if (core_entry->header.version != CKPT_HEADER_VERSION) {
+ core_entry->header.arch != CKPT_HEADER_ARCH_X86_64) {
+ pr_err("elf-ckpt: Unsupported or corrupted header\n"); + pr_err("elf-ckpt: Unsupported or corrupted header\n");
+ ret = -ENOEXEC; + ret = -ENOEXEC;
+ goto out; + goto out;
...@@ -604,7 +604,9 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -604,7 +604,9 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ current->flags |= PF_RANDOMIZE; + 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); + setup_new_exec(bprm);
+ +
...@@ -712,7 +714,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c ...@@ -712,7 +714,7 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c
+ current->mm->end_data = end_data; + current->mm->end_data = end_data;
+ current->mm->start_stack = start_stack; + current->mm->start_stack = start_stack;
+ current->mm->start_brk = start_brk; + current->mm->start_brk = start_brk;
+ current->mm->brk = brk; + current->mm->brk = core_entry->mm_brk;
+ +
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ ret = arch_setup_additional_pages_at(bprm, (void *)vdso, 0); + ret = arch_setup_additional_pages_at(bprm, (void *)vdso, 0);
...@@ -873,7 +875,7 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h ...@@ -873,7 +875,7 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
=================================================================== ===================================================================
--- /dev/null --- /dev/null
+++ linux-2.6.git/include/linux/elf_ckpt.h +++ linux-2.6.git/include/linux/elf_ckpt.h
@@ -0,0 +1,90 @@ @@ -0,0 +1,97 @@
+#ifndef _LINUX_ELF_CHECKPOINT_H +#ifndef _LINUX_ELF_CHECKPOINT_H
+#define _LINUX_ELF_CHECKPOINT_H +#define _LINUX_ELF_CHECKPOINT_H
+ +
...@@ -941,13 +943,20 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h ...@@ -941,13 +943,20 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h
+} __packed; +} __packed;
+ +
+#define CKPT_ARCH_SIZE 2048 +#define CKPT_ARCH_SIZE 2048
+#define CKPT_CORE_SIZE 8192
+ +
+struct core_entry { +struct core_entry {
+ union {
+ struct {
+ struct image_header header; + struct image_header header;
+ __u8 arch[CKPT_ARCH_SIZE]; /* should be enough for all archs */ + __u8 arch[CKPT_ARCH_SIZE]; /* should be enough for all archs */
+ __u32 task_personality; + __u32 task_personality;
+ __u8 task_comm[CKPT_TASK_COMM_LEN]; + __u8 task_comm[CKPT_TASK_COMM_LEN];
+ __u32 task_flags; + __u32 task_flags;
+ __u64 mm_brk;
+ };
+ __u8 __core_pad[CKPT_CORE_SIZE];
+ };
+} __packed; +} __packed;
+ +
+#ifdef CONFIG_BINFMT_ELF_CKPT +#ifdef CONFIG_BINFMT_ELF_CKPT
......
...@@ -100,6 +100,29 @@ int kill_seized(pid_t pid, user_regs_struct_t *where) ...@@ -100,6 +100,29 @@ int kill_seized(pid_t pid, user_regs_struct_t *where)
return ret; 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, int syscall_seized(pid_t pid,
user_regs_struct_t *where, user_regs_struct_t *where,
user_regs_struct_t *params, 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