Re: killing a set of user processes causes system
Helge Deller <[email protected]>
| Newsgroups | gmane.linux.ports.hppa |
|---|---|
| Message-ID | <[email protected]> |
On Saturday 16 December 2006 22:17, Helge Deller wrote:
> On Saturday 16 December 2006 22:10, John David Anglin wrote:
> > > > If not, maybe you could try my (ugly & temporary) kernel patch from http://lists.parisc-linux.org/pipermail/parisc-linux/2006-December/030967.html ?
> > >
> > > I'll give it a try.
> >
> > I get a bunch of messages like:
> > WARNING: "show_stack" [net/ipv6/ipv6.ko] undefined!
>
> disable ipv6 for now... The problem is show_stack() in access_ok().
> I don't use modules atm.
this is an updated patch, where only the absolute necessary pieces were changed.
It applies to current git tree...
Helge
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 5575e41..72a873d 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -56,6 +56,7 @@
#include <linux/module.h>
#include <linux/compiler.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
#define s_space "%%sr1"
#define d_space "%%sr2"
#else
@@ -488,23 +489,37 @@ handle_store_error:
#ifdef __KERNEL__
unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len)
{
- mtsp(get_kernel_space(), 1);
- mtsp(get_user_space(), 2);
- return pa_memcpy((void __force *)dst, src, len);
+ BUG_ON((long) len < 0);
+ if (access_ok(VERIFY_WRITE, dst, len)) {
+ mtsp(get_kernel_space(), 1);
+ mtsp(get_user_space(), 2);
+ len = pa_memcpy((void __force *)dst, src, len);
+ };
+ return len;
}
unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len)
{
- mtsp(get_user_space(), 1);
- mtsp(get_kernel_space(), 2);
- return pa_memcpy(dst, (void __force *)src, len);
+ BUG_ON((long) len < 0);
+ if (access_ok(VERIFY_READ, src, len)) {
+ mtsp(get_user_space(), 1);
+ mtsp(get_kernel_space(), 2);
+ len = pa_memcpy(dst, (void __force *)src, len);
+ } else
+ memset(dst, 0, len);
+ return len;
}
unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len)
{
- mtsp(get_user_space(), 1);
- mtsp(get_user_space(), 2);
- return pa_memcpy((void __force *)dst, (void __force *)src, len);
+ BUG_ON((long) len < 0);
+ if (likely(access_ok(VERIFY_READ, src, len) &&
+ access_ok(VERIFY_WRITE, dst, len))) {
+ mtsp(get_user_space(), 1);
+ mtsp(get_user_space(), 2);
+ len = pa_memcpy((void __force *)dst, (void __force *)src, len);
+ }
+ return len;
}
@@ -516,6 +531,24 @@ void * memcpy(void * dst,const void *src
return dst;
}
+long access_ok(int type, const void __user * addr, unsigned long size)
+{
+ unsigned long a = (unsigned long __force) addr;
+ long ok;
+
+ if (segment_eq(get_fs(),KERNEL_DS))
+ ok = 1;
+ else
+ ok = (a < F_EXTEND(0xfff00000));
+ if (unlikely(!ok)) {
+ printk(KERN_ERR "function %s() FAILED for addr=%p len=%lx\n", __FUNCTION__, addr, size);
+ show_stack(NULL,NULL);
+ }
+ return (ok);
+}
+EXPORT_SYMBOL(access_ok);
+
+
EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(copy_from_user);
EXPORT_SYMBOL(copy_in_user);
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index 2e87e82..3dbac23 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -33,14 +33,7 @@ extern int __get_user_bad(void);
extern int __put_kernel_bad(void);
extern int __put_user_bad(void);
-static inline long access_ok(int type, const void __user * addr,
- unsigned long size)
-{
- return 1;
-}
-
-#define put_user __put_user
-#define get_user __get_user
+long access_ok(int type, const void __user * addr, unsigned long size);
#if BITS_PER_LONG == 32
#define LDD_KERNEL(ptr) __get_kernel_bad();
@@ -254,6 +247,21 @@ struct exception_data {
#endif /* !__LP64__ */
+/* Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ */
+#define put_user(x,ptr) ({ \
+ __chk_user_ptr(ptr); \
+ likely(access_ok(0,ptr,sizeof(*(ptr)))) ? \
+ __put_user(x,ptr) : -EFAULT; })
+
+#define get_user(x,ptr) ({ \
+ __chk_user_ptr(ptr); \
+ likely(access_ok(0,ptr,sizeof(*(ptr)))) ? \
+ __get_user(x,ptr) : ({ x=0; -EFAULT;}); })
+
+
/*
* Complex access routines -- external declarations
*/