diff --git a/cr-dump.c b/cr-dump.c index 288bc39b5..1eaa222bc 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -417,12 +417,19 @@ err: #define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e)) static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, - u64 *start_code, u64 *end_code) + u64 *start_code, u64 *end_code, + u64 *start_data, u64 *end_data, + u64 *start_stack, u64 *start_brk) { FILE *file = NULL; char *tok1, *tok2; int i, ret = -1; + /* + * NOTE: Be careful, /proc/$pid/stat has a parasite + * '0' symbol at argument 20 in format string. + */ + snprintf(loc_buf, sizeof(loc_buf), "/proc/%d/stat", pid); file = fopen(loc_buf, "r"); if (!file) { @@ -448,7 +455,7 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, if (!ret) { ret = -1; for (i = 0; i < 7; i++) { - tok1 = strtok(NULL, " "); + tok1 = strtok(NULL, " \n\t"); if (!tok1) goto err_corrupted; } @@ -458,22 +465,53 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, if (!ret) { ret = -1; - for (i = 0; i < 15; i++) { - tok1 = strtok(NULL, " "); + for (i = 0; i < 16; i++) { + tok1 = strtok(NULL, " \n\t"); if (!tok1) goto err_corrupted; } - tok1 = strtok(NULL, " "); + tok1 = strtok(NULL, " \n\t"); if (!tok1) goto err_corrupted; *start_code = atol(tok1); - tok1 = strtok(NULL, " "); + tok1 = strtok(NULL, " \n\t"); if (!tok1) goto err_corrupted; *end_code = atol(tok1); ret = 0; + + tok1 = strtok(NULL, " \n\t"); + if (!tok1) + goto err_corrupted; + *start_stack = atol(tok1); + ret = 0; + } + + if (!ret) { + ret = -1; + for (i = 0; i < 16; i++) { + tok1 = strtok(NULL, " \n\t"); + if (!tok1) + goto err_corrupted; + } + + tok1 = strtok(NULL, " \n\t"); + if (!tok1) + goto err_corrupted; + *start_data = atol(tok1); + + tok1 = strtok(NULL, " \n\t"); + if (!tok1) + goto err_corrupted; + *end_data = atol(tok1); + + tok1 = strtok(NULL, " \n\t"); + if (!tok1) + goto err_corrupted; + *start_brk = atol(tok1); + ret = 0; } err: @@ -645,7 +683,11 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset) ret = get_task_stat(pid, core->task_comm, &core->task_flags, &core->mm_start_code, - &core->mm_end_code); + &core->mm_end_code, + &core->mm_start_data, + &core->mm_end_data, + &core->mm_start_stack, + &core->mm_start_brk); if (ret) goto err_free; pr_info("OK\n"); diff --git a/cr-show.c b/cr-show.c index 1079254c8..48d2feed1 100644 --- a/cr-show.c +++ b/cr-show.c @@ -108,6 +108,7 @@ static void show_core_rest(struct cr_fdset *cr_fdset) u32 personality; char comm[TASK_COMM_LEN]; u64 mm_brk, mm_start_code, mm_end_code; + u64 mm_start_data, mm_end_data, mm_start_stack, mm_start_brk; fd_core = cr_fdset->desc[CR_FD_CORE].fd; if (fd_core < 0) @@ -128,11 +129,28 @@ static void show_core_rest(struct cr_fdset *cr_fdset) lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_end_code), SEEK_SET); read_ptr_safe(fd_core, &mm_end_code, err); - pr_info("Personality: %x\n", personality); - pr_info("Command: %s\n", comm); - pr_info("Brk: %lx\n", mm_brk); - pr_info("Start code: %lx\n", mm_start_code); - pr_info("End code: %lx\n", mm_end_code); + lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_start_stack), SEEK_SET); + read_ptr_safe(fd_core, &mm_start_stack, err); + + lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_start_data), SEEK_SET); + read_ptr_safe(fd_core, &mm_start_data, err); + + lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_end_data), SEEK_SET); + read_ptr_safe(fd_core, &mm_end_data, err); + + lseek(fd_core, GET_FILE_OFF(struct core_entry, mm_start_brk), SEEK_SET); + read_ptr_safe(fd_core, &mm_start_brk, err); + + pr_info("Personality: %x\n", personality); + pr_info("Command: %s\n", comm); + pr_info("Brk: %lx\n", mm_brk); + pr_info("Start code: %lx\n", mm_start_code); + pr_info("End code: %lx\n", mm_end_code); + pr_info("Start stack: %lx\n", mm_end_code); + pr_info("Start data: %lx\n", mm_end_code); + pr_info("End data: %lx\n", mm_end_code); + pr_info("Start brk: %lx\n", mm_end_code); + err: return; } diff --git a/include/image.h b/include/image.h index c3147d44d..7eca80161 100644 --- a/include/image.h +++ b/include/image.h @@ -167,8 +167,8 @@ struct ckpt_arch_entry { struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; }; -#define CKPT_ARCH_SIZE 2048 -#define CKPT_CORE_SIZE 8192 +#define CKPT_ARCH_SIZE (2 * 4096) +#define CKPT_CORE_SIZE (4 * 4096) struct core_entry { union { @@ -181,9 +181,13 @@ struct core_entry { u32 task_personality; u8 task_comm[TASK_COMM_LEN]; u32 task_flags; - u64 mm_brk; u64 mm_start_code; u64 mm_end_code; + u64 mm_start_data; + u64 mm_end_data; + u64 mm_start_stack; + u64 mm_start_brk; + u64 mm_brk; }; u8 __core_pad[CKPT_CORE_SIZE]; }; diff --git a/kernel/binfmt-elf-for-cr-5 b/kernel/binfmt-elf-for-cr-5 index a87a35c54..cec8d4803 100644 --- a/kernel/binfmt-elf-for-cr-5 +++ b/kernel/binfmt-elf-for-cr-5 @@ -25,18 +25,19 @@ v2: (from Andrew Vagin) Signed-off-by: Cyrill Gorcunov --- 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/elf_ckpt.c | 161 ++++++++++++++++ + 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 | 389 ++++++++++++++++++++++++++++++++++++++++ - fs/exec.c | 27 +- + fs/binfmt_elf.c | 17 +- + fs/binfmt_elf_ckpt.c | 332 ++++++++++++++++++++++++++++++++++++++++ + fs/exec.c | 27 ++- + fs/proc/array.c | 7 include/linux/binfmts.h | 1 - include/linux/elf_ckpt.h | 99 ++++++++++ - 12 files changed, 801 insertions(+), 12 deletions(-) + include/linux/elf_ckpt.h | 103 ++++++++++++ + 13 files changed, 753 insertions(+), 14 deletions(-) Index: linux-2.6.git/arch/x86/include/asm/elf.h =================================================================== @@ -429,7 +430,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,389 @@ +@@ -0,0 +1,332 @@ +#include +#include +#include @@ -481,9 +482,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c + struct file *file = NULL; + unsigned long map_addr; + -+ unsigned long start_code, end_code, start_data, end_data; -+ unsigned long start_brk, start_stack; -+ +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES + unsigned long vdso = -1UL; +#endif @@ -501,15 +499,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c + nr_vma_found = 0; + nr_vma_mapped = 0; + -+ start_code = -1UL; -+ end_code = 0; -+ -+ start_data = -1UL; -+ end_data = 0; -+ -+ start_stack = -1UL; -+ start_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)) { + ret = -ENOMEM; @@ -616,14 +605,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c + for (i = 0; i < nr_vma_found; i++) { + vma_entry_ptr = flex_array_get(fa, i); + -+ /* -+ * This [heap] area is not explicitly existing on old kernels -+ * so if it's not found we need to setup brk area from saved -+ * brk value. -+ */ -+ if (vma_entry_ptr->status & VMA_AREA_HEAP) -+ start_brk = vma_entry_ptr->start; -+ +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES + if (vma_entry_ptr->status & VMA_AREA_VDSO) + vdso = vma_entry_ptr->start; @@ -665,37 +646,6 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c + goto out_unmap; + } + -+ /* -+ * Some heuristics to guess previously loaded real -+ * elf file structure. Probably this things should -+ * be exported via /proc somewhere instead. -+ */ -+ -+ if (vma_entry_ptr->status & VMA_AREA_STACK) { -+ /* Note if stack is VM_GROWSUP -- it should be reversed */ -+ start_stack = vma_entry_ptr->start; -+ } -+ -+ if (vma_entry_ptr->prot & PROT_EXEC) { -+ if (start_code > vma_entry_ptr->start) -+ start_code = vma_entry_ptr->start; -+ if (end_code < vma_entry_ptr->end) -+ end_code = vma_entry_ptr->end; -+ } else { -+ /* -+ * Neither .bss nor .data was being file mapped. -+ * FIXME: .rodata are loaded by interp. -+ */ -+ if (!file) { -+ if (vma_entry_ptr->prot & (PROT_WRITE)) { -+ if (start_data > vma_entry_ptr->start) -+ start_data = vma_entry_ptr->start; -+ if (end_data < vma_entry_ptr->end) -+ end_data = vma_entry_ptr->end; -+ } -+ } -+ } -+ + nr_vma_mapped++; + } + @@ -711,20 +661,14 @@ Index: linux-2.6.git/fs/binfmt_elf_ckpt.c + /* The name it has before */ + set_task_comm(current, core_entry->task_comm); + -+ bprm->p = start_stack; -+ -+ if (start_brk == -1UL) { -+ pr_err("elf-ckpt: Can't find brk area\n"); -+ ret = -ENOEXEC; -+ goto out_unmap; -+ } ++ bprm->p = core_entry->mm_start_stack; + + current->mm->start_code = core_entry->mm_start_code; + current->mm->end_code = core_entry->mm_end_code; -+ current->mm->start_data = start_data; -+ current->mm->end_data = end_data; -+ current->mm->start_stack = start_stack; -+ current->mm->start_brk = start_brk; ++ current->mm->start_data = core_entry->mm_start_data; ++ current->mm->end_data = core_entry->mm_end_data; ++ current->mm->start_stack = core_entry->mm_start_stack; ++ current->mm->start_brk = core_entry->mm_start_brk; + current->mm->brk = core_entry->mm_brk; + +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES @@ -870,6 +814,31 @@ Index: linux-2.6.git/fs/exec.c EXPORT_SYMBOL(flush_old_exec); void would_dump(struct linux_binprm *bprm, struct file *file) +Index: linux-2.6.git/fs/proc/array.c +=================================================================== +--- linux-2.6.git.orig/fs/proc/array.c ++++ linux-2.6.git/fs/proc/array.c +@@ -478,7 +478,7 @@ static int do_task_stat(struct seq_file + + seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \ + %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ +-%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", ++%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n", + pid_nr_ns(pid, ns), + tcomm, + state, +@@ -525,7 +525,10 @@ static int do_task_stat(struct seq_file + task->policy, + (unsigned long long)delayacct_blkio_ticks(task), + cputime_to_clock_t(gtime), +- cputime_to_clock_t(cgtime)); ++ cputime_to_clock_t(cgtime), ++ mm ? (permitted ? mm->start_data : 1) : 0, ++ mm ? (permitted ? mm->end_data : 1) : 0, ++ mm ? (permitted ? mm->start_brk : 1) : 0); + if (mm) + mmput(mm); + return 0; Index: linux-2.6.git/include/linux/binfmts.h =================================================================== --- linux-2.6.git.orig/include/linux/binfmts.h @@ -886,7 +855,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,99 @@ +@@ -0,0 +1,103 @@ +#ifndef _LINUX_ELF_CHECKPOINT_H +#define _LINUX_ELF_CHECKPOINT_H + @@ -953,8 +922,8 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h + __u32 flags; +} __packed; + -+#define CKPT_ARCH_SIZE 2048 -+#define CKPT_CORE_SIZE 8192 ++#define CKPT_ARCH_SIZE (2 * 4096) ++#define CKPT_CORE_SIZE (4 * 4096) + +struct core_entry { + union { @@ -964,9 +933,13 @@ Index: linux-2.6.git/include/linux/elf_ckpt.h + __u32 task_personality; + __u8 task_comm[CKPT_TASK_COMM_LEN]; + __u32 task_flags; -+ __u64 mm_brk; + __u64 mm_start_code; + __u64 mm_end_code; ++ __u64 mm_start_data; ++ __u64 mm_end_data; ++ __u64 mm_start_stack; ++ __u64 mm_start_brk; ++ __u64 mm_brk; + }; + __u8 __core_pad[CKPT_CORE_SIZE]; + };