rpms/kernel/F-11 devmem-check-vmalloc-address-on-kmem-read-write.patch, NONE, 1.1 devmem-fix-kmem-write-bug-on-memory-holes.patch, NONE, 1.1 devmem-introduce-size_inside_page.patch, NONE, 1.1 kernel.spec, 1.1808, 1.1809
Chuck Ebbert
cebbert at fedoraproject.org
Fri Feb 5 18:18:33 UTC 2010
Author: cebbert
Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv1195
Modified Files:
kernel.spec
Added Files:
devmem-check-vmalloc-address-on-kmem-read-write.patch
devmem-fix-kmem-write-bug-on-memory-holes.patch
devmem-introduce-size_inside_page.patch
Log Message:
Backport three bug fixes for /dev/kmem
devmem-check-vmalloc-address-on-kmem-read-write.patch:
mem.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- NEW FILE devmem-check-vmalloc-address-on-kmem-read-write.patch ---
From: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
Date: Tue, 2 Feb 2010 21:44:05 +0000 (-0800)
Subject: devmem: check vmalloc address on kmem read/write
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=325fda71d0badc1073dc59f12a948f24ff05796a
[ cebbert at redhat.com : backport to 2.6.32 ]
devmem: check vmalloc address on kmem read/write
Otherwise vmalloc_to_page() will BUG().
This also makes the kmem read/write implementation aligned with mem(4):
"References to nonexistent locations cause errors to be returned." Here we
return -ENXIO (inspired by Hugh) if no bytes have been transfered to/from
user space, otherwise return partial read/write results.
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
Signed-off-by: Wu Fengguang <fengguang.wu at intel.com>
Cc: Greg Kroah-Hartman <gregkh at suse.de>
Cc: Hugh Dickins <hugh.dickins at tiscali.co.uk>
Cc: <stable at kernel.org>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index be832b6..1fd4b11 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -395,6 +395,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
unsigned long p = *ppos;
ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+ int err = 0;
read = 0;
if (p < (unsigned long) high_memory) {
@@ -441,12 +442,16 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
while (count > 0) {
int len = size_inside_page(p, count);
+ if (!is_vmalloc_or_module_addr((void *)p)) {
+ err = -ENXIO;
+ break;
+ }
len = vread(kbuf, (char *)p, len);
if (!len)
break;
if (copy_to_user(buf, kbuf, len)) {
- free_page((unsigned long)kbuf);
- return -EFAULT;
+ err = -EFAULT;
+ break;
}
count -= len;
buf += len;
@@ -455,8 +460,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
free_page((unsigned long)kbuf);
}
- *ppos = p;
- return read;
+ *ppos = p;
+ return read ? read : err;
}
@@ -520,6 +525,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
ssize_t virtr = 0;
ssize_t written;
char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+ int err = 0;
if (p < (unsigned long) high_memory) {
@@ -540,13 +546,15 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
while (count > 0) {
int len = size_inside_page(p, count);
+ if (!is_vmalloc_or_module_addr((void *)p)) {
+ err = -ENXIO;
+ break;
+ }
if (len) {
written = copy_from_user(kbuf, buf, len);
if (written) {
- if (wrote + virtr)
- break;
- free_page((unsigned long)kbuf);
- return -EFAULT;
+ err = -EFAULT;
+ break;
}
}
len = vwrite(kbuf, (char *)p, sz);
@@ -556,8 +564,8 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
free_page((unsigned long)kbuf);
}
- *ppos = p;
- return virtr + wrote;
+ *ppos = p;
+ return virtr + wrote ? : err;
}
#endif
devmem-fix-kmem-write-bug-on-memory-holes.patch:
mem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- NEW FILE devmem-fix-kmem-write-bug-on-memory-holes.patch ---
From: Wu Fengguang <fengguang.wu at intel.com>
Date: Tue, 2 Feb 2010 21:44:06 +0000 (-0800)
Subject: devmem: fix kmem write bug on memory holes
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=c85e9a97c4102ce2e83112da850d838cfab5ab13
devmem: fix kmem write bug on memory holes
[ cebbert at redhat.com : backport to 2.6.32 ]
write_kmem() used to assume vwrite() always return the full buffer length.
However now vwrite() could return 0 to indicate memory hole. This
creates a bug that "buf" is not advanced accordingly.
Fix it to simply ignore the return value, hence the memory hole.
Signed-off-by: Wu Fengguang <fengguang.wu at intel.com>
Cc: Andi Kleen <andi at firstfloor.org>
Cc: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Cc: Christoph Lameter <cl at linux-foundation.org>
Cc: Ingo Molnar <mingo at elte.hu>
Cc: Tejun Heo <tj at kernel.org>
Cc: Nick Piggin <npiggin at suse.de>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
Cc: <stable at kernel.org>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1fd4b11..48788db 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -555,7 +555,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
break;
}
}
- len = vwrite(kbuf, (char *)p, len);
+ vwrite(kbuf, (char *)p, len);
count -= len;
buf += len;
virtr += len;
devmem-introduce-size_inside_page.patch:
mem.c | 40 +++++++++++++++++-----------------------
1 file changed, 17 insertions(+), 23 deletions(-)
--- NEW FILE devmem-introduce-size_inside_page.patch ---
From: Wu Fengguang <fengguang.wu at intel.com>
Date: Tue, 15 Dec 2009 01:58:07 +0000 (-0800)
Subject: /dev/mem: introduce size_inside_page()
X-Git-Tag: v2.6.33-rc1~263
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=f222318e9c3a315723e3524fb9d6566b2430db44
/dev/mem: introduce size_inside_page()
[ cebbert at redhat.com : backport to 2.6.32 ]
[ subset of original patch, for just /dev/kmem ]
Introduce size_inside_page() to replace duplicate /dev/mem code.
Also apply it to /dev/kmem, whose alignment logic was buggy.
Signed-off-by: Wu Fengguang <fengguang.wu at intel.com>
Acked-by: Andi Kleen <ak at linux.intel.com>
Cc: Marcelo Tosatti <mtosatti at redhat.com>
Cc: Greg Kroah-Hartman <gregkh at suse.de>
Cc: Mark Brown <broonie at opensource.wolfsonmicro.com>
Cc: Johannes Berg <johannes at sipsolutions.net>
Cc: Avi Kivity <avi at qumranet.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f0a9059..aaa9c24 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -35,6 +35,19 @@
# include <linux/efi.h>
#endif
+static inline unsigned long size_inside_page(unsigned long start,
+ unsigned long size)
+{
+ unsigned long sz;
+
+ if (-start & (PAGE_SIZE - 1))
+ sz = -start & (PAGE_SIZE - 1);
+ else
+ sz = PAGE_SIZE;
+
+ return min_t(unsigned long, sz, size);
+}
+
/*
* Architectures vary in how they handle caching for addresses
* outside of main memory.
@@ -428,15 +441,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
#endif
while (low_count > 0) {
- /*
- * Handle first page in case it's not aligned
- */
- if (-p & (PAGE_SIZE - 1))
- sz = -p & (PAGE_SIZE - 1);
- else
- sz = PAGE_SIZE;
-
- sz = min_t(unsigned long, sz, low_count);
+ sz = size_inside_page(p, low_count);
/*
* On ia64 if a page has been mapped somewhere as
@@ -461,10 +466,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
if (!kbuf)
return -ENOMEM;
while (count > 0) {
- int len = count;
+ int len = size_inside_page(p, count);
- if (len > PAGE_SIZE)
- len = PAGE_SIZE;
len = vread(kbuf, (char *)p, len);
if (!len)
break;
@@ -509,15 +512,8 @@ do_write_kmem(void *p, unsigned long realp, const char __user * buf,
while (count > 0) {
char *ptr;
- /*
- * Handle first page in case it's not aligned
- */
- if (-realp & (PAGE_SIZE - 1))
- sz = -realp & (PAGE_SIZE - 1);
- else
- sz = PAGE_SIZE;
- sz = min_t(unsigned long, sz, count);
+ sz = size_inside_page(realp, count);
/*
* On ia64 if a page has been mapped somewhere as
@@ -577,10 +573,8 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
if (!kbuf)
return wrote ? wrote : -ENOMEM;
while (count > 0) {
- int len = count;
+ int len = size_inside_page(p, count);
- if (len > PAGE_SIZE)
- len = PAGE_SIZE;
if (len) {
written = copy_from_user(kbuf, buf, len);
if (written) {
Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1808
retrieving revision 1.1809
diff -u -p -r1.1808 -r1.1809
--- kernel.spec 5 Feb 2010 00:49:37 -0000 1.1808
+++ kernel.spec 5 Feb 2010 18:18:33 -0000 1.1809
@@ -751,6 +751,11 @@ Patch12102: wmi-check-wmi-get-event-data
Patch12301: fix-conntrack-bug-with-namespaces.patch
Patch12302: prevent-runtime-conntrack-changes.patch
+# backport /dev/mem patches for -stable
+Patch20010: devmem-introduce-size_inside_page.patch
+Patch20020: devmem-check-vmalloc-address-on-kmem-read-write.patch
+Patch20030: devmem-fix-kmem-write-bug-on-memory-holes.patch
+
#===============================================================================
%endif
@@ -1373,6 +1378,11 @@ ApplyPatch wmi-check-wmi-get-event-data-
ApplyPatch fix-conntrack-bug-with-namespaces.patch
ApplyPatch prevent-runtime-conntrack-changes.patch
+# backport /dev/mem patches for -stable
+ApplyPatch devmem-introduce-size_inside_page.patch
+ApplyPatch devmem-check-vmalloc-address-on-kmem-read-write.patch
+ApplyPatch devmem-fix-kmem-write-bug-on-memory-holes.patch
+
# END OF PATCH APPLICATIONS ====================================================
%endif
@@ -2028,6 +2038,9 @@ fi
# and build.
%changelog
+* Fri Feb 05 2010 Chuck Ebbert <cebbert at redhat.com> 2.6.32.8-24.rc1
+- Backport three bug fixes for /dev/kmem
+
* Thu Feb 04 2010 Chuck Ebbert <cebbert at redhat.com> 2.6.32.8-23.rc1
- Copy DMAR fix for cantiga chipset from F-12
- Disable DMAR by default: CONFIG_DMAR_DEFAULT_ON is not set
More information about the scm-commits
mailing list