git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[safe/jmp/linux-2.6]
/
fs
/
binfmt_elf_fdpic.c
diff --git
a/fs/binfmt_elf_fdpic.c
b/fs/binfmt_elf_fdpic.c
index
5810aa1
..
d051a32
100644
(file)
--- a/
fs/binfmt_elf_fdpic.c
+++ b/
fs/binfmt_elf_fdpic.c
@@
-30,7
+30,6
@@
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/init.h>
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
#include <linux/elf.h>
#include <linux/elf-fdpic.h>
#include <linux/elfcore.h>
#include <linux/elf.h>
#include <linux/elf-fdpic.h>
#include <linux/elfcore.h>
@@
-76,7
+75,7
@@
static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
struct file *, struct mm_struct *);
#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
struct file *, struct mm_struct *);
#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *);
+static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *
, unsigned long limit
);
#endif
static struct linux_binfmt elf_fdpic_format = {
#endif
static struct linux_binfmt elf_fdpic_format = {
@@
-137,8
+136,8
@@
static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
retval = kernel_read(file, params->hdr.e_phoff,
(char *) params->phdrs, size);
retval = kernel_read(file, params->hdr.e_phoff,
(char *) params->phdrs, size);
- if (
retval < 0
)
- return retval;
+ if (
unlikely(retval != size)
)
+ return retval
< 0 ? retval : -ENOEXEC
;
/* determine stack size for this binary */
phdr = params->phdrs;
/* determine stack size for this binary */
phdr = params->phdrs;
@@
-179,6
+178,8
@@
static int load_elf_fdpic_binary(struct linux_binprm *bprm,
int executable_stack;
int retval, i;
int executable_stack;
int retval, i;
+ kdebug("____ LOAD %d ____", current->pid);
+
memset(&exec_params, 0, sizeof(exec_params));
memset(&interp_params, 0, sizeof(interp_params));
memset(&exec_params, 0, sizeof(exec_params));
memset(&interp_params, 0, sizeof(interp_params));
@@
-217,8
+218,11
@@
static int load_elf_fdpic_binary(struct linux_binprm *bprm,
phdr->p_offset,
interpreter_name,
phdr->p_filesz);
phdr->p_offset,
interpreter_name,
phdr->p_filesz);
- if (retval < 0)
+ if (unlikely(retval != phdr->p_filesz)) {
+ if (retval >= 0)
+ retval = -ENOEXEC;
goto error;
goto error;
+ }
retval = -ENOENT;
if (interpreter_name[phdr->p_filesz - 1] != '\0')
retval = -ENOENT;
if (interpreter_name[phdr->p_filesz - 1] != '\0')
@@
-244,8
+248,11
@@
static int load_elf_fdpic_binary(struct linux_binprm *bprm,
retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
- if (retval < 0)
+ if (unlikely(retval != BINPRM_BUF_SIZE)) {
+ if (retval >= 0)
+ retval = -ENOEXEC;
goto error;
goto error;
+ }
interp_params.hdr = *((struct elfhdr *) bprm->buf);
break;
interp_params.hdr = *((struct elfhdr *) bprm->buf);
break;
@@
-383,7
+390,7
@@
static int load_elf_fdpic_binary(struct linux_binprm *bprm,
}
/* expand the stack mapping to use up the entire allocation granule */
}
/* expand the stack mapping to use up the entire allocation granule */
- fullsize = ksize((char *) current->mm->start_brk);
+ fullsize = k
obj
size((char *) current->mm->start_brk);
if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size,
fullsize, 0, 0)))
stack_size = fullsize;
if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size,
fullsize, 0, 0)))
stack_size = fullsize;
@@
-620,8
+627,8
@@
static int create_elf_fdpic_tables(struct linux_binprm *bprm,
p = (char __user *) current->mm->arg_start;
for (loop = bprm->argc; loop > 0; loop--) {
__put_user((elf_caddr_t) p, argv++);
p = (char __user *) current->mm->arg_start;
for (loop = bprm->argc; loop > 0; loop--) {
__put_user((elf_caddr_t) p, argv++);
- len = strnlen_user(p,
PAGE_SIZE * MAX_ARG_PAGES
);
- if (!len || len >
PAGE_SIZE * MAX_ARG_PAGES
)
+ len = strnlen_user(p,
MAX_ARG_STRLEN
);
+ if (!len || len >
MAX_ARG_STRLEN
)
return -EINVAL;
p += len;
}
return -EINVAL;
p += len;
}
@@
-632,8
+639,8
@@
static int create_elf_fdpic_tables(struct linux_binprm *bprm,
current->mm->env_start = (unsigned long) p;
for (loop = bprm->envc; loop > 0; loop--) {
__put_user((elf_caddr_t)(unsigned long) p, envp++);
current->mm->env_start = (unsigned long) p;
for (loop = bprm->envc; loop > 0; loop--) {
__put_user((elf_caddr_t)(unsigned long) p, envp++);
- len = strnlen_user(p,
PAGE_SIZE * MAX_ARG_PAGES
);
- if (!len || len >
PAGE_SIZE * MAX_ARG_PAGES
)
+ len = strnlen_user(p,
MAX_ARG_STRLEN
);
+ if (!len || len >
MAX_ARG_STRLEN
)
return -EINVAL;
p += len;
}
return -EINVAL;
p += len;
}
@@
-941,8
+948,11
@@
static int elf_fdpic_map_file_constdisp_on_uclinux(
if (mm) {
if (phdr->p_flags & PF_X) {
if (mm) {
if (phdr->p_flags & PF_X) {
- mm->start_code = seg->addr;
- mm->end_code = seg->addr + phdr->p_memsz;
+ if (!mm->start_code) {
+ mm->start_code = seg->addr;
+ mm->end_code = seg->addr +
+ phdr->p_memsz;
+ }
} else if (!mm->start_data) {
mm->start_data = seg->addr;
#ifndef CONFIG_MMU
} else if (!mm->start_data) {
mm->start_data = seg->addr;
#ifndef CONFIG_MMU
@@
-1123,8
+1133,10
@@
static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (mm) {
if (phdr->p_flags & PF_X) {
if (mm) {
if (phdr->p_flags & PF_X) {
- mm->start_code = maddr;
- mm->end_code = maddr + phdr->p_memsz;
+ if (!mm->start_code) {
+ mm->start_code = maddr;
+ mm->end_code = maddr + phdr->p_memsz;
+ }
} else if (!mm->start_data) {
mm->start_data = maddr;
mm->end_data = maddr + phdr->p_memsz;
} else if (!mm->start_data) {
mm->start_data = maddr;
mm->end_data = maddr + phdr->p_memsz;
@@
-1175,8
+1187,10
@@
static int dump_seek(struct file *file, loff_t off)
*
* I think we should skip something. But I am not sure how. H.J.
*/
*
* I think we should skip something. But I am not sure how. H.J.
*/
-static int maydump(struct vm_area_struct *vma)
+static int maydump(struct vm_area_struct *vma
, unsigned long mm_flags
)
{
{
+ int dump_ok;
+
/* Do not dump I/O mapped devices or special mappings */
if (vma->vm_flags & (VM_IO | VM_RESERVED)) {
kdcore("%08lx: %08lx: no (IO)", vma->vm_start, vma->vm_flags);
/* Do not dump I/O mapped devices or special mappings */
if (vma->vm_flags & (VM_IO | VM_RESERVED)) {
kdcore("%08lx: %08lx: no (IO)", vma->vm_start, vma->vm_flags);
@@
-1191,27
+1205,35
@@
static int maydump(struct vm_area_struct *vma)
return 0;
}
return 0;
}
- /*
Dump shared memory onl
y if mapped from an anonymous file. */
+ /*
By default, dump shared memor
y if mapped from an anonymous file. */
if (vma->vm_flags & VM_SHARED) {
if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) {
if (vma->vm_flags & VM_SHARED) {
if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0) {
- kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
- return 1;
+ 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;
}
}
- kdcore("%08lx: %08lx: no (share)", vma->vm_start, vma->vm_flags);
- return 0;
+ 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
}
#ifdef CONFIG_MMU
- /*
I
f it hasn't been written to, don't write it out */
+ /*
By default, i
f it hasn't been written to, don't write it out */
if (!vma->anon_vma) {
if (!vma->anon_vma) {
- kdcore("%08lx: %08lx: no (!anon)", vma->vm_start, vma->vm_flags);
- return 0;
+ 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
}
#endif
- kdcore("%08lx: %08lx: yes", vma->vm_start, vma->vm_flags);
- return 1;
+ 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;
}
/* An ELF note in memory */
}
/* An ELF note in memory */
@@
-1326,10
+1348,10
@@
static void fill_prstatus(struct elf_prstatus *prstatus,
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
- prstatus->pr_pid =
p->pid
;
- prstatus->pr_ppid =
p->parent->pid
;
- prstatus->pr_pgrp =
process_group
(p);
- prstatus->pr_sid =
process_session
(p);
+ prstatus->pr_pid =
task_pid_vnr(p)
;
+ prstatus->pr_ppid =
task_pid_vnr(p->parent)
;
+ prstatus->pr_pgrp =
task_pgrp_vnr
(p);
+ prstatus->pr_sid =
task_session_vnr
(p);
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
if (thread_group_leader(p)) {
/*
* This is the record for the group leader. Add in the
@@
-1375,10
+1397,10
@@
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
psinfo->pr_psargs[i] = ' ';
psinfo->pr_psargs[len] = 0;
psinfo->pr_psargs[i] = ' ';
psinfo->pr_psargs[len] = 0;
- psinfo->pr_pid =
p->pid
;
- psinfo->pr_ppid =
p->parent->pid
;
- psinfo->pr_pgrp =
process_group
(p);
- psinfo->pr_sid =
process_session
(p);
+ psinfo->pr_pid =
task_pid_vnr(p)
;
+ psinfo->pr_ppid =
task_pid_vnr(p->parent)
;
+ psinfo->pr_pgrp =
task_pgrp_vnr
(p);
+ psinfo->pr_sid =
task_session_vnr
(p);
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
i = p->state ? ffz(~p->state) + 1 : 0;
psinfo->pr_state = i;
@@
-1401,7
+1423,7
@@
struct elf_thread_status
elf_fpregset_t fpu; /* NT_PRFPREG */
struct task_struct *thread;
#ifdef ELF_CORE_COPY_XFPREGS
elf_fpregset_t fpu; /* NT_PRFPREG */
struct task_struct *thread;
#ifdef ELF_CORE_COPY_XFPREGS
- elf_fpxregset_t xfpu; /*
NT_PRXFPREG
*/
+ elf_fpxregset_t xfpu; /*
ELF_CORE_XFPREG_TYPE
*/
#endif
struct memelfnote notes[3];
int num_notes;
#endif
struct memelfnote notes[3];
int num_notes;
@@
-1437,8
+1459,8
@@
static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
- fill_note(&t->notes[2], "LINUX",
NT_PRXFPREG, sizeof(t->xfpu)
,
- &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]);
}
t->num_notes++;
sz += notesize(&t->notes[2]);
}
@@
-1450,15
+1472,15
@@
static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
* dump the segments for an MMU process
*/
#ifdef CONFIG_MMU
* dump the segments for an MMU process
*/
#ifdef CONFIG_MMU
-static int elf_fdpic_dump_segments(struct file *file, s
truct mm_struct *mm
,
-
size_t *size, unsigned long *limit
)
+static int elf_fdpic_dump_segments(struct file *file, s
ize_t *size
,
+
unsigned long *limit, unsigned long mm_flags
)
{
struct vm_area_struct *vma;
for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
unsigned long addr;
{
struct vm_area_struct *vma;
for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
unsigned long addr;
- if (!maydump(vma))
+ if (!maydump(vma
, mm_flags
))
continue;
for (addr = vma->vm_start;
continue;
for (addr = vma->vm_start;
@@
-1472,9
+1494,9
@@
static int elf_fdpic_dump_segments(struct file *file, struct mm_struct *mm,
&page, &vma) <= 0) {
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
&page, &vma) <= 0) {
DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
- else if (page == ZERO_PAGE(addr)) {
- DUMP_SEEK(file->f_pos + PAGE_SIZE);
+ else if (page == ZERO_PAGE(0)) {
page_cache_release(page);
page_cache_release(page);
+ DUMP_SEEK(file->f_pos + PAGE_SIZE);
}
else {
void *kaddr;
}
else {
void *kaddr;
@@
-1505,15
+1527,15
@@
end_coredump:
* dump the segments for a NOMMU process
*/
#ifndef CONFIG_MMU
* dump the segments for a NOMMU process
*/
#ifndef CONFIG_MMU
-static int elf_fdpic_dump_segments(struct file *file, s
truct mm_struct *mm
,
-
size_t *size, unsigned long *limit
)
+static int elf_fdpic_dump_segments(struct file *file, s
ize_t *size
,
+
unsigned long *limit, unsigned long mm_flags
)
{
struct vm_list_struct *vml;
for (vml = current->mm->context.vmlist; vml; vml = vml->next) {
struct vm_area_struct *vma = vml->vma;
{
struct vm_list_struct *vml;
for (vml = current->mm->context.vmlist; vml; vml = vml->next) {
struct vm_area_struct *vma = vml->vma;
- if (!maydump(vma))
+ if (!maydump(vma
, mm_flags
))
continue;
if ((*size += PAGE_SIZE) > *limit)
continue;
if ((*size += PAGE_SIZE) > *limit)
@@
-1536,7
+1558,7
@@
static int elf_fdpic_dump_segments(struct file *file, struct mm_struct *mm,
* we just truncate.
*/
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
* we just truncate.
*/
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
- struct file *file)
+ struct file *file
, unsigned long limit
)
{
#define NUM_NOTES 6
int has_dumped = 0;
{
#define NUM_NOTES 6
int has_dumped = 0;
@@
-1547,7
+1569,6
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
struct vm_area_struct *vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff;
struct vm_area_struct *vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff;
- unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
int numnote;
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
int numnote;
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
@@
-1564,6
+1585,7
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
struct vm_list_struct *vml;
#endif
elf_addr_t *auxv;
struct vm_list_struct *vml;
#endif
elf_addr_t *auxv;
+ unsigned long mm_flags;
/*
* We no longer stop all VM operations.
/*
* We no longer stop all VM operations.
@@
-1673,7
+1695,7
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(current, xfpu))
fill_note(notes + numnote++,
#ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(current, xfpu))
fill_note(notes + numnote++,
- "LINUX",
NT_PRXFPREG
, sizeof(*xfpu), xfpu);
+ "LINUX",
ELF_CORE_XFPREG_TYPE
, sizeof(*xfpu), xfpu);
#endif
fs = get_fs();
#endif
fs = get_fs();
@@
-1701,6
+1723,13
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
/* Page-align dumped data */
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
/* Page-align dumped data */
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
+ /*
+ * We must use the same mm->flags while dumping core to avoid
+ * inconsistency between the program headers and bodies, otherwise an
+ * unusable core file can be generated.
+ */
+ mm_flags = current->mm->flags;
+
/* write program headers for segments dump */
for (
#ifdef CONFIG_MMU
/* write program headers for segments dump */
for (
#ifdef CONFIG_MMU
@@
-1722,7
+1751,7
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
- phdr.p_filesz = maydump(vma) ? sz : 0;
+ phdr.p_filesz = maydump(vma
, mm_flags
) ? sz : 0;
phdr.p_memsz = sz;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
phdr.p_memsz = sz;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@
-1756,7
+1785,7
@@
static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
DUMP_SEEK(dataoff);
DUMP_SEEK(dataoff);
- if (elf_fdpic_dump_segments(file,
current->mm, &size, &limit
) < 0)
+ if (elf_fdpic_dump_segments(file,
&size, &limit, mm_flags
) < 0)
goto end_coredump;
#ifdef ELF_CORE_WRITE_EXTRA_DATA
goto end_coredump;
#ifdef ELF_CORE_WRITE_EXTRA_DATA