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

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

diff -urN linux-2.4.22/fs/proc/kcore.c linux-2.4.23/fs/proc/kcore.c
@@ -27,11 +27,14 @@
 	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 }
 
+static loff_t lseek_kcore(struct file * file, loff_t offset, int origin);
+
 static ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
 
 struct file_operations proc_kcore_operations = {
 	read:		read_kcore,
 	open:		open_kcore,
+	llseek:		lseek_kcore,
 };
 
 #ifdef CONFIG_KCORE_AOUT
@@ -112,9 +115,9 @@
 
 extern char saved_command_line[];
 
-static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
+static unsigned long get_kcore_size(int *num_vma, size_t *elf_buflen)
 {
-	size_t try, size;
+	unsigned long try, size;
 	struct vm_struct *m;
 
 	*num_vma = 0;
@@ -125,7 +128,7 @@
 	}
 
 	for (m=vmlist; m; m=m->next) {
-		try = (size_t)m->addr + m->size;
+		try = (unsigned long)m->addr + m->size;
 		if (try > size)
 			size = try;
 		*num_vma = *num_vma + 1;
@@ -313,14 +316,14 @@
 static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos)
 {
 	ssize_t acc = 0;
-	size_t size, tsz;
+	unsigned long size, tsz;
 	size_t elf_buflen;
 	int num_vma;
 	unsigned long start;
 
 	read_lock(&vmlist_lock);
 	proc_root_kcore->size = size = get_kcore_size(&num_vma, &elf_buflen);
-	if (buflen == 0 || *fpos >= size) {
+	if (buflen == 0 || (unsigned long long)*fpos >= size) {
 		read_unlock(&vmlist_lock);
 		return 0;
 	}
@@ -390,9 +393,16 @@
 	start = PAGE_OFFSET + (*fpos - elf_buflen);
 	if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
 		tsz = buflen;
-		
 	while (buflen) {
-		if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
+		int err; 
+	
+		if ((start > PAGE_OFFSET) && (start < (unsigned long)high_memory)) {
+			if (kern_addr_valid(start)) {
+				err = copy_to_user(buffer, (char *)start, tsz);
+			} else {
+				err = clear_user(buffer, tsz);
+			}
+		} else {
 			char * elf_buf;
 			struct vm_struct *m;
 			unsigned long curstart = start;
@@ -432,24 +442,11 @@
 					(char *)vmstart, vmsize);
 			}
 			read_unlock(&vmlist_lock);
-			if (copy_to_user(buffer, elf_buf, tsz)) {
+			err = copy_to_user(buffer, elf_buf, tsz); 
 				kfree(elf_buf);
-				return -EFAULT;
 			}
-			kfree(elf_buf);
-		} else if ((start > PAGE_OFFSET) && (start < 
-						(unsigned long)high_memory)) {
-			if (kern_addr_valid(start)) {
-				if (copy_to_user(buffer, (char *)start, tsz))
+		if (err)
 					return -EFAULT;
-			} else {
-				if (clear_user(buffer, tsz))
-					return -EFAULT;
-			}
-		} else {
-			if (clear_user(buffer, tsz))
-				return -EFAULT;
-		}
 		buflen -= tsz;
 		*fpos += tsz;
 		buffer += tsz;
@@ -461,3 +458,17 @@
 	return acc;
 }
 #endif /* CONFIG_KCORE_AOUT */
+
+static loff_t lseek_kcore(struct file * file, loff_t offset, int origin)
+{
+	switch (origin) {
+		case 2:
+			offset += file->f_dentry->d_inode->i_size;
+			break;
+		case 1:
+			offset += file->f_pos;
+	}
+	/* RED-PEN user can fake an error here by setting offset to >=-4095 && <0  */
+	file->f_pos = offset;
+	return offset;
+}

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