[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: Jan Beulich <jbeulich@novell.com>

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Jan Beulich and committed by Linus Torvalds 5f1d189f 1b2f6304

+18 -7
+9 -3
arch/x86_64/kernel/traps.c
··· 340 void handle_BUG(struct pt_regs *regs) 341 { 342 struct bug_frame f; 343 - char tmp; 344 345 if (user_mode(regs)) 346 return; ··· 351 if (f.filename >= 0 || 352 f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 353 return; 354 - if (__get_user(tmp, (char *)(long)f.filename)) 355 f.filename = (int)(long)"unmapped filename"; 356 printk("----------- [cut here ] --------- [please bite here ] ---------\n"); 357 - printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line); 358 } 359 360 #ifdef CONFIG_BUG
··· 340 void handle_BUG(struct pt_regs *regs) 341 { 342 struct bug_frame f; 343 + long len; 344 + const char *prefix = ""; 345 346 if (user_mode(regs)) 347 return; ··· 350 if (f.filename >= 0 || 351 f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 352 return; 353 + len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1; 354 + if (len < 0 || len >= PATH_MAX) 355 f.filename = (int)(long)"unmapped filename"; 356 + else if (len > 50) { 357 + f.filename += len - 50; 358 + prefix = "..."; 359 + } 360 printk("----------- [cut here ] --------- [please bite here ] ---------\n"); 361 + printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line); 362 } 363 364 #ifdef CONFIG_BUG
+8 -4
arch/x86_64/lib/usercopy.c
··· 109 * Return 0 on exception, a value greater than N if too long 110 */ 111 112 - long strnlen_user(const char __user *s, long n) 113 { 114 long res = 0; 115 char c; 116 - 117 - if (!access_ok(VERIFY_READ, s, n)) 118 - return 0; 119 120 while (1) { 121 if (res>n) ··· 124 res++; 125 s++; 126 } 127 } 128 129 long strlen_user(const char __user *s)
··· 109 * Return 0 on exception, a value greater than N if too long 110 */ 111 112 + long __strnlen_user(const char __user *s, long n) 113 { 114 long res = 0; 115 char c; 116 117 while (1) { 118 if (res>n) ··· 127 res++; 128 s++; 129 } 130 + } 131 + 132 + long strnlen_user(const char __user *s, long n) 133 + { 134 + if (!access_ok(VERIFY_READ, s, n)) 135 + return 0; 136 + return __strnlen_user(s, n); 137 } 138 139 long strlen_user(const char __user *s)
+1
include/asm-x86_64/uaccess.h
··· 348 long strncpy_from_user(char *dst, const char __user *src, long count); 349 long __strncpy_from_user(char *dst, const char __user *src, long count); 350 long strnlen_user(const char __user *str, long n); 351 long strlen_user(const char __user *str); 352 unsigned long clear_user(void __user *mem, unsigned long len); 353 unsigned long __clear_user(void __user *mem, unsigned long len);
··· 348 long strncpy_from_user(char *dst, const char __user *src, long count); 349 long __strncpy_from_user(char *dst, const char __user *src, long count); 350 long strnlen_user(const char __user *str, long n); 351 + long __strnlen_user(const char __user *str, long n); 352 long strlen_user(const char __user *str); 353 unsigned long clear_user(void __user *mem, unsigned long len); 354 unsigned long __clear_user(void __user *mem, unsigned long len);