patch-2.3.29 linux/fs/proc/kcore.c

Next file: linux/fs/proc/openprom-dev.c
Previous file: linux/fs/proc/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.28/linux/fs/proc/kcore.c linux/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>
@@ -42,8 +42,7 @@
 };
 
 #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;
@@ -78,7 +77,8 @@
 		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;
@@ -89,14 +89,16 @@
 		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;
@@ -129,6 +131,8 @@
 	}
 
 	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;
@@ -247,8 +251,11 @@
 	phdr->p_filesz	= phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
 	phdr->p_align	= PAGE_SIZE;
 
-	/* setup ELF PT_LOAD program headers, one for every kvma range */
+	/* 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);
@@ -315,12 +322,8 @@
 {
 	ssize_t acc = 0;
 	size_t size, tsz;
-	char * elf_buffer;
-	size_t elf_buflen = 0;
-	int num_vma = 0;
-
-	if (verify_area(VERIFY_WRITE, buffer, buflen))
-		return -EFAULT;
+	size_t elf_buflen;
+	int num_vma;
 
 	/* XXX we need to somehow lock vmlist between here
 	 * and after elf_kcore_store_hdr() returns.
@@ -336,16 +339,21 @@
 
 	/* 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 + *fpos, 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;
@@ -365,7 +373,8 @@
 			tsz = buflen;
 
 		/* write zeros to buffer */
-		clear_user(buffer, tsz);
+		if (clear_user(buffer, tsz))
+			return -EFAULT;
 		buflen -= tsz;
 		*fpos += tsz;
 		buffer += tsz;
@@ -376,13 +385,12 @@
 			return tsz;
 	}
 #endif
-
 	/* fill the remainder of the buffer from kernel VM space */
-	copy_to_user(buffer, __va(*fpos - elf_buflen), buflen);
+	if (copy_to_user(buffer, __va(*fpos - elf_buflen), buflen))
+		return -EFAULT;
 
 	acc += buflen;
 	*fpos += buflen;
 	return acc;
-
 }
 #endif /* CONFIG_KCORE_AOUT */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)