From 9999e48639b3cecb08ffb37358bcba3b48161b29 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 08:50:17 +0000 Subject: [PATCH] add ax88772_rst --- kernel/fs/binfmt_elf_fdpic.c | 443 +++++++++++++++++++------------------------------------ 1 files changed, 152 insertions(+), 291 deletions(-) diff --git a/kernel/fs/binfmt_elf_fdpic.c b/kernel/fs/binfmt_elf_fdpic.c index b53bb37..f4f146f 100644 --- a/kernel/fs/binfmt_elf_fdpic.c +++ b/kernel/fs/binfmt_elf_fdpic.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* binfmt_elf_fdpic.c: FDPIC ELF binary format * * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * Derived from binfmt_elf.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. */ #include <linux/module.h> @@ -39,10 +35,10 @@ #include <linux/elfcore.h> #include <linux/coredump.h> #include <linux/dax.h> +#include <linux/regset.h> #include <linux/uaccess.h> #include <asm/param.h> -#include <asm/pgalloc.h> typedef char *elf_caddr_t; @@ -342,17 +338,16 @@ interp_params.flags |= ELF_FDPIC_FLAG_CONSTDISP; /* flush all traces of the currently running executable */ - retval = flush_old_exec(bprm); + retval = begin_new_exec(bprm); if (retval) goto error; /* there's now no turning back... the old userspace image is dead, * defunct, deceased, etc. */ + SET_PERSONALITY(exec_params.hdr); if (elf_check_fdpic(&exec_params.hdr)) - set_personality(PER_LINUX_FDPIC); - else - set_personality(PER_LINUX); + current->personality |= PER_LINUX_FDPIC; if (elf_read_implies_exec(&exec_params.hdr, executable_stack)) current->personality |= READ_IMPLIES_EXEC; @@ -438,9 +433,9 @@ current->mm->start_stack = current->mm->start_brk + stack_size; #endif - install_exec_creds(bprm); - if (create_elf_fdpic_tables(bprm, current->mm, - &exec_params, &interp_params) < 0) + retval = create_elf_fdpic_tables(bprm, current->mm, &exec_params, + &interp_params); + if (retval < 0) goto error; kdebug("- start_code %lx", current->mm->start_code); @@ -541,7 +536,7 @@ platform_len = strlen(k_platform) + 1; sp -= platform_len; u_platform = (char __user *) sp; - if (__copy_to_user(u_platform, k_platform, platform_len) != 0) + if (copy_to_user(u_platform, k_platform, platform_len) != 0) return -EFAULT; } @@ -556,7 +551,7 @@ platform_len = strlen(k_base_platform) + 1; sp -= platform_len; u_base_platform = (char __user *) sp; - if (__copy_to_user(u_base_platform, k_base_platform, platform_len) != 0) + if (copy_to_user(u_base_platform, k_base_platform, platform_len) != 0) return -EFAULT; } @@ -593,7 +588,7 @@ nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) + (k_base_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH; - if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) + if (bprm->have_execfd) nitems++; csp = sp; @@ -608,11 +603,13 @@ /* put the ELF interpreter info on the stack */ #define NEW_AUX_ENT(id, val) \ do { \ - struct { unsigned long _id, _val; } __user *ent; \ + struct { unsigned long _id, _val; } __user *ent, v; \ \ ent = (void __user *) csp; \ - __put_user((id), &ent[nr]._id); \ - __put_user((val), &ent[nr]._val); \ + v._id = (id); \ + v._val = (val); \ + if (copy_to_user(ent + nr, &v, sizeof(v))) \ + return -EFAULT; \ nr++; \ } while (0) @@ -633,10 +630,10 @@ (elf_addr_t) (unsigned long) u_base_platform); } - if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { + if (bprm->have_execfd) { nr = 0; csp -= 2 * sizeof(unsigned long); - NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); + NEW_AUX_ENT(AT_EXECFD, bprm->execfd); } nr = 0; @@ -679,7 +676,8 @@ /* stack argc */ csp -= sizeof(unsigned long); - __put_user(bprm->argc, (unsigned long __user *) csp); + if (put_user(bprm->argc, (unsigned long __user *) csp)) + return -EFAULT; BUG_ON(csp != sp); @@ -693,25 +691,29 @@ p = (char __user *) current->mm->arg_start; for (loop = bprm->argc; loop > 0; loop--) { - __put_user((elf_caddr_t) p, argv++); + if (put_user((elf_caddr_t) p, argv++)) + return -EFAULT; len = strnlen_user(p, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) return -EINVAL; p += len; } - __put_user(NULL, argv); + if (put_user(NULL, argv)) + return -EFAULT; current->mm->arg_end = (unsigned long) p; /* fill in the envv[] array */ current->mm->env_start = (unsigned long) p; for (loop = bprm->envc; loop > 0; loop--) { - __put_user((elf_caddr_t)(unsigned long) p, envp++); + if (put_user((elf_caddr_t)(unsigned long) p, envp++)) + return -EFAULT; len = strnlen_user(p, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) return -EINVAL; p += len; } - __put_user(NULL, envp); + if (put_user(NULL, envp)) + return -EFAULT; current->mm->env_end = (unsigned long) p; mm->start_stack = (unsigned long) sp; @@ -853,8 +855,8 @@ tmp = phdr->p_memsz / sizeof(Elf32_Dyn); dyn = (Elf32_Dyn __user *)params->dynamic_addr; - __get_user(d_tag, &dyn[tmp - 1].d_tag); - if (d_tag != 0) + if (get_user(d_tag, &dyn[tmp - 1].d_tag) || + d_tag != 0) goto dynamic_error; break; } @@ -1187,75 +1189,31 @@ */ #ifdef CONFIG_ELF_CORE -/* - * Decide whether a segment is worth dumping; default is yes to be - * sure (missing info is worse than too much; etc). - * Personally I'd include everything, and use the coredump limit... - * - * I think we should skip something. But I am not sure how. H.J. - */ -static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) +struct elf_prstatus_fdpic { - int dump_ok; - - /* Do not dump I/O mapped devices or special mappings */ - if (vma->vm_flags & VM_IO) { - kdcore("%08lx: %08lx: no (IO)", vma->vm_start, vma->vm_flags); - return 0; - } - - /* If we may not read the contents, don't allow us to dump - * them either. "dump_write()" can't handle it anyway. + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned long pr_sigpend; /* Set of pending signals */ + unsigned long pr_sighold; /* Set of held signals */ + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct __kernel_old_timeval pr_utime; /* User time */ + struct __kernel_old_timeval pr_stime; /* System time */ + struct __kernel_old_timeval pr_cutime; /* Cumulative user time */ + struct __kernel_old_timeval pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + /* When using FDPIC, the loadmap addresses need to be communicated + * to GDB in order for GDB to do the necessary relocations. The + * fields (below) used to communicate this information are placed + * immediately after ``pr_reg'', so that the loadmap addresses may + * be viewed as part of the register set if so desired. */ - if (!(vma->vm_flags & VM_READ)) { - kdcore("%08lx: %08lx: no (!read)", vma->vm_start, vma->vm_flags); - return 0; - } - - /* support for DAX */ - if (vma_is_dax(vma)) { - if (vma->vm_flags & VM_SHARED) { - dump_ok = test_bit(MMF_DUMP_DAX_SHARED, &mm_flags); - kdcore("%08lx: %08lx: %s (DAX shared)", vma->vm_start, - vma->vm_flags, dump_ok ? "yes" : "no"); - } else { - dump_ok = test_bit(MMF_DUMP_DAX_PRIVATE, &mm_flags); - kdcore("%08lx: %08lx: %s (DAX private)", vma->vm_start, - vma->vm_flags, dump_ok ? "yes" : "no"); - } - return dump_ok; - } - - /* By default, dump shared memory if mapped from an anonymous file. */ - if (vma->vm_flags & VM_SHARED) { - if (file_inode(vma->vm_file)->i_nlink == 0) { - dump_ok = test_bit(MMF_DUMP_ANON_SHARED, &mm_flags); - kdcore("%08lx: %08lx: %s (share)", vma->vm_start, - vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; - } - - dump_ok = test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags); - kdcore("%08lx: %08lx: %s (share)", vma->vm_start, - vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; - } - -#ifdef CONFIG_MMU - /* By default, if it hasn't been written to, don't write it out */ - if (!vma->anon_vma) { - dump_ok = test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags); - kdcore("%08lx: %08lx: %s (!anon)", vma->vm_start, - vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; - } -#endif - - dump_ok = test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags); - kdcore("%08lx: %08lx: %s", vma->vm_start, vma->vm_flags, - dump_ok ? "yes" : "no"); - return dump_ok; -} + unsigned long pr_exec_fdpic_loadmap; + unsigned long pr_interp_fdpic_loadmap; + int pr_fpvalid; /* True if math co-processor being used. */ +}; /* An ELF note in memory */ struct memelfnote @@ -1343,7 +1301,7 @@ * fill up all the fields in prstatus from the given task struct, except * registers which need to be filled up separately. */ -static void fill_prstatus(struct elf_prstatus *prstatus, +static void fill_prstatus(struct elf_prstatus_fdpic *prstatus, struct task_struct *p, long signr) { prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; @@ -1363,17 +1321,17 @@ * group-wide total, not its individual thread total. */ thread_group_cputime(p, &cputime); - prstatus->pr_utime = ns_to_timeval(cputime.utime); - prstatus->pr_stime = ns_to_timeval(cputime.stime); + prstatus->pr_utime = ns_to_kernel_old_timeval(cputime.utime); + prstatus->pr_stime = ns_to_kernel_old_timeval(cputime.stime); } else { u64 utime, stime; task_cputime(p, &utime, &stime); - prstatus->pr_utime = ns_to_timeval(utime); - prstatus->pr_stime = ns_to_timeval(stime); + prstatus->pr_utime = ns_to_kernel_old_timeval(utime); + prstatus->pr_stime = ns_to_kernel_old_timeval(stime); } - prstatus->pr_cutime = ns_to_timeval(p->signal->cutime); - prstatus->pr_cstime = ns_to_timeval(p->signal->cstime); + prstatus->pr_cutime = ns_to_kernel_old_timeval(p->signal->cutime); + prstatus->pr_cstime = ns_to_kernel_old_timeval(p->signal->cstime); prstatus->pr_exec_fdpic_loadmap = p->mm->context.exec_fdpic_loadmap; prstatus->pr_interp_fdpic_loadmap = p->mm->context.interp_fdpic_loadmap; @@ -1425,14 +1383,10 @@ /* Here is the structure in which status of each thread is captured. */ struct elf_thread_status { - struct list_head list; - struct elf_prstatus prstatus; /* NT_PRSTATUS */ + struct elf_thread_status *next; + struct elf_prstatus_fdpic prstatus; /* NT_PRSTATUS */ elf_fpregset_t fpu; /* NT_PRFPREG */ - struct task_struct *thread; -#ifdef ELF_CORE_COPY_XFPREGS - elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ -#endif - struct memelfnote notes[3]; + struct memelfnote notes[2]; int num_notes; }; @@ -1441,38 +1395,44 @@ * we need to keep a linked list of every thread's pr_status and then create * a single section for them in the final core file. */ -static int elf_dump_thread_status(long signr, struct elf_thread_status *t) +static struct elf_thread_status *elf_dump_thread_status(long signr, struct task_struct *p, int *sz) { - struct task_struct *p = t->thread; - int sz = 0; + const struct user_regset_view *view = task_user_regset_view(p); + struct elf_thread_status *t; + int i, ret; - t->num_notes = 0; + t = kzalloc(sizeof(struct elf_thread_status), GFP_KERNEL); + if (!t) + return t; fill_prstatus(&t->prstatus, p, signr); - elf_core_copy_task_regs(p, &t->prstatus.pr_reg); + regset_get(p, &view->regsets[0], + sizeof(t->prstatus.pr_reg), &t->prstatus.pr_reg); fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &t->prstatus); t->num_notes++; - sz += notesize(&t->notes[0]); + *sz += notesize(&t->notes[0]); - t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu); + for (i = 1; i < view->n; ++i) { + const struct user_regset *regset = &view->regsets[i]; + if (regset->core_note_type != NT_PRFPREG) + continue; + if (regset->active && regset->active(p, regset) <= 0) + continue; + ret = regset_get(p, regset, sizeof(t->fpu), &t->fpu); + if (ret >= 0) + t->prstatus.pr_fpvalid = 1; + break; + } + if (t->prstatus.pr_fpvalid) { fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &t->fpu); t->num_notes++; - sz += notesize(&t->notes[1]); + *sz += notesize(&t->notes[1]); } - -#ifdef ELF_CORE_COPY_XFPREGS - if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { - fill_note(&t->notes[2], "LINUX", ELF_CORE_XFPREG_TYPE, - sizeof(t->xfpu), &t->xfpu); - t->num_notes++; - sz += notesize(&t->notes[2]); - } -#endif - return sz; + return t; } static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, @@ -1494,52 +1454,19 @@ /* * dump the segments for an MMU process */ -static bool elf_fdpic_dump_segments(struct coredump_params *cprm) +static bool elf_fdpic_dump_segments(struct coredump_params *cprm, + struct core_vma_metadata *vma_meta, + int vma_count) { - struct vm_area_struct *vma; + int i; - for (vma = current->mm->mmap; vma; vma = vma->vm_next) { -#ifdef CONFIG_MMU - unsigned long addr; -#endif + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; - if (!maydump(vma, cprm->mm_flags)) - continue; - -#ifdef CONFIG_MMU - for (addr = vma->vm_start; addr < vma->vm_end; - addr += PAGE_SIZE) { - bool res; - struct page *page = get_dump_page(addr); - if (page) { - void *kaddr = kmap(page); - res = dump_emit(cprm, kaddr, PAGE_SIZE); - kunmap(page); - put_page(page); - } else { - res = dump_skip(cprm, PAGE_SIZE); - } - if (!res) - return false; - } -#else - if (!dump_emit(cprm, (void *) vma->vm_start, - vma->vm_end - vma->vm_start)) + if (!dump_user_range(cprm, meta->start, meta->dump_size)) return false; -#endif } return true; -} - -static size_t elf_core_vma_data_size(unsigned long mm_flags) -{ - struct vm_area_struct *vma; - size_t size = 0; - - for (vma = current->mm->mmap; vma; vma = vma->vm_next) - if (maydump(vma, mm_flags)) - size += vma->vm_end - vma->vm_start; - return size; } /* @@ -1551,24 +1478,14 @@ */ static int elf_fdpic_core_dump(struct coredump_params *cprm) { -#define NUM_NOTES 6 int has_dumped = 0; - mm_segment_t fs; - int segs; + int vma_count, segs; int i; - struct vm_area_struct *vma; struct elfhdr *elf = NULL; loff_t offset = 0, dataoff; - int numnote; - struct memelfnote *notes = NULL; - struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ + struct memelfnote psinfo_note, auxv_note; struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ - LIST_HEAD(thread_list); - struct list_head *t; - elf_fpregset_t *fpu = NULL; -#ifdef ELF_CORE_COPY_XFPREGS - elf_fpxregset_t *xfpu = NULL; -#endif + struct elf_thread_status *thread_list = NULL; int thread_status_size = 0; elf_addr_t *auxv; struct elf_phdr *phdr4note = NULL; @@ -1577,67 +1494,40 @@ elf_addr_t e_shoff; struct core_thread *ct; struct elf_thread_status *tmp; - - /* - * We no longer stop all VM operations. - * - * This is because those proceses that could possibly change map_count - * or the mmap / vma pages are now blocked in do_exit on current - * finishing this core dump. - * - * Only ptrace can touch these memory addresses, but it doesn't change - * the map_count or the pages allocated. So no possibility of crashing - * exists while dumping the mm->vm_next areas to the core file. - */ + struct core_vma_metadata *vma_meta = NULL; + size_t vma_data_size; /* alloc memory for large data structures: too large to be on stack */ elf = kmalloc(sizeof(*elf), GFP_KERNEL); if (!elf) - goto cleanup; - prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL); - if (!prstatus) - goto cleanup; + goto end_coredump; psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); if (!psinfo) - goto cleanup; - notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote), - GFP_KERNEL); - if (!notes) - goto cleanup; - fpu = kmalloc(sizeof(*fpu), GFP_KERNEL); - if (!fpu) - goto cleanup; -#ifdef ELF_CORE_COPY_XFPREGS - xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL); - if (!xfpu) - goto cleanup; -#endif + goto end_coredump; + + if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, &vma_data_size)) + goto end_coredump; for (ct = current->mm->core_state->dumper.next; ct; ct = ct->next) { - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + tmp = elf_dump_thread_status(cprm->siginfo->si_signo, + ct->task, &thread_status_size); if (!tmp) - goto cleanup; + goto end_coredump; - tmp->thread = ct->task; - list_add(&tmp->list, &thread_list); - } - - list_for_each(t, &thread_list) { - struct elf_thread_status *tmp; - int sz; - - tmp = list_entry(t, struct elf_thread_status, list); - sz = elf_dump_thread_status(cprm->siginfo->si_signo, tmp); - thread_status_size += sz; + tmp->next = thread_list; + thread_list = tmp; } /* now collect the dump for the current */ - fill_prstatus(prstatus, current, cprm->siginfo->si_signo); - elf_core_copy_regs(&prstatus->pr_reg, cprm->regs); + tmp = elf_dump_thread_status(cprm->siginfo->si_signo, + current, &thread_status_size); + if (!tmp) + goto end_coredump; + tmp->next = thread_list; + thread_list = tmp; - segs = current->mm->map_count; - segs += elf_core_extra_phdrs(); + segs = vma_count + elf_core_extra_phdrs(); /* for notes section */ segs++; @@ -1656,59 +1546,33 @@ * with info from their /proc. */ - fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); fill_psinfo(psinfo, current->group_leader, current->mm); - fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); - - numnote = 2; + fill_note(&psinfo_note, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); + thread_status_size += notesize(&psinfo_note); auxv = (elf_addr_t *) current->mm->saved_auxv; - i = 0; do i += 2; while (auxv[i - 2] != AT_NULL); - fill_note(¬es[numnote++], "CORE", NT_AUXV, - i * sizeof(elf_addr_t), auxv); + fill_note(&auxv_note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); + thread_status_size += notesize(&auxv_note); - /* Try to dump the FPU. */ - if ((prstatus->pr_fpvalid = - elf_core_copy_task_fpregs(current, cprm->regs, fpu))) - fill_note(notes + numnote++, - "CORE", NT_PRFPREG, sizeof(*fpu), fpu); -#ifdef ELF_CORE_COPY_XFPREGS - if (elf_core_copy_task_xfpregs(current, xfpu)) - fill_note(notes + numnote++, - "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu); -#endif - - fs = get_fs(); - set_fs(KERNEL_DS); - - offset += sizeof(*elf); /* Elf header */ + offset = sizeof(*elf); /* Elf header */ offset += segs * sizeof(struct elf_phdr); /* Program headers */ /* Write notes phdr entry */ - { - int sz = 0; + phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); + if (!phdr4note) + goto end_coredump; - for (i = 0; i < numnote; i++) - sz += notesize(notes + i); - - sz += thread_status_size; - - phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); - if (!phdr4note) - goto end_coredump; - - fill_elf_note_phdr(phdr4note, sz, offset); - offset += sz; - } + fill_elf_note_phdr(phdr4note, thread_status_size, offset); + offset += thread_status_size; /* Page-align dumped data */ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); - offset += elf_core_vma_data_size(cprm->mm_flags); + offset += vma_data_size; offset += elf_core_extra_data_size(); e_shoff = offset; @@ -1728,23 +1592,26 @@ goto end_coredump; /* write program headers for segments dump */ - for (vma = current->mm->mmap; vma; vma = vma->vm_next) { + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; struct elf_phdr phdr; size_t sz; - sz = vma->vm_end - vma->vm_start; + sz = meta->end - meta->start; phdr.p_type = PT_LOAD; phdr.p_offset = offset; - phdr.p_vaddr = vma->vm_start; + phdr.p_vaddr = meta->start; phdr.p_paddr = 0; - phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0; + phdr.p_filesz = meta->dump_size; phdr.p_memsz = sz; offset += phdr.p_filesz; - phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; - if (vma->vm_flags & VM_WRITE) + phdr.p_flags = 0; + if (meta->flags & VM_READ) + phdr.p_flags |= PF_R; + if (meta->flags & VM_WRITE) phdr.p_flags |= PF_W; - if (vma->vm_flags & VM_EXEC) + if (meta->flags & VM_EXEC) phdr.p_flags |= PF_X; phdr.p_align = ELF_EXEC_PAGESIZE; @@ -1756,15 +1623,18 @@ goto end_coredump; /* write out the notes section */ - for (i = 0; i < numnote; i++) - if (!writenote(notes + i, cprm)) + if (!writenote(thread_list->notes, cprm)) + goto end_coredump; + if (!writenote(&psinfo_note, cprm)) + goto end_coredump; + if (!writenote(&auxv_note, cprm)) + goto end_coredump; + for (i = 1; i < thread_list->num_notes; i++) + if (!writenote(thread_list->notes + i, cprm)) goto end_coredump; /* write out the thread status notes section */ - list_for_each(t, &thread_list) { - struct elf_thread_status *tmp = - list_entry(t, struct elf_thread_status, list); - + for (tmp = thread_list->next; tmp; tmp = tmp->next) { for (i = 0; i < tmp->num_notes; i++) if (!writenote(&tmp->notes[i], cprm)) goto end_coredump; @@ -1773,7 +1643,7 @@ if (!dump_skip(cprm, dataoff - cprm->pos)) goto end_coredump; - if (!elf_fdpic_dump_segments(cprm)) + if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count)) goto end_coredump; if (!elf_core_write_extra_data(cprm)) @@ -1792,26 +1662,17 @@ } end_coredump: - set_fs(fs); - -cleanup: - while (!list_empty(&thread_list)) { - struct list_head *tmp = thread_list.next; - list_del(tmp); - kfree(list_entry(tmp, struct elf_thread_status, list)); + while (thread_list) { + tmp = thread_list; + thread_list = thread_list->next; + kfree(tmp); } + kvfree(vma_meta); kfree(phdr4note); kfree(elf); - kfree(prstatus); kfree(psinfo); - kfree(notes); - kfree(fpu); kfree(shdr4extnum); -#ifdef ELF_CORE_COPY_XFPREGS - kfree(xfpu); -#endif return has_dumped; -#undef NUM_NOTES } #endif /* CONFIG_ELF_CORE */ -- Gitblit v1.6.2