aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/traps.c12
-rw-r--r--arch/x86_64/lib/usercopy.c12
-rw-r--r--include/asm-x86_64/uaccess.h1
3 files changed, 18 insertions, 7 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index d345c712c6ca..2671fd46ea85 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -340,7 +340,8 @@ bad:
340void handle_BUG(struct pt_regs *regs) 340void handle_BUG(struct pt_regs *regs)
341{ 341{
342 struct bug_frame f; 342 struct bug_frame f;
343 char tmp; 343 long len;
344 const char *prefix = "";
344 345
345 if (user_mode(regs)) 346 if (user_mode(regs))
346 return; 347 return;
@@ -350,10 +351,15 @@ void handle_BUG(struct pt_regs *regs)
350 if (f.filename >= 0 || 351 if (f.filename >= 0 ||
351 f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 352 f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
352 return; 353 return;
353 if (__get_user(tmp, (char *)(long)f.filename)) 354 len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
355 if (len < 0 || len >= PATH_MAX)
354 f.filename = (int)(long)"unmapped filename"; 356 f.filename = (int)(long)"unmapped filename";
357 else if (len > 50) {
358 f.filename += len - 50;
359 prefix = "...";
360 }
355 printk("----------- [cut here ] --------- [please bite here ] ---------\n"); 361 printk("----------- [cut here ] --------- [please bite here ] ---------\n");
356 printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line); 362 printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
357} 363}
358 364
359#ifdef CONFIG_BUG 365#ifdef CONFIG_BUG
diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c
index db8abba1ad81..9bc2c295818e 100644
--- a/arch/x86_64/lib/usercopy.c
+++ b/arch/x86_64/lib/usercopy.c
@@ -109,14 +109,11 @@ unsigned long clear_user(void __user *to, unsigned long n)
109 * Return 0 on exception, a value greater than N if too long 109 * Return 0 on exception, a value greater than N if too long
110 */ 110 */
111 111
112long strnlen_user(const char __user *s, long n) 112long __strnlen_user(const char __user *s, long n)
113{ 113{
114 long res = 0; 114 long res = 0;
115 char c; 115 char c;
116 116
117 if (!access_ok(VERIFY_READ, s, n))
118 return 0;
119
120 while (1) { 117 while (1) {
121 if (res>n) 118 if (res>n)
122 return n+1; 119 return n+1;
@@ -129,6 +126,13 @@ long strnlen_user(const char __user *s, long n)
129 } 126 }
130} 127}
131 128
129long strnlen_user(const char __user *s, long n)
130{
131 if (!access_ok(VERIFY_READ, s, n))
132 return 0;
133 return __strnlen_user(s, n);
134}
135
132long strlen_user(const char __user *s) 136long strlen_user(const char __user *s)
133{ 137{
134 long res = 0; 138 long res = 0;
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 1bb8b8a24436..2892c4b7a28b 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -348,6 +348,7 @@ static inline int __copy_in_user(void __user *dst, const void __user *src, unsig
348long strncpy_from_user(char *dst, const char __user *src, long count); 348long strncpy_from_user(char *dst, const char __user *src, long count);
349long __strncpy_from_user(char *dst, const char __user *src, long count); 349long __strncpy_from_user(char *dst, const char __user *src, long count);
350long strnlen_user(const char __user *str, long n); 350long strnlen_user(const char __user *str, long n);
351long __strnlen_user(const char __user *str, long n);
351long strlen_user(const char __user *str); 352long strlen_user(const char __user *str);
352unsigned long clear_user(void __user *mem, unsigned long len); 353unsigned long clear_user(void __user *mem, unsigned long len);
353unsigned long __clear_user(void __user *mem, unsigned long len); 354unsigned long __clear_user(void __user *mem, unsigned long len);