summaryrefslogtreecommitdiffstats
path: root/fs/proc/kcore.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /fs/proc/kcore.c
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'fs/proc/kcore.c')
-rw-r--r--fs/proc/kcore.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index ec2a92db3..28635ff14 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -3,9 +3,9 @@
*
* Modelled on fs/exec.c:aout_core_dump()
* Jeremy Fitzhardinge <jeremy@sw.oz.au>
- * Implemented by David Howells <David.Howells@nexor.co.uk>
+ * ELF version written by David Howells <David.Howells@nexor.co.uk>
* Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com>
- * Support to dump vmalloc'd data structures (ELF only), Tigran Aivazian <tigran@sco.com>
+ * Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@sco.com>
*/
#include <linux/config.h>
@@ -16,7 +16,6 @@
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
#include <asm/uaccess.h>
@@ -43,8 +42,7 @@ struct inode_operations proc_kcore_inode_operations = {
};
#ifdef CONFIG_KCORE_AOUT
-static ssize_t read_kcore(struct file * file, char * buf,
- size_t count, loff_t *ppos)
+static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *ppos)
{
unsigned long long p = *ppos, memsize;
ssize_t read;
@@ -79,7 +77,8 @@ static ssize_t read_kcore(struct file * file, char * buf,
if (p + count1 > sizeof(struct user))
count1 = sizeof(struct user)-p;
pnt = (char *) &dump + p;
- copy_to_user(buf,(void *) pnt, count1);
+ if (copy_to_user(buf,(void *) pnt, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
@@ -90,14 +89,16 @@ static ssize_t read_kcore(struct file * file, char * buf,
count1 = PAGE_SIZE + FIRST_MAPPED - p;
if (count1 > count)
count1 = count;
- clear_user(buf, count1);
+ if (clear_user(buf, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
read += count1;
}
if (count > 0) {
- copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count);
+ if (copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count))
+ return -EFAULT;
read += count;
}
*ppos += read;
@@ -130,6 +131,8 @@ static size_t get_kcore_size(int *num_vma, int *elf_buflen)
}
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
try = (size_t)m->addr + m->size;
if (try > size)
size = try;
@@ -189,7 +192,7 @@ static char *storenote(struct memelfnote *men, char *bufp)
* store an ELF coredump header in the supplied buffer
* num_vma is the number of elements in vmlist
*/
-static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
+static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff)
{
struct elf_prstatus prstatus; /* NT_PRSTATUS */
struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */
@@ -235,28 +238,33 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
nhdr->p_flags = 0;
nhdr->p_align = 0;
- /* setup ELF PT_LOAD program header */
+ /* setup ELF PT_LOAD program header for the
+ * virtual range 0xc0000000 -> high_memory */
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = elf_buflen;
+ phdr->p_offset = dataoff;
phdr->p_vaddr = PAGE_OFFSET;
phdr->p_paddr = __pa(PAGE_OFFSET);
phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
phdr->p_align = PAGE_SIZE;
+ /* setup ELF PT_LOAD program header for every vmalloc'd area */
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
+
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + elf_buflen;
+ phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + dataoff;
phdr->p_vaddr = (size_t)m->addr;
- phdr->p_paddr = __pa(m);
+ phdr->p_paddr = __pa(m->addr);
phdr->p_filesz = phdr->p_memsz = m->size;
phdr->p_align = PAGE_SIZE;
}
@@ -310,13 +318,12 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
/*
* read from the ELF header and then kernel memory
*/
-static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
- loff_t *fpos)
+static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos)
{
ssize_t acc = 0;
size_t size, tsz;
- char * elf_buffer;
- int elf_buflen = 0, num_vma = 0;
+ size_t elf_buflen;
+ int num_vma;
/* XXX we need to somehow lock vmlist between here
* and after elf_kcore_store_hdr() returns.
@@ -332,16 +339,21 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* construct an ELF core header if we'll need some of it */
if (*fpos < elf_buflen) {
+ char * elf_buf;
+
tsz = elf_buflen - *fpos;
if (buflen < tsz)
tsz = buflen;
- elf_buffer = kmalloc(elf_buflen, GFP_KERNEL);
- if (!elf_buffer)
+ elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
+ if (!elf_buf)
return -ENOMEM;
- memset(elf_buffer, 0, elf_buflen);
- elf_kcore_store_hdr(elf_buffer, num_vma, elf_buflen);
- copy_to_user(buffer, elf_buffer, tsz);
- kfree(elf_buffer);
+ memset(elf_buf, 0, elf_buflen);
+ elf_kcore_store_hdr(elf_buf, num_vma, elf_buflen);
+ if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
+ kfree(elf_buf);
+ return -EFAULT;
+ }
+ kfree(elf_buf);
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -349,7 +361,7 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* leave now if filled buffer already */
if (buflen == 0)
- return tsz;
+ return acc;
}
/* where page 0 not mapped, write zeros into buffer */
@@ -361,7 +373,8 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
tsz = buflen;
/* write zeros to buffer */
- clear_user(buffer, tsz);
+ if (clear_user(buffer, tsz))
+ return -EFAULT;
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -372,17 +385,12 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
return tsz;
}
#endif
-
/* fill the remainder of the buffer from kernel VM space */
-#if defined (__i386__) || defined (__mc68000__)
- copy_to_user(buffer, __va(*fpos - PAGE_SIZE), buflen);
-#else
- copy_to_user(buffer, __va(*fpos), buflen);
-#endif
+ if (copy_to_user(buffer, __va(*fpos - elf_buflen), buflen))
+ return -EFAULT;
+
acc += buflen;
*fpos += buflen;
-
return acc;
-
}
#endif /* CONFIG_KCORE_AOUT */