|
@@ -1151,11 +1151,23 @@ static int dump_write(struct file *file, const void *addr, int nr)
|
|
|
|
|
|
static int dump_seek(struct file *file, loff_t off)
|
|
static int dump_seek(struct file *file, loff_t off)
|
|
{
|
|
{
|
|
- if (file->f_op->llseek) {
|
|
|
|
- if (file->f_op->llseek(file, off, 0) != off)
|
|
|
|
|
|
+ if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
|
|
|
|
+ if (file->f_op->llseek(file, off, 1) != off)
|
|
return 0;
|
|
return 0;
|
|
- } else
|
|
|
|
- file->f_pos = off;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ char *buf = (char *)get_zeroed_page(GFP_KERNEL);
|
|
|
|
+ if (!buf)
|
|
|
|
+ return 0;
|
|
|
|
+ while (off > 0) {
|
|
|
|
+ unsigned long n = off;
|
|
|
|
+ if (n > PAGE_SIZE)
|
|
|
|
+ n = PAGE_SIZE;
|
|
|
|
+ if (!dump_write(file, buf, n))
|
|
|
|
+ return 0;
|
|
|
|
+ off -= n;
|
|
|
|
+ }
|
|
|
|
+ free_page((unsigned long)buf);
|
|
|
|
+ }
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1203,30 +1215,35 @@ static int notesize(struct memelfnote *en)
|
|
return sz;
|
|
return sz;
|
|
}
|
|
}
|
|
|
|
|
|
-#define DUMP_WRITE(addr, nr) \
|
|
|
|
- do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
|
|
|
|
-#define DUMP_SEEK(off) \
|
|
|
|
- do { if (!dump_seek(file, (off))) return 0; } while(0)
|
|
|
|
|
|
+#define DUMP_WRITE(addr, nr, foffset) \
|
|
|
|
+ do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
|
|
|
|
|
|
-static int writenote(struct memelfnote *men, struct file *file)
|
|
|
|
|
|
+static int alignfile(struct file *file, loff_t *foffset)
|
|
{
|
|
{
|
|
- struct elf_note en;
|
|
|
|
|
|
+ char buf[4] = { 0, };
|
|
|
|
+ DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
|
|
|
|
+static int writenote(struct memelfnote *men, struct file *file,
|
|
|
|
+ loff_t *foffset)
|
|
|
|
+{
|
|
|
|
+ struct elf_note en;
|
|
en.n_namesz = strlen(men->name) + 1;
|
|
en.n_namesz = strlen(men->name) + 1;
|
|
en.n_descsz = men->datasz;
|
|
en.n_descsz = men->datasz;
|
|
en.n_type = men->type;
|
|
en.n_type = men->type;
|
|
|
|
|
|
- DUMP_WRITE(&en, sizeof(en));
|
|
|
|
- DUMP_WRITE(men->name, en.n_namesz);
|
|
|
|
- /* XXX - cast from long long to long to avoid need for libgcc.a */
|
|
|
|
- DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
|
|
|
|
- DUMP_WRITE(men->data, men->datasz);
|
|
|
|
- DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
|
|
|
|
|
|
+ DUMP_WRITE(&en, sizeof(en), foffset);
|
|
|
|
+ DUMP_WRITE(men->name, en.n_namesz, foffset);
|
|
|
|
+ if (!alignfile(file, foffset))
|
|
|
|
+ return 0;
|
|
|
|
+ DUMP_WRITE(men->data, men->datasz, foffset);
|
|
|
|
+ if (!alignfile(file, foffset))
|
|
|
|
+ return 0;
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
#undef DUMP_WRITE
|
|
#undef DUMP_WRITE
|
|
-#undef DUMP_SEEK
|
|
|
|
|
|
|
|
#define DUMP_WRITE(addr, nr) \
|
|
#define DUMP_WRITE(addr, nr) \
|
|
if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
|
|
if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
|
|
@@ -1426,7 +1443,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
int i;
|
|
int i;
|
|
struct vm_area_struct *vma;
|
|
struct vm_area_struct *vma;
|
|
struct elfhdr *elf = NULL;
|
|
struct elfhdr *elf = NULL;
|
|
- loff_t offset = 0, dataoff;
|
|
|
|
|
|
+ loff_t offset = 0, dataoff, foffset;
|
|
unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
|
|
unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
|
|
int numnote;
|
|
int numnote;
|
|
struct memelfnote *notes = NULL;
|
|
struct memelfnote *notes = NULL;
|
|
@@ -1569,7 +1586,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
DUMP_WRITE(&phdr, sizeof(phdr));
|
|
DUMP_WRITE(&phdr, sizeof(phdr));
|
|
}
|
|
}
|
|
|
|
|
|
- /* Page-align dumped data */
|
|
|
|
|
|
+ foffset = offset;
|
|
|
|
+
|
|
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
|
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
|
|
|
|
|
|
/* Write program headers for segments dump */
|
|
/* Write program headers for segments dump */
|
|
@@ -1594,6 +1612,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
phdr.p_align = ELF_EXEC_PAGESIZE;
|
|
phdr.p_align = ELF_EXEC_PAGESIZE;
|
|
|
|
|
|
DUMP_WRITE(&phdr, sizeof(phdr));
|
|
DUMP_WRITE(&phdr, sizeof(phdr));
|
|
|
|
+ foffset += sizeof(phdr);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
|
|
#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
|
|
@@ -1602,7 +1621,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
|
|
|
|
/* write out the notes section */
|
|
/* write out the notes section */
|
|
for (i = 0; i < numnote; i++)
|
|
for (i = 0; i < numnote; i++)
|
|
- if (!writenote(notes + i, file))
|
|
|
|
|
|
+ if (!writenote(notes + i, file, &foffset))
|
|
goto end_coredump;
|
|
goto end_coredump;
|
|
|
|
|
|
/* write out the thread status notes section */
|
|
/* write out the thread status notes section */
|
|
@@ -1611,11 +1630,12 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
list_entry(t, struct elf_thread_status, list);
|
|
list_entry(t, struct elf_thread_status, list);
|
|
|
|
|
|
for (i = 0; i < tmp->num_notes; i++)
|
|
for (i = 0; i < tmp->num_notes; i++)
|
|
- if (!writenote(&tmp->notes[i], file))
|
|
|
|
|
|
+ if (!writenote(&tmp->notes[i], file, &foffset))
|
|
goto end_coredump;
|
|
goto end_coredump;
|
|
}
|
|
}
|
|
-
|
|
|
|
- DUMP_SEEK(dataoff);
|
|
|
|
|
|
+
|
|
|
|
+ /* Align to page */
|
|
|
|
+ DUMP_SEEK(dataoff - foffset);
|
|
|
|
|
|
for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
|
|
for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
|
|
unsigned long addr;
|
|
unsigned long addr;
|
|
@@ -1631,10 +1651,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
|
|
|
|
if (get_user_pages(current, current->mm, addr, 1, 0, 1,
|
|
if (get_user_pages(current, current->mm, addr, 1, 0, 1,
|
|
&page, &vma) <= 0) {
|
|
&page, &vma) <= 0) {
|
|
- DUMP_SEEK(file->f_pos + PAGE_SIZE);
|
|
|
|
|
|
+ DUMP_SEEK(PAGE_SIZE);
|
|
} else {
|
|
} else {
|
|
if (page == ZERO_PAGE(addr)) {
|
|
if (page == ZERO_PAGE(addr)) {
|
|
- DUMP_SEEK(file->f_pos + PAGE_SIZE);
|
|
|
|
|
|
+ DUMP_SEEK(PAGE_SIZE);
|
|
} else {
|
|
} else {
|
|
void *kaddr;
|
|
void *kaddr;
|
|
flush_cache_page(vma, addr,
|
|
flush_cache_page(vma, addr,
|
|
@@ -1658,13 +1678,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
|
|
ELF_CORE_WRITE_EXTRA_DATA;
|
|
ELF_CORE_WRITE_EXTRA_DATA;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- if (file->f_pos != offset) {
|
|
|
|
- /* Sanity check */
|
|
|
|
- printk(KERN_WARNING
|
|
|
|
- "elf_core_dump: file->f_pos (%Ld) != offset (%Ld)\n",
|
|
|
|
- file->f_pos, offset);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
end_coredump:
|
|
end_coredump:
|
|
set_fs(fs);
|
|
set_fs(fs);
|
|
|
|
|