aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHirofumi Ogawa <hirofumi@mail.parknet.co.jp>2005-03-30 16:27:22 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-30 16:27:22 -0800
commit31b6c032a05d7df098cafa6fa1062dfe735e1d40 (patch)
tree095e8a53f11794307c71290a11baca061252c3cc
parent883108b9b92b3232b114d4466222332f8529235e (diff)
downloadhistory-31b6c032a05d7df098cafa6fa1062dfe735e1d40.tar.gz
[PATCH] read_kmem() fixes
drivers/char/mem.c:289 if (p < PAGE_SIZE && read > 0) { [...] read -= tmp; count -= tmp; This part is losting the number of bytes which read. drivers/char/mem.c:302 sz = min_t(unsigned long, sz, count); This should use "read" instead of "count". drivers/char/mem.c:315 read -= sz; count -= sz; Also lost the number of bytes which read. In short, kmem returns incorrect number always if user is accessing the lowmem area. And also it doesn't handle the highmem boundary rightly. This patch uses "low_count" instead of "read", as the number of copy in lowmem area. And "read" is used as the number of bytes which read. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/mem.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index d47efcc9e5613..947cb3cef8167 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -283,30 +283,30 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- ssize_t read, virtr, sz;
+ ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
read = 0;
- virtr = 0;
if (p < (unsigned long) high_memory) {
- read = count;
+ low_count = count;
if (count > (unsigned long) high_memory - p)
- read = (unsigned long) high_memory - p;
+ low_count = (unsigned long) high_memory - p;
#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
/* we don't have page 0 mapped on sparc and m68k.. */
- if (p < PAGE_SIZE && read > 0) {
+ if (p < PAGE_SIZE && low_count > 0) {
size_t tmp = PAGE_SIZE - p;
- if (tmp > read) tmp = read;
+ if (tmp > low_count) tmp = low_count;
if (clear_user(buf, tmp))
return -EFAULT;
buf += tmp;
p += tmp;
- read -= tmp;
+ read += tmp;
+ low_count -= tmp;
count -= tmp;
}
#endif
- while (read > 0) {
+ while (low_count > 0) {
/*
* Handle first page in case it's not aligned
*/
@@ -315,7 +315,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
else
sz = PAGE_SIZE;
- sz = min_t(unsigned long, sz, count);
+ sz = min_t(unsigned long, sz, low_count);
/*
* On ia64 if a page has been mapped somewhere as
@@ -328,7 +328,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
return -EFAULT;
buf += sz;
p += sz;
- read -= sz;
+ read += sz;
+ low_count -= sz;
count -= sz;
}
}
@@ -351,13 +352,13 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
count -= len;
buf += len;
- virtr += len;
+ read += len;
p += len;
}
free_page((unsigned long)kbuf);
}
*ppos = p;
- return virtr + read;
+ return read;
}