Commit 5f1d189f authored by Jan Beulich's avatar Jan Beulich Committed by Linus Torvalds

[PATCH] x86_64: Display meaningful part of filename during BUG()

When building in a separate objtree, file names produced by BUG() & Co. can
get fairly long; printing only the first 50 characters may thus result in
(almost) no useful information. The following change makes it so that rather
the last 50 characters of the filename get printed.
Signed-Off-By: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 1b2f6304
...@@ -340,7 +340,8 @@ bad: ...@@ -340,7 +340,8 @@ bad:
void handle_BUG(struct pt_regs *regs) void handle_BUG(struct pt_regs *regs)
{ {
struct bug_frame f; struct bug_frame f;
char tmp; long len;
const char *prefix = "";
if (user_mode(regs)) if (user_mode(regs))
return; return;
...@@ -350,10 +351,15 @@ void handle_BUG(struct pt_regs *regs) ...@@ -350,10 +351,15 @@ void handle_BUG(struct pt_regs *regs)
if (f.filename >= 0 || if (f.filename >= 0 ||
f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
return; return;
if (__get_user(tmp, (char *)(long)f.filename)) len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
if (len < 0 || len >= PATH_MAX)
f.filename = (int)(long)"unmapped filename"; f.filename = (int)(long)"unmapped filename";
else if (len > 50) {
f.filename += len - 50;
prefix = "...";
}
printk("----------- [cut here ] --------- [please bite here ] ---------\n"); printk("----------- [cut here ] --------- [please bite here ] ---------\n");
printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line); printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
} }
#ifdef CONFIG_BUG #ifdef CONFIG_BUG
......
...@@ -109,14 +109,11 @@ unsigned long clear_user(void __user *to, unsigned long n) ...@@ -109,14 +109,11 @@ unsigned long clear_user(void __user *to, unsigned long n)
* Return 0 on exception, a value greater than N if too long * Return 0 on exception, a value greater than N if too long
*/ */
long strnlen_user(const char __user *s, long n) long __strnlen_user(const char __user *s, long n)
{ {
long res = 0; long res = 0;
char c; char c;
if (!access_ok(VERIFY_READ, s, n))
return 0;
while (1) { while (1) {
if (res>n) if (res>n)
return n+1; return n+1;
...@@ -129,6 +126,13 @@ long strnlen_user(const char __user *s, long n) ...@@ -129,6 +126,13 @@ long strnlen_user(const char __user *s, long n)
} }
} }
long strnlen_user(const char __user *s, long n)
{
if (!access_ok(VERIFY_READ, s, n))
return 0;
return __strnlen_user(s, n);
}
long strlen_user(const char __user *s) long strlen_user(const char __user *s)
{ {
long res = 0; long res = 0;
......
...@@ -348,6 +348,7 @@ static inline int __copy_in_user(void __user *dst, const void __user *src, unsig ...@@ -348,6 +348,7 @@ static inline int __copy_in_user(void __user *dst, const void __user *src, unsig
long strncpy_from_user(char *dst, const char __user *src, long count); long strncpy_from_user(char *dst, const char __user *src, long count);
long __strncpy_from_user(char *dst, const char __user *src, long count); long __strncpy_from_user(char *dst, const char __user *src, long count);
long strnlen_user(const char __user *str, long n); long strnlen_user(const char __user *str, long n);
long __strnlen_user(const char __user *str, long n);
long strlen_user(const char __user *str); long strlen_user(const char __user *str);
unsigned long clear_user(void __user *mem, unsigned long len); unsigned long clear_user(void __user *mem, unsigned long len);
unsigned long __clear_user(void __user *mem, unsigned long len); unsigned long __clear_user(void __user *mem, unsigned long len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment