[Crash-utility] The problems when running SuSE 12 on VirtualBox

David Mair dmair at suse.com
Thu Nov 19 21:01:10 UTC 2015


On 11/19/2015 12:20 PM, Dave Anderson wrote:
> 
> 
> ----- Original Message -----
>> On 11/19/2015 08:37 AM, David Mair wrote:
>>> On 11/19/2015 07:45 AM, Dave Anderson wrote:
>>>
>>> Hi Dave,
>>>
>>>> ----- Original Message -----
>>> <snip>
>>>>
>>>>> (2) Execute "crash -d8" on physical machine will cause crash utility core
>>>>> dump.
>>>>
>>>> I can reproduce this, so I'll look into it.  It's related to the /dev/mem "test"
>>>> to determine whether the kernel was configured with CONFIG_STRICT_DEVMEM, where
>>>> it tries to read from pfn 257 (just above the CONFIG_STRICT_DEVMEM limit), but
>>>> gets into an infinite loop when used in conjunction with -d.
>>>>
>>>> Anyway, just continue to use /proc/kcore and you should be fine.
>>>
>>> This is the cause in readmem():
>>>
>>> switch(READMEM(...))
>>> {
>>> 	.
>>> 	.
>>> 	.
>>> case READ_ERROR:
>>> 	if (PRINT_ERROR_MESSAGE) ********** THIS ***********
>>> 	{
>>> 		causes a nested readmem() call before the goto gives it
>>> 		to the caller to deal with
>>> 	}
>>> 	goto readmem_error
>>> }
>>> 	.
>>> 	.
>>> 	.
>>> switch(error_handle)
>>> {
>>> 	case (RETURN_ON_ERROR):
>>> }
>>>
>>> The PRINT_ERROR_MESSAGE I assume is an escalation from -d 8 in this case.
>>>
>>
>> The whole switch_to_proc_kcore() probably shouldn't be conditional on
>> the presence of PRINT_ERROR_MESSAGE, only the actual error message
>> should be.
>>
>> Patch shortly.
>>
>> --
>> David.
> 
> Yeah, I agree.  It was done that way to catch the very first non-QUIET readmem()
> call from kernel_init(), and make the bait-and-switch right there.  Without the 
> CRASHDEBUG(x) override, it works as-is because the readmem() calls in 
> devmem_is_restricted() are purposely set to QUIET.  
> 
> So we're thinking something like this, right?:
> 
> diff --git a/memory.c b/memory.c
> index 824b3ae..2282ba9 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -2207,13 +2207,12 @@ readmem(ulonglong addr, int memtype, void *buffer, long size,
>                          goto readmem_error;
>  
>                 case READ_ERROR:
> -                        if (PRINT_ERROR_MESSAGE) {
> -                               if ((pc->flags & DEVMEM) && (kt->flags & PRE_KERNEL_INIT) &&
> -                                   devmem_is_restricted() && switch_to_proc_kcore())
> -                                       return(readmem(addr, memtype, bufptr, size,
> -                                               type, error_handle));
> +                       if ((pc->flags & DEVMEM) && (kt->flags & PRE_KERNEL_INIT) && 
> +                           !(error_handle & QUIET) && devmem_is_restricted() && switch_to_proc_kcore())
> +                               return(readmem(addr, memtype, bufptr, size,
> +                                       type, error_handle));
> +                       if (PRINT_ERROR_MESSAGE)
>                                 error(INFO, READ_ERRMSG, memtype_string(memtype, 0), addr, type);
> -                       }
>                          goto readmem_error;
>  
>                 case PAGE_EXCLUDED:
> 
> Works for me, and is better than hiding a recursive-call check in devmem_is_restricted().

That protects from nesting devmem_is_restricted() as long as
devmem_is_restricted() continues to do QUIET readmem()s but fails to
switch_to_proc_kcore() for QUIET readmem() at other random failing
addresses that could be fixed via /proc/kcore. QUIET isn't a global flag
only for being in devmem_is_restricted().

Here's mine, it's the kind of clumsy hardcore you were trying to avoid,
it's not thread or signal safe. I do feel the same concern you expressed
but I believe it does work for all failing QUIET readmem() cases.

diff --git a/memory.c b/memory.c
index 72218e7..71f1e47 100644
--- a/memory.c
+++ b/memory.c
@@ -319,6 +319,7 @@ static void dump_hstates(void);
 #define ASCII_UNLIMITED ((ulong)(-1) >> 1)

 static ulong DISPLAY_DEFAULT;
+static int IN_DEVMEM_IS_RESTRICTED;

 /*
  *  Verify that the sizeof the primitive types are reasonable.
@@ -338,6 +339,7 @@ mem_init(void)
                 error(FATAL, "pointer size: %d is not sizeof(long):
%d\n", sizeof(void *), sizeof(long));

         DISPLAY_DEFAULT = (sizeof(long) == 8) ? DISPLAY_64 : DISPLAY_32;
+        IN_DEVMEM_IS_RESTRICTED = FALSE;
 }


@@ -2204,13 +2206,13 @@ readmem(ulonglong addr, int memtype, void
*buffer, long size,
                         goto readmem_error;

 		case READ_ERROR:
-                        if (PRINT_ERROR_MESSAGE) {
-				if ((pc->flags & DEVMEM) && (kt->flags & PRE_KERNEL_INIT) &&
-				    devmem_is_restricted() && switch_to_proc_kcore())
-					return(readmem(addr, memtype, bufptr, size,
-						type, error_handle));
+                        if (PRINT_ERROR_MESSAGE)
 				error(INFO, READ_ERRMSG, memtype_string(memtype, 0), addr, type);
-			}
+
+			if ((pc->flags & DEVMEM) && (kt->flags & PRE_KERNEL_INIT) &&
+			    devmem_is_restricted() && switch_to_proc_kcore())
+				return(readmem(addr, memtype, bufptr, size,
+					type, error_handle));
                         goto readmem_error;

 		case PAGE_EXCLUDED:
@@ -2393,6 +2395,11 @@ devmem_is_restricted(void)
 	long tmp;
 	int restricted;

+	if (IN_DEVMEM_IS_RESTRICTED)
+		return FALSE;
+	IN_DEVMEM_IS_RESTRICTED = TRUE;
+
+	restricted = FALSE;

 	/*
 	 *  Check for pre-CONFIG_STRICT_DEVMEM kernels.
@@ -2401,11 +2408,9 @@ devmem_is_restricted(void)
 		if (machine_type("ARM") || machine_type("ARM64") ||
 		    machine_type("X86") || machine_type("X86_64") ||
 		    machine_type("PPC") || machine_type("PPC64"))
-			return FALSE;
+			goto end_devmem_is_restricted;
 	}

-	restricted = FALSE;
-
 	if (STREQ(pc->live_memsrc, "/dev/mem")) {
 	    	if (machine_type("X86") || machine_type("X86_64")) {
 			if (readmem(255*PAGESIZE(), PHYSADDR, &tmp,
@@ -2429,6 +2434,9 @@ devmem_is_restricted(void)
 			    "source.\n");
 	}

+end_devmem_is_restricted:
+	IN_DEVMEM_IS_RESTRICTED = FALSE;
+
 	return restricted;
 }





More information about the Crash-utility mailing list